From 8eec96a8fc406853ecb35c6e6568639fb7d74511 Mon Sep 17 00:00:00 2001 From: Maxim Likhachev Date: Fri, 13 Dec 2019 22:34:19 +0300 Subject: [PATCH] Code2Graph v2.0 --- COPYING | 674 +++++++++++++++++++++ CoC.md | 7 + README.md | 62 ++ code2graph | 1936 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ example.png | Bin 0 -> 31935 bytes robodoc.rc | 206 +++++++ 6 files changed, 2885 insertions(+) create mode 100644 COPYING create mode 100644 CoC.md create mode 100644 README.md create mode 100755 code2graph create mode 100644 example.png create mode 100644 robodoc.rc diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/CoC.md b/CoC.md new file mode 100644 index 0000000..55df6a7 --- /dev/null +++ b/CoC.md @@ -0,0 +1,7 @@ +# Go Fuck Yourself + +Offended? Go away. We don't need people who are offended because of a stranger on the internet. +Not offended? You're welcome to contribute. + +© Copyright 2015 [WTFCoC Consortium Committee](https://github.com/mniip/wtfcoc). + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c59622b --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# Code2Graph + + ______ __ ___ ______ __ + / ____/___ ____/ /__ /__ \ / ____/________ ____ / /_ + / / / __ \/ __ / _ \__/ // / __/ ___/ __ `/ __ \/ __ \ + / /___/ /_/ / /_/ / __/ __// /_/ / / / /_/ / /_/ / / / / + \____/\____/\__,_/\___/____/\____/_/ \__,_/ .___/_/ /_/ + A graph of Tcl code /_/ v 2.0 + +Построение графа вызовов процедур для исходного кода на языке программирования Tcl. + +## Зависимости + +Программа зависит от следующих пакетов: + +- package Tcldot - Пакет предоставляет доступ к API graphviz для создания dot-файла. +- package struct::list - Процедуры для работы со списками. + +## Использование + +**code2graph** [опции...] + +- -h - вывод справки. +- -i - входной файл с Tcl-кодом. +- -t - подпись изображения. +- -o - выходной файл. По умолчанию осуществляется вывод на экран. +- -f - формат. По умолчанию: dot. Может быть ps, mif, hpgl, plain, dot, gif, ismap. + +## Пример использования + +Построение графа вызовов процедур для данной программы: + + $ code2graph -t "Code2Graph" -i code2graph.tcl -f gif -o graph.gif + +## Известные проблемы + +- Программа не работает на проектах, разделенных на несколько файлов. +- Код, помещенный в блок namespace eval name {<...>}, выполняется при загрузке в защищенный интерпретатор. +- Команды из namespace ensemble {<...>} не учитываются. +- Глобальные переменные не выводятся, т.к. верхний уровень не выполняется. +- Псевдонимы разделяются на несколько записей в узлах типа record. + +## Пример визуалицации ([frets](https://code.envrm.info/src/frets/)) + +![](https://code.envrm.info/src/Code2Graph/raw/branch/master/example.png) + +# Лицензия + +> Copyright (C) 2011-2019, Maxim Lihachev, +> +> 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, version 3. +> +> 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 . + diff --git a/code2graph b/code2graph new file mode 100755 index 0000000..88a8590 --- /dev/null +++ b/code2graph @@ -0,0 +1,1936 @@ +#!/usr/bin/env tclsh + +#****h* program/code2graph **************************************************** +# +# NAME +# ______ __ ___ ______ __ +# / ____/___ ____/ /__ /__ \ / ____/________ ____ / /_ +# / / / __ \/ __ / _ \__/ // / __/ ___/ __ `/ __ \/ __ \ +# / /___/ /_/ / /_/ / __/ __// /_/ / / / /_/ / /_/ / / / / +# \____/\____/\__,_/\___/____/\____/_/ \__,_/ .___/_/ /_/ +# A graph of Tcl code /_/ v 2.0 +# +# COPYRIGHT +# Copyright (C) 2011-2019, Maxim Lihachev, +# +# LICENSE +# +# 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, version 3. +# +# 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 . +# +# Full license: +# href:COPYING +# +# VERSION +# 2.0 +# +# DESCRIPTION +# Программа предназначена для визуализации вызовов процедур в скриптах, +# написанных на языке Tcl. +# +# USAGE +# code2graph [options] +# +# ARGUMENTS +# * -h - вывод справки +# * -i - входной файл с Tcl-кодом +# * -t - подпись изображения +# * -o - выходной файл. По умолчанию осуществляется вывод на экран +# * -f - формат. По умолчанию: dot. +# Может быть ps, mif, hpgl, plain, dot, gif, ismap +# +# STRUCTURE +# +# |exec ../code2graph.tcl -i ../code2graph.tcl -t Code2Graph -o main.gv -f dot +# |dotfile ./doc/main.gv +# +# CHANGELOG +# +# * v2.0 +# - обработка файлов с исходным кодом в защищенных интерпретаторах +# - анализ пространств имен +# - анализ псевдонимов +# - вывод графа в различных форматах +# * v1.0 +# - работа с простейшим проектами +# +# |exec cd .. && git log > ./doc/git-log.txt +# href:git-log.txt +# +# TODO +# * Обработка команды load +# * Ссылка на в узлах типа "record" +# +# BUGS +# * Программа не работает на проектах, разделенных на несколько файлов +# * Код, помещенный в блок namespace eval name {<...>}, выполняется при +# загрузке в защищенный интерпретатор +# * Команды из namespace ensemble {<...>} не учитываются +# * Глобальные переменные не выводятся, т.к. верхний уровень не выполняется +# * addedge ::clock (?) +# * Псевдонимы разделяются на несколько записей в узлах типа record +# +# USER HELP +# +# |exec doctools2man nroff ../man/man ../man/man.man +# |exec doctools2man html ../man/man ../man/man.html +# +# href:../man/man.html +# +#****************************************************************************** + +#****p* code2graph/packages *************************************************** +# +# PACKAGES +# * struct::list - процедуры для работы со списками (map/fold/filter/...) +# * Tcldot - процедуры для работы с dot-структурой +# +#****************************************************************************** +package require struct::list +package require Tcldot + +#------------------------------------------------------------------------------ + +#****n* code2graph/code ******************************************************* +# +# NAMESPACE +# code - процедуры для работы с исходным кодом на языке Tcl +# +#****************************************************************************** +namespace eval code { + #****f* code/findProcCalls + # + # NAME + # code::findProcCalls - + # + # DESCRIPTION + # + # USAGE + # code::findProcCalls string + # + # ARGUMENTS + # * string + # + # RESULT + # + # EXAMPLE + # code::findProcCalls + # + # SOURCE + # + proc findProcCalls {interp namespace line} { + set rawCalls [regexp -all -inline -- {(?x) + (?:^\s* # Начальные пробелы + |\[ # [proc args] + |\{ # switch/map/filter { proc args } + |\" # switch/map/filter " proc args " + |; # proc1 args; proc2 args; proc3 + |eval # eval proc args + |\[list\s+ # uplevel 1 [list proc args] + |(?:struct::)? # struct::list map|fold|filter + (?:list)? # struct::list map|fold|filter + (?:::L)?\s* # struct::list::L(map|fold|filter) + (?:map|fold|filter) # map|fold|filter command + \s+\{? # map|fold|filter { command args } + |catch\s+\{?)\s* # catch {proc args} var + ([\w:'._?!<>-]+) # Имя процедуры + } $line] + + set procedures {} + foreach {_raw command} $rawCalls { + lappend procedures [proc::fullName $interp $command $namespace] + } + return $procedures + } + #***** + + #****a* code/package? + # + # NAME + # code::package? + # + # DESCRIPTION + # + # USAGE + # code::package? string + # + # ARGUMENTS + # + # TODO + # * Включить в процедуру [code::commandIs] + # + # EXAMPLE + # + # SOURCE + # + interp alias {} package? {} regexp {^\s*package\s+require\s+([^\s]*)\s*$} + #***** + + #****a* code/source? + # + # NAME + # code::source? + # + # DESCRIPTION + # + # USAGE + # code::source? string + # + # ARGUMENTS + # + # EXAMPLE + # + # TODO + # * Включить в процедуру [code::commandIs] + # + # BUGS + # * Имя файла не может содержать ";" + # + # SOURCE + # + interp alias {} source? {} regexp {^\s*source\s+([^;]+)(?:;.*)?\s*$} + #***** + + #****f* code/aliases + # + # NAME + # code::aliases - получение информации о псевдонимах команд + # + # DESCRIPTION + # Процедура получает информацию о псевдонимах команд, созданных + # файлом с исходным кодом в интерпретаторе $interp. Информация о + # псевдонимах заносится в подграф "ALIASES". + # + # USAGE + # code::aliases graph interp + # + # ARGUMENTS + # * graph - граф, в который требуется добавить информацию + # * interp - интерпретатор + # + # RESULT + # Добавление в граф $graph информации о псевдонимах команд + # + # |dot start + # digraph G { + # subgraph cluster_1 { + # label="ALIASES" + # + # node1 [label="alias1"] + # node2 [label="alias2"] + # } + # } + # |dot end + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # SOURCE + # + proc aliases {graph interp} { + set aliases [$interp eval {interp aliases}] + + if {$aliases ne {}} { + set aliasesSubgraph [dot::addsubgraph $graph aliases_graph] + + foreach alias $aliases { + #TODO: ГРЯЗНЫЙ ХАК! + if {[regexp {.*(clock|mathfunc|msgbox).*} $alias -> all] eq 0} { + set command [$interp eval [list interp alias {} $alias]] + + set node [$aliasesSubgraph addnode ::aliases::$alias \ + label [dot::label ::aliases::$alias [list $command]] \ + {*}$dot::style(aliases_node)] + + dot::addedges $node -> [list::delete :: from [findProcCalls $interp :: $command]] + } + } + } + } + #***** + + #****f* code/commandIs + # + # NAME + # code::commandIs - + # + # DESCRIPTION + # + # USAGE + # code::commandIs type command + # + # ARGUMENTS + # * type + # * command + # + # RESULT + # + # EXAMPLE + # code::commandIs + # + # SOURCE + # + proc commandIs {type command} { + switch $type { + alias {set regexp {^\s*interp\s+alias\s+.*$}} + blank {set regexp {^[[:space:]]*$}} + commentary {set regexp {^\s*#.*$}} + namespace {set regexp {^\s*namespace\s+eval\s+\w+.*$}} + package {set regexp {^\s*package\s+require\s+([^\s]*)\s*}} + proc {set regexp {^\s*proc\s+([\w:'._?!<>-]+).*$}} + source {set regexp {^\s*source\s+([^;]+)\s*(?:;.*)?\s*$}} + default {error "error: usage: commandIs (alias|blank|commentary|namespace|package|proc|source) command"} + } + + if {[regexp -- $regexp $command -> match]} { + return true + } else { + return false + } + } + #***** + + #****f* code/toplevel + # + # NAME + # code::toplevel - вызовы верхнего уровня + # + # DESCRIPTION + # Процедура получения вызовов верхнего уровня. Возвращает значение + # переменной toplevel, созданной при инициализации интерпретатора + # + # USAGE + # code::toplevel interp + # + # ARGUMENTS + # * graph + # * interp - интерпретатор с загруженным исходным текстом + # + # RESULT + # Список процедур, вызываемых из глобального пространства имен + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # SOURCE + # + proc toplevel {graph interp} { + dot::addedges [$graph addnode [file tail $interp] {*}$dot::style(toplevel)] \ + -> [code::proc::localCalls $interp :: [$interp eval {set toplevel}]] + } + #***** + + #****f* code/packages + # + # NAME + # packages - получение списка используемых пакетов + # + # DESCRIPTION + # Процедура извлекает список используемых пакетов (загружаемых с + # помощью команды [package require ]) из переменной + # $packages интерпретатора $interp + # + # USAGE + # packages interp + # + # ARGUMENTS + # * interp - имя интерпретатора + # + # RESULT + # Список пакетов + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # SOURCE + # + proc packages {graph interp} { + set pack [dot::addsubgraph $graph packages_graph] + foreach package [$interp eval {set packages}] { + $pack addnode $package {*}$dot::style(packages_node) + } + } + #***** + + #****f* code/defaultElem? + # + # NAME + # defaultElem? - + # + # DESCRIPTION + # + # USAGE + # defaultElem? interp + # + # ARGUMENTS + # * interp + # + # RESULT + # + # EXAMPLE + # defaultElem? + # + # SOURCE + # + proc defaultElem? {type interp elem} { + expr {$elem in [$interp eval [list set default[string totitle ${type}]s]]} + } + #***** + + #****n* code/namespace ************************************************ + # + # NAMESPACE + # code::namespace - процедуры для работы с пространствами имен + # + #********************************************************************** + namespace eval namespace { + #****f* namespace/children + # + # NAME + # code::namespace::children - получение дочерних + # пространств имен + # + # DESCRIPTION + # Процедура получает список дочерних пространств имен. Если + # переданное для поиска пространство имен является + # пустым списком, то дочерним считается глобальное + # пространство имен :: + # + # USAGE + # code::namespace::children namespace + # + # ARGUMENTS + # * namespace - корневое для поиска пространство имен + # + # RESULT + # Список дочерних пространств имен + # + # EXAMPLE + # code::namespace::children {} -> :: + # code::namespace::children :: -> ::tcl + # + # SOURCE + # + proc children {namespace} { + if {$namespace ne {}} { + return [namespace children $namespace] + } else { + return :: + } + } + #***** + + #****f* namespace/variables + # + # NAME + # code::namespace::variables - переменные пространства имен + # + # DESCRIPTION + # Процедура получает переменные, определенные в пространстве + # имен $namespace. + # + # USAGE + # code::namespace::variables graph interp namespace + # + # ARGUMENTS + # * grpah - граф пространства имен + # * interp - интерпретатор с загруженным исходным кодом + # * namespace - пространство имен для поиска переменных + # + # RESULT + # Список переменных + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # BUGS + # * Не выдает переменные, определенные в глобальном + # пространстве имен (::), т.к. код высшего уровня не + # выполняется при загрузке файла в интерпретатор. + # + # SOURCE + # + proc variables {graph interp namespace} { + set variables [list::delete [$interp eval {set defaultVars}] \ + from [$interp eval [list info vars ${namespace}::*]]] + + if {$variables ne ""} { + set graphVars [dot::addsubgraph $graph variables_graph] + foreach var $variables { + $graphVars addnode $var {*}$dot::style(variables_node) + } + } + } + #***** + + #****f* namespace/withoutDefaults + # + # NAME + # code::namespace::withoutDefaults - + # + # DESCRIPTION + # + # USAGE + # code::namespace::withoutDefaults interp namespaces + # + # ARGUMENTS + # * interp + # * namespaces + # + # RESULT + # + # EXAMPLE + # code::namespace::withoutDefaults + # + # SOURCE + # + proc withoutDefaults {interp list {type namespace}} { + list::filterNot "code::defaultElem? $type $interp" $list + } + #***** + + #****f* namespace/analyzeAll + # + # NAME + # code::namespace::analyzeAll - + # + # DESCRIPTION + # + # USAGE + # code::namespace::analyzeAll interp ?parentNamespace {}? + # + # ARGUMENTS + # * interp + # * ?parentNamespace {}? + # + # BUGS + # * Переменные пространств имен располагаются вертикально, + # т.к. graphviz не позволяет указывать расположение + # элементов (опция rankdir) для каждого подграфа, поэтому + # весь граф оказывается неоправданно вытянутым по + # вертикали. + # + # RESULT + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # EXAMPLE + # code::namespace::analyzeAll + # + # SOURCE + # + proc analyzeAll {graph interp {parentNamespace {}}} { + foreach ns [withoutDefaults $interp \ + [$interp eval \ + [list namespace_children $parentNamespace]] + ] { + set graphNS [dot::addsubgraph $graph namespace label $ns] + + variables $graphNS $interp $ns + childrenProcs $graphNS $interp $ns + + #Вложенные пространства имен + if {[$interp eval [list namespace_children $ns]] ne ""} { + analyzeAll $graphNS $interp $ns + } + } + } + #***** + + #****f* namespace/childrenProcs + # + # NAME + # code::namespace::childrenProcs - + # + # DESCRIPTION + # + # USAGE + # code::namespace::childrenProcs interp ?namespace {::}? + # + # ARGUMENTS + # * interp ?namespace {::}? + # + # RESULT + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # EXAMPLE + # code::namespace::childrenProcs + # + # SOURCE + # + proc childrenProcs {graph interp {namespace {::}}} { + foreach pr [withoutDefaults $interp \ + [$interp eval \ + [list info procs ${namespace}::*]] proc\ + ] { + set args [$interp eval [list proc_args $pr]] + + set graphProc [$graph addnode "$pr" label \ + [dot::label $pr $args] {*}$dot::style(proc)] + + dot::addedges $graphProc -> [code::proc::localCalls \ + $interp $namespace \ + [$interp eval [list info body $pr]]] + } + } + #***** + } + + #****n* code/proc ***************************************************** + # + # NAMESPACE + # code::proc - процедуры для работы с процедурами + # + #********************************************************************** + namespace eval proc { + #****f* proc/fullName + # + # NAME + # code::proc::fullName - полное имя процедуры + # + # DESCRIPTION + # Процедура получает полное имя процедуры, включающее все + # пространства имен, в которых объявленая процедура. Если + # процедура является псевдонимом, то к имени прибавляется + # приставка "::aliases::", необходимая для правильной + # организации связей процедур на графе. + # + # USAGE + # code::proc::fullName interp proc ?namespace {::}? + # + # ARGUMENTS + # * interp - интерпретатор с исходным кодом + # * proc - имя процедуры + # * ?namespace {::}? - начальное для поиска пространство + # имен. По умолчанию процедура ищется в + # глобальном пространстве имен (::). + # + # RESULT + # Полное имя процедуры, включающее все пространства имен + # + # EXAMPLE + # code::proc::fullName {} fullName :: -> ::code::proc::fullName + # + # SOURCE + # + proc fullName {interp proc {namespace ::}} { + #Поиск команды среди псевдонимов + set alias [lsearch [$interp eval {interp aliases {}}] $proc] + + if {$alias >= 0} { + return ::aliases::$proc + } + + #Поиск команды в текущем пространстве имен + set command [$interp eval [list info procs ${namespace}::${proc}]] + + if {$command eq ""} { + #Поиск команды в глобальном пространстве имен + return ::[$interp eval [list info procs $proc]] + } else { + return ::$command + } + } + #***** + + #****f* proc/args + # + # NAME + # code::proc::args - получение аргументов процедуры + # + # DESCRIPTION + # Процедура получает список аргументов по имени процедуры. + # От стандартной [info args $procname] отличается тем, что + # результат содержит значения аргументов по умолчанию. + # + # USAGE + # code::proc::args procname + # + # ARGUMENTS + # * procname - имя процедуры + # + # RESULT + # Список аргументов процедуры + # + # EXAMPLE + # code::proc::args procname -> arg1 ?arg2 default? ?arg3 {}? + # + # SOURCE + # + proc args {procname} { + set arglist {} + + foreach arg [info args $procname] { + if {[info default $procname $arg default]} { + lappend arglist "? ${arg} (${default}) ?" + } else { + lappend arglist $arg + } + } + return $arglist + } + #***** + + #****f* proc/localCalls + # + # NAME + # code::proc::localCalls - + # + # DESCRIPTION + # + # USAGE + # code::proc::localCalls interp namespace body + # + # ARGUMENTS + # * interp + # * namespace + # * body + # + # RESULT + # + # EXAMPLE + # localCalls + # + # SOURCE + # + proc localCalls {interp namespace body} { + set result {} + foreach line [split $body "\n"] { + lappend result {*}[code::findProcCalls $interp $namespace $line] + } + #Без :: + return [list::delete {::} from [lsort -unique $result]] + } + #***** + } + +} + +#****n* code2graph/sourcefile ************************************************* +# +# NAMESPACE +# sourcefile +# +#****************************************************************************** +namespace eval sourcefile { + #****f* sourcefile/analyze + # + # NAME + # sourcefile::analyze - + # + # DESCRIPTION + # + # USAGE + # sourcefile::analyze filename + # + # ARGUMENTS + # * filename + # + # RESULT + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # EXAMPLE + # sourcefile::analyze + # + # SOURCE + # + proc analyze {graph filename} { + loadFileToInterp $graph $filename + + set fileSubgraph [dot::addsubgraph $graph file label [file tail $filename]] + + code::packages $fileSubgraph $filename + code::aliases $fileSubgraph $filename + code::toplevel $fileSubgraph $filename + + code::namespace::analyzeAll $fileSubgraph $filename + } + #***** + + #****f* sourcefile/loadFileToInterp + # + # NAME + # sourcefile::loadFileToInterp - + # + # DESCRIPTION + # + # USAGE + # sourcefile::loadFileToInterp filename + # + # ARGUMENTS + # * filename + # + # RESULT + # + # EXAMPLE + # sourcefile::loadFileToInterp + # + # SOURCE + # + proc loadFileToInterp {graph filename} { + #Создание интерпретатора + interp::init $filename + + #Построчное чтение файла + foreachTclCommand command $filename { + if {[code::commandIs namespace $command] \ + || [code::commandIs proc $command] \ + || [code::commandIs alias $command] + } { + $filename eval $command + } elseif {[source? $command -> sourceFile]} { + readSource $graph $filename $sourceFile + } elseif {[package? $command -> packageName]} { + $filename eval [list lappend packages $packageName] + } elseif { ![code::commandIs commentary $command] \ + && ![code::commandIs blank $command]} { + $filename eval [list append toplevel "\n$command"] + } + } + } + #***** + + #****f* sourcefile/readSource + # + # NAME + # sourcefile::readSource - + # + # DESCRIPTION + # + # USAGE + # sourcefile::readSource sourcefile + # + # ARGUMENTS + # * sourcefile + # + # RESULT + # + # EXAMPLE + # sourcefile::readSource + # + # SOURCE + # + proc readSource {graph interp sourceString} { + regsub -- {\[info\s+script\]} $sourceString [$interp eval {set filename}] sourceString + set sourceFile [$interp eval [list return [subst $sourceString]]] + analyze $graph $sourceFile + } + #***** + + #****c* sourcefile/foreachTclCommand + # + # NAME + # sourcefile::foreachTclCommand - выполнение пользовательских команд для каждой + # tcl-команды в файле + # + # DESCRIPTION + # Процедура выполняет блок кода для каждой команды tcl в файле + # $filename. Каждая команда присваивается пользовательской + # переменной $var. Блок кода выполняется на уровень выше (в + # вызывающей данную процедуру процедуре). + # + # USAGE + # sourcefile::foreachTclCommand var filename code + # + # ARGUMENTS + # * var - переменная для хранения команд + # * filename - файл, содержащий tcl-код + # * code - блок кода + # + # RESULT + # Выполнение блока кода $code в вышележащем уровне для каждой + # tcl-команды из файла $filename + # + # EXAMPLE + # #Вывод всех полных команд с нумерацией + # foreachTclCommand command filename.tcl { + # puts "[incr index]> $command" + # } + # + # SOURCE + # + proc foreachTclCommand {var filename code} { + #Открытие файла исходного кода + if {[catch {open $filename r} fileIN]} { + error $fileIN + } + + upvar 1 $var line + + #Выполнение каждой команды уровнем выше + while {[set line [readCompleteTclCommand $fileIN]] != 0} { + uplevel 1 $code + } + + close $fileIN + } + #***** + + #****f* sourcefile/readCompleteTclCommand + # + # NAME + # sourcefile::readCompleteTclCommand - чтение tcl-процедуры из потока + # + # DESCRIPTION + # Процедура чтения tcl-процедуры из потока данных. + # + # USAGE + # sourcefile::readCompleteTclCommand stream ?code? + # + # ARGUMENTS + # * stream - поток данных (указатель на файл) + # * ?code? - прочитанные данные - часть команды + # + # RESULT + # tcl-команда + # + # SIDE EFFECTS + # Указатель позиции чтения потока $stream устанавливается в новую + # позицию + # + # SOURCE + # + proc readCompleteTclCommand {stream {code {}}} { + while {[gets $stream line] >= 0} { + append code "\n$line" + + if {[info complete $code]} { + return $code + } + } + return 0 + } + #***** +} + +#****n* code2graph/interp ***************************************************** +# +# NAMESPACE +# interp - процедуры для работы с интерпретаторами +# +#****************************************************************************** +namespace eval interp { + #****f* interp/init + # + # NAME + # interp::init - создание интерпретатора + # + # DESCRIPTION + # Процедура создания интерпретатора для загрузки исходного кода. + # Инициализирует необходимые переменные и загружает следующие + # процедуры: namespace::children под именем namespace_children + # и proc::args под именем proc_args + # + # USAGE + # interp::init interp + # + # ARGUMENTS + # * interp - имя интерпретатора + # + # RESULT + # Интерпретатор interp с инициализированными переменными + # + # SIDE EFFECTS + # Интерпретатор создается в глобальном пространстве имен + # + # EXAMPLE + # interp::init filename.tcl + # + # VARIABLES + # * filename - полный путь к загружаемому файлу + # * defaultAliases - автоматически созданные псевдонимы + # * defaultVars - автоматически созданные переменные + # (::tcl_platform, ...) + # * defaultProcs - автоматически созданные процедуры + # (::unknown, ::auto_load, ...) + # * defaultNamespaces - автоматически созданные пространства имен + # (::tcl) + # * packages - переменная для сохранения информации об + # используемых пакетах + # * toplevel - переменная для сохранения глобальных + # вызовов, которые не должны выполняться в + # интерпретаторе + # + # SOURCE + # + proc init {interp} { + interp create $interp -safe + + loadProc code::namespace::children in $interp as namespace_children + loadProc code::proc::args in $interp as proc_args + + $interp eval {proc unknown {args} {}} + + $interp eval [list set filename [file normalize $interp]] + + #TODO: Выполнять после загрузки файла + $interp eval {set defaultAliases [interp aliases]} + $interp eval {set defaultProcs [info procs ::*]} + $interp eval {set defaultNamespaces [namespace children ::]} + $interp eval {set packages {}} + $interp eval {set toplevel {}} + + $interp eval {set defaultVars [concat ::defaultVars ::errorCode ::auto_index [info vars ::*]]} + } + #***** + + #****f* interp/loadProc + # + # NAME + # interp::loadProc - + # + # DESCRIPTION + # + # USAGE + # interp::loadProc procname _in interp _as newname + # + # ARGUMENTS + # * procname + # * _in + # * interp + # * _as + # * newname + # + # RESULT + # + # WARNINGS + # Зависимости не учитываются. Команды, вызываемые загружаемой + # процедуры, должны быть доступны в интерпретаторе. + # + # EXAMPLE + # interp::loadProc + # + # SOURCE + # + proc loadProc {procname _in interp _as newname} { + $interp eval [list proc $newname [code::proc::args $procname] \ + [info body $procname]] + } + #***** +} + +#****n* code2graph/list ******************************************************* +# +# NAMESPACE +# list +# +#****************************************************************************** +namespace eval list { + #****f* list/delete + # + # NAME + # list::delete - + # + # DESCRIPTION + # + # USAGE + # list::delete list1 _from list2 + # + # ARGUMENTS + # * list1 _from list2 + # + # RESULT + # + # EXAMPLE + # list::delete + # + # SOURCE + # + proc delete {list1 _from list2} { + set result {} + foreach elem $list2 { + if {[lsearch $list1 $elem] == -1} { + lappend result $elem + } + } + return $result + } + #***** + + #****f* list/filterNot + # + # NAME + # list::filterNot - + # + # DESCRIPTION + # + # USAGE + # list::filterNot cmd list + # + # ARGUMENTS + # * cmd list + # + # RESULT + # + # EXAMPLE + # list::filterNot + # + # SOURCE + # + proc filterNot {cmd list} { + struct::list filterfor elem $list {![eval $cmd $elem]} + } + #***** +} + +#****n* code2graph/dot ******************************************************** +# +# NAMESPACE +# dot - процедуры для работы с dot-графом +# +#****************************************************************************** +namespace eval dot { + #****v* dot/clusterIndex + # + # VARIABLE + # dot::clusterIndex - порядковый номер последнего подграфа типа cluster + # + # INIT VALUE + # 0 + # + # USED BY + # dot::cluster + # + # SOURCE + # + variable clusterIndex 0 + #***** + + #****v* dot/edges + # + # VARIABLE + # dot::edges - список связей между элементами графа + # + # INIT VALUE + # {} - пустой список + # + # USED BY + # dot::addedge + # dot::addedges + # dot::makeEdges + # + # SOURCE + # + variable edges {} + #***** + + #****s* dot/settings + # + # DESCRIPTION + # Значения настроек графа по умолчанию: + # * format - формат вывода графа. По умолчанию - dot + # * input - файл исходного кода + # * title - описание изображения + # * output - выходной файл. По умолчанию вывод осуществляется на терминал + # + # SOURCE + # + array set settings { + format dot + input {} + output stdout + title {} + } + #***** + + #****s* dot/style + # + # DESCRIPTION + # Стандартные настройки отображения элементов графа: + # + # |dot start + # digraph G { + # graph [ + # rankdir = LR, + # center = true, + # fontsize = 52 + # ]; + # + # subgraph cluster_1 { + # graph [style=solid, color=black]; + # + # node4 [ + # label = "toplevel", + # color = lightblue2, + # style = filled, + # shape = doublecircle + # ] + # + # subgraph cluster_2 { + # graph [ + # label = file, + # color = black, + # fontsize = 24, + # style = dashed, + # shape = folder + # ] + # + # subgraph cluster_3 { + # graph [ + # label = ALIASES, + # color = red, + # shape = box + # fontsize = 14 + # ] + # alias [ + # label = " alias | command", + # color = red, + # shape = record, + # style = rounded + # ] + # } + # + # subgraph cluster_4 { + # graph [ + # label = PACKAGES, + # color = blue, + # style = solid, + # shape = rect + # fontsize = 14 + # ] + # package [ + # label = package, + # color = blue, + # style = solid, + # shape = folder + # ] + # } + # + # subgraph cluster_5 { + # graph [ + # label = namespace, + # color = black, + # fontsize = 18, + # fontcolor = darkgreen, + # style = dashed, + # shape = folder + # ] + # + # subgraph cluster_6 { + # graph [ + # label = "VARIABLES", + # color = magenta, + # fontsize = 12, + # fontcolor = black, + # shape = box + # ] + # variable [ + # label = variable, + # color = magenta, + # shape = note, + # fontsize = 12 + # ] + # } + # + # proc [ + # label = " procedure | argument 1 | argument 2 | ...", + # shape = record, + # style = rounded, + # color = darkolivegreen3, + # fontsize = 14 + # ] + # } + # } + # } + # label = "Title" + # } + # |dot end + # + # BUGS + # * Graphviz текущей версии не позволяет указывать форму подграфов + # (shape), поэтому они отображаются прямоугольниками + # + # SOURCE + # + array set style { + digraph { + rankdir LR + center true + fontsize 52 + } + + namespace { + color black + style dashed + shape folder + fontsize 18 + fontcolor darkgreen + } + + file { + color black + style dashed + shape folder + fontsize 24 + } + + proc { + shape record + style rounded + color darkolivegreen3 + fontsize 14 + } + + toplevel { + shape doublecircle + style filled + color lightblue2 + } + + packages_graph { + label "PACKAGES" + color blue + style solid + shape rect + fontsize 14 + } + + packages_node { + color blue + style solid + shape folder + } + + variables_graph { + label "VARIABLES" + color magenta + fontsize 12 + fontcolor black + shape box + } + + variables_node { + color magenta + shape note + fontsize 12 + height 0.010 + } + + aliases_graph { + label "ALIASES" + color red + shape box + fontsize 14 + } + + aliases_node { + color red + style rounded + shape record + } + } + #***** + + #****f* dot/generate + # + # NAME + # dot::generate - создание графа из файла с исходным кодом + # + # DESCRIPTION + # Начальная процедура, запускающая процесс создания графа вызовов из + # файла с исходным кодом. + # + # USAGE + # dot::generate filename description format output + # + # ARGUMENTS + # * filename - файл с исходным кодом + # * description - описание, которое будет являться подписью графа + # * format + # * output + # + # RESULT + # Граф в формате dot + # + # SIDE EFFECTS + # Созданный граф выводится на экран или в файл, если указана опция -о + # + # SOURCE + # + proc generate {filename description format output} { + set graph [dot::digraph $description] + + sourcefile::analyze $graph $filename + dot::makeEdges + + if {$output ne "stdout"} { + if {[catch {open $output w} output]} { + error $output + } + } + + $graph write $output $format + } + #***** + + #****f* dot/digraph + # + # NAME + # dot::digraph - создание графа типа + # + # DESCRIPTION + # Процедура создает граф, используя стандартные настройки + # (переменная $dot::style(digraph)). + # + # USAGE + # dot::digraph label + # + # ARGUMENTS + # * label - подпись под изображением + # + # USED VARIABLES + # * $dot::style(digraph) - настройки графа + # + # RESULT + # Граф graphviz + # + # SIDE EFFECTS + # Создается глобальный граф graphviz + # + # EXAMPLE + # dot::digraph "Graphviz" -> + # + # digraph G { + # + # + # label = "Graphviz" + # } + # + # SOURCE + # + proc digraph {label} { + dotnew digraph label $label {*}$::dot::style(digraph) + } + #***** + + #****f* dot/addsubgraph + # + # NAME + # dot::addsubgraph - добавление подграфа в граф + # + # DESCRIPTION + # Процедура создает подграф в переданном графе. Тип подграфа - + # cluster, позволяющий создавать вложенные подграфы. Порядковый + # номер подграфа вычисляется с помощью процедуры [dot::cluster]. + # + # USAGE + # dot::addsubgraph graph type ?args? + # + # ARGUMENTS + # * graph - родительский граф + # * type - тип подграфа, от которого зависит набор настроек + # (переменная $dot::style($type)) + # * args - пользовательские настройки подграфа (label, color, + # shape и т.д.) + # + # RESULT + # Подграф graphviz типа cluster + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # EXAMPLE + # set graph [dot::digraph "Graphviz"] + # dot::addsubgraph $graph variables_graph label VARIABLES + # dot::addsubgraph $graph aliases_graph label ALIASES + # + # -> + # + # digraph G { + # subgraph cluster_1 { + # graph [ + # label = "VARIABLES", + # color = magenta, + # fontsize = 12, + # fontcolor = black, + # shape = box + # ] + # var [shape=plaintext] + # } + # + # subgraph cluster_2 { + # graph [ + # label = "ALIASES", + # color = red, + # fontsize = 14, + # fontcolor = black, + # shape = box, + # style = dashed + # ] + # alias [shape=plaintext] + # } + # + # label = "Graphviz" + # } + # + # |dot begin + # digraph G { + # subgraph cluster_1 { + # graph [ + # label = "VARIABLES", + # color = magenta, + # fontsize = 12, + # fontcolor = black, + # shape = box + # ] + # var [shape=plaintext] + # } + # + # subgraph cluster_2 { + # graph [ + # label = "ALIASES", + # color = red, + # fontsize = 14, + # fontcolor = black, + # shape = box, + # style = dashed + # ] + # alias [shape=plaintext] + # } + # + # label = "Graphviz" + # } + # |dot end + # + # SOURCE + # + proc addsubgraph {graph type args} { + $graph addsubgraph [cluster] {*}$dot::style($type) {*}$args + } + #***** + + #****f* dot/addedge + # + # NAME + # dot::addedge - создание связи между элементами графа + # + # DESCRIPTION + # Процедура добавляет команду создания связи между элементами графа + # к списку связей (переменная $edges). + # + # NOTES + # Связи не добавляются в граф, так как пакет Tcldot при добавлении + # связи проверяет наличие элементов, что при последовательной + # загрузке и анализе файлов с исходным кодом и пространств имен + # приводит к ошибкам ссылки на несуществующий элемент. После анализа + # всех файлов необходимо выполнить процедуру [dot::makeEdges] для + # добавления связей в общий граф. + # + # USAGE + # dot::addedge from to + # + # ARGUMENTS + # * from - источник + # * to - + # + # RESULT + # Добавление команды создания связи между элементами графа к списку + # + # SIDE EFFECTS + # Изменение переменной пространства имен ::dot $dot::edges + # + # EXAMPLE + # dot::addedge source destination -> + # + # digraph G { + # source -> destination + # } + # + # |dot start + # digraph G { + # rankdir = LR + # source -> destination + # } + # |dot end + # + # SOURCE + # + proc addedge {from to} { + variable edges + lappend edges [list "$from" addedge "$to"] + } + #***** + + #****f* dot/addedges + # + # NAME + # dot::addedges - + # + # DESCRIPTION + # + # USAGE + # dot::addedges $from - + # + # ARGUMENTS + # * from - + # + # RESULT + # + # SIDE EFFECTS + # + # EXAMPLE + # dot::addedges source -> {destination1 destination2 destination3} -> + # + # digraph G { + # source -> destination1 + # source -> destination2 + # source -> destination3 + # } + # + # |dot start + # digraph G { + # rankdir = LR + # source -> destination1 + # source -> destination2 + # source -> destination3 + # } + # |dot end + # + # SOURCE + # + proc addedges {from -> to} { + foreach target $to { + #Удаление повторов :: в начале + regsub -- {^(?:::)+} $target {::} target + dot::addedge $from $target + } + } + #***** + + #****f* dot/makeEdges + # + # NAME + # dot::makeEdges - + # + # DESCRIPTION + # + # USAGE + # dot::makeEdges + # + # ARGUMENTS + # * + # + # RESULT + # + # SIDE EFFECTS + # Изменяется глобальный граф graphviz + # + # SOURCE + # + proc makeEdges {} { + variable edges + foreach edge $edges { + #FIXME ::clock + if {[regexp {.*(clock|mathfunc).*} $edge -> all] eq 0} { + catch {eval $edge} + } + } + } + #***** + + #****f* dot/cluster + # + # NAME + # dot::cluster - получение имени следующего подграфа + # + # DESCRIPTION + # Процедура возвращает имя следующего подграфа, которое должно + # соответствовать виду "cluster_INDEX", где INDEX - сквозной + # порядковый номер. + # + # USAGE + # dot::cluster + # + # RESULT + # Имя следующего свободного подграфа + # + # EXAMPLE + # dot::cluster -> cluster_1 + # dot::cluster -> cluster_2 + # dot::cluster -> cluster_3 + # dot::cluster -> cluster_4 + # dot::cluster -> cluster_5 + # + # SIDE EFFECTS + # Используется переменная пространства имен ::dot::clusterIndex, + # значение которой увеличивается на 1 при каждом вызове процедуры + # + # SOURCE + # + proc cluster {} { + variable clusterIndex + return "cluster_[incr clusterIndex]" + } + #***** + + #****f* dot/label + # + # NAME + # dot::label - формирование заголовков dot-узлов + # + # DESCRIPTION + # Процедура формирует заголовок узла graphviz типа record, имеющего + # несколько полей. Тип shape=record имеет вид + # " string | string | ..." + # + # USAGE + # dot::label title nodelist + # + # ARGUMENTS + # * title - заголовок узла + # * nodelist - список полей узла + # + # RESULT + # Строка заголовка + # + # EXAMPLE + # dot::label title {elem1 elem2 elem3} -> + # " title | elem1 | elem2 | elem3" + # + # SOURCE + # + proc label {title nodelist} { + set index 0 + lappend result " [mask $title]" + foreach node $nodelist { + lappend result " [mask $node]" + } + #BUGS: Двойной проход по списку + return [join $result { | }] + } + #***** + + #****f* dot/mask + # + # NAME + # dot::mask - экранирование специальных символов + # + # DESCRIPTION + # Процедура экранирует специальные символы, которые не могут быть + # использованы в полях опций графа/подграфов/узлов (label, ...): + # <, >, {, }. + # + # USAGE + # dot::mask string + # + # ARGUMENTS + # * string - строка символов + # + # RESULT + # Строка с замаскированными символами + # + # EXAMPLE + # dot::mask "