pax_global_header00006660000000000000000000000064140013605370014511gustar00rootroot0000000000000052 comment=7b5710199e96a4788b58943c5e15a725c45b6895 pmccabe-v2.8/000077500000000000000000000000001400136053700131425ustar00rootroot00000000000000pmccabe-v2.8/.gitignore000066400000000000000000000001061400136053700151270ustar00rootroot00000000000000/combined.o /decomment /pmccabe /tests/test*.out /tests/test006/*.out pmccabe-v2.8/COPYING000066400000000000000000001063341400136053700142040ustar00rootroot00000000000000 Software Copyright (C) 2003 Hewlett-Packard (Paul Bame ) GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. 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 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. 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 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 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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 Library General Public License instead of this License. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. 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 Program or any portion of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, 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 Program, 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 Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) 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; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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. If distribution of executable or 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 counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program 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. 5. 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 Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program 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 to this License. 7. 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 Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program 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 Program. 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. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program 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. 9. The Free Software Foundation may publish revised and/or new versions of the 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 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 Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, 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 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. 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 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. 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 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 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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 Library General Public License instead of this License. pmccabe-v2.8/Makefile000066400000000000000000000024771400136053700146140ustar00rootroot00000000000000# Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later CFILES=\ cparse.c dmain.c gettoken.c nmain.c pmccabe.c \ getopt.c io.c OFILES=$(CFILES:.c=.o) CFLAGS = -Wall -Wextra -O3 -fwhole-program INCLUDES=config.h dmain.h getopt.h pmccabe.h ###############{ # On HP-UX you will have to change this INSTALL = install -o root -g root DESTDIR = PROGS = codechanges pmccabe decomment vifn MANPGS = codechanges.1 pmccabe.1 vifn.1 decomment.1 DOCS = TODO NEWS COPYING PMOBJS = combined.o all: $(PROGS) test: $(PROGS) cd tests && ./testsuite pmccabe: $(PMOBJS) $(CC) $(CFLAGS) -o pmccabe $(PMOBJS) combined.o: $(CFILES) $(CC) $(CFLAGS) -c combined.c clean: rm -f *.[oa] pmccabe decomment *.out */*.out install: $(PROGS) $(MANPGS) $(DOCS) $(INSTALL) -d $(DESTDIR)/usr/share/doc/pmccabe \ $(DESTDIR)/usr/share/man/man1 \ $(DESTDIR)/usr/bin $(INSTALL) -m 644 $(MANPGS) $(DESTDIR)/usr/share/man/man1 #$(INSTALL) -m 644 $(DOCS) $(DESTDIR)/usr/share/doc/pmccabe $(INSTALL) -m 755 $(PROGS) $(DESTDIR)/usr/bin indent: indent -bap -bad -d0 -bli0 -nce -cli0 -ss -npcs -bs -di1 -nbc -psl -i4 -lp -ip0 -nfca -nfc1 *.c *.h ###############} getopt.o : config.h getopt.h dmain.o \ io.o : dmain.h pmccabe.h cparse.o \ gettoken.o \ nmain.o : pmccabe.h dmain.h pmccabe.o : pmccabe.h getopt.h pmccabe-v2.8/NEWS000066400000000000000000000075471400136053700136560ustar00rootroot00000000000000Version 2.8 -- Sun, 17 Jan 2021 18:13:43 -0500 * Resolved Ubuntu bug 1151766 * The -X parser is now the default * tests moved to ./tests * repairs to pdiff(1) -- anybody ever use this? Version 2.7b -- Thu, 14 Jan 2021 14:59:07 +0100 * Moved web site to https://gitlab.com/jas/pmccabe/ * Fix typos in pmccabe.1. * The 'description' file was renamed to README. * The ChangeLog file renamed to NEWS and contains more history. * Non-source files were removed, notably pmccabe.html that can be re-generated from pmccabe.1. * Don't infloop on architectures with unsigned char (regression introduced in 2.7). * Source code re-indented using 'make indent' (only minor changes for newly added code). * The -x parser is still the default, switch to -X is planned for 2.8. Version 2.7 -- Fri, 20 May 2011 17:37:45 -0400 * moved web site to http://people.debian.org/~bame/pmccabe * Fix bugs from Ahmad Jbara 1. no longer counts ^ as part of complexity like && 2. statement count now includes # of switch (but not case) statements which will break people's regression tests WARNING! WARNING! * Inspired by and/or code donated by Matt Hargett: * (LP: #499591) "add threshold capability" from Matt Hargett * (LP: #659550) - * added -x/-X options to select the old or Matt's "cpp" algorithm * WARNING WARNING WARNING!!!! in version 2.8, -X will become the default and which will likely break people's existing regression tests * used indent(1) to format the source -st -bap -bad -d0 -bli0 -nce -cli0 -ss -npcs -bs -di1 -nbc -psl -i4 -lp -ip0 -nfca -nfc1 * made some things boolean and fixed a bunch of compiler warnings * added -fwhole-program speedup Version 2.6 -- Fri, 06 Aug 2010 14:18:25 -0400 * (LP: #364338) pdiff script change has bug (ubuntu) * (LP: #499589) infinite loop with namespaced struct variable declaration * Thanks to matt_hargett for bugs and patches * Fixed a problem parsing DOS-format CRLF files Version 2.5 -- Wed, 30 Jul 2008 15:21:28 -0600 * updated codechanges and pdiff to be bashism safe * updated test files Version 2.4 -- Mon, 13 Aug 2007 21:14:22 -0600 * add support for C++ namespaces Version 2.3 -- Wed, 26 Nov 2003 12:06:55 -0700 * you can use "class" as an identifier in C code now. Thanks to xianjie zhang for an excellent bug report. 12 Mar 2003 pmccabe 2.2-3 Debian package (for sarge/unstable) uploaded. Red Hat version is pmccabe-2.2-4.i386.rpm, created with alien(1). Version 2.2 -- Tue, 17 Dec 2002 10:07:41 -0700 Prepare for releasing to Open Source, includes Debianizing. Version 2.1 Allow non-K&R 'const' in K&R-style function definitions (yuck). Version 2.0 Parse destructor names properly for functions implemented within their class definitions. Support declarations of classes within functions and functions within classes, recursively. Add -f and -F options to enable per-file statistics printing. Add -V option to get the current version number. Add -n option to calculate non-commented source lines directly. Output format compatible with 'anac'. Count C-preprocessor lines properly with -d and -n options, previously was not counting them as non-commented lines. Keep track of # statements in a file which are outside the scope of functions (e.g., variable declarations). Parsing 'struct foo function() {return;}' and some related constructs used to confuse the parser -- fixed. Remove a bunch of dead code. More consistent error messages. 12 Feb 2003 First external web pages prototype Jan 2002 Announced intent to package for Debian. Dec 2002 Hewlett-Packard agrees to release pmccabe July 1998 Port to win32 May 1993 Get rid of Unixy multi-process architecture so it'll work on DOS. July 1992 pmccabe begins as a personal project within HP. pmccabe-v2.8/README000066400000000000000000000025311400136053700140230ustar00rootroot00000000000000McCabe-style complexity and line counting for C and C++ Pmccabe calculates McCabe-style cyclomatic complexity for C and C++ source code. Per-function complexity may be used for spotting likely trouble spots and for estimating testing effort. Pmccabe also includes a non-commented line counter compatible with anac, 'decomment' which only removes comments from source code; 'codechanges', a program to calculate the amount of change which has occurred between two source trees or files; and 'vifn', to invoke 'vi' given a function name rather than a file name. Pmccabe attempts to calculate the apparent complexity rather than the complexity following the C++ and/or cpp preprocessors. This causes Pmccabe to become confused with cpp constructs which cause unmatched curly braces - most of which can profitably be rewritten so they won't confuse prettyprinters anyway. Pmccabe prints C-compiler-style error messages when the parser gets confused so they may be browsed with standard tools. Two types of cyclomatic complexity are generated - one type counts each switch() statement as regardless of the number of cases included and the other more traditional measure counts each case within the switch(). Pmccabe also calculates the starting line for each function, the number of lines consumed by the function, and the number of C statements within the function. pmccabe-v2.8/TODO000066400000000000000000000006001400136053700136260ustar00rootroot00000000000000Templates probably don't work Revise the man page to be more accurate about statement counting. Remember to change the default -x -X for 2.8 to -X WARNING!!!! Before upgrading to Matt's cparse.c changes I ran his new tests with -X and only 16, 17, and 19 failed. 1. Don't skip over the #else block when the #if is always false: #if 0 void f() { #else void g() { #endif int a; } pmccabe-v2.8/codechanges000077500000000000000000000115311400136053700153340ustar00rootroot00000000000000#!/bin/sh -f # $Header: /gjd/tools/pmccabe/codechanges 1.12 2001/10/25 23:51:46 bame Exp $ # Find a "good", e.g., "new" (circa 1988?), awk goodawk() { for AWK in gawk nawk awk mawk do $AWK -v foo=bar 'function f() { print 1 }' >/dev/null 2>&1 && return done echo "I can't find a new enough 'awk' (tried gawk, nawk and awk) in" >&2 echo "your \$PATH to run this program -- sorry." >&2 exit 5 } FIND() { ( cd $1 && find . -type f -a \ \( \ -name *.[cC] \ -o -name *.[hH] \ -o -name *.*sh \ -o -name *.mak \ -o -name *akefile \ -o -name *.cpp \ -o -name *.cxx \ -o -name *.C \ -o -name *.cc \ -o -name *.hh \ \) -print | sort ) } parsediff() { $AWK -v dir1="$1" -v dir2="$2" ' # Skip noise lines BEGIN { printf("%s\t%s\t%s\tOld File, New File\n", "NEW", "DELETED", "CHANGED"); } (/^>/) { next } (/^ 0) { nlines++ } return nlines } ($1 == "Add") { #print "DEBUG: adding", lines, "lines from", fname eof() file1 = "NEWFILE" file2 = $2 addtotal += $3; eof() next } ($1 == "Delete") { #print "DEBUG: deleting", lines, "lines from", fname eof() file2 = "DELETED" file1 = $2 deltotal += $3; eof() next } function eof() { if (file1 != "" && (addtotal > 0 || deltotal > 0 || chgtotal > 0)) { printf("%d\t%d\t%d\t%s %s\n", addtotal, deltotal, chgtotal, file1, file2); taddtotal += addtotal; tdeltotal += deltotal; tchgtotal += chgtotal; } file1 = "" addtotal = 0; deltotal = 0; chgtotal = 0; } ($1 == "diff") { #print "DEBUG: ", $0 eof(); file1 = $(NF - 1) file2 = $(NF) next } (/c/) { n=split($0,tmparray,"c"); # do left side of c and then right leftchg = parse(tmparray[1]) + 0; rightchg = parse(tmparray[n])+ 0; if(leftchg == rightchg) { change = leftchg; } # assume that smaller side is change and the difference is add or delete else if(leftchg > rightchg) { #print "DEBUG=", leftchg, rightchg change = rightchg ; deltotal += (leftchg - rightchg) #print "deleted via change " leftchg - rightchg } else if(leftchg < rightchg) { change = leftchg addtotal += (rightchg-leftchg) #print "DEBUG<", leftchg, rightchg #print "added via change " rightchg - leftchg }; # print "change ", change, "left changed ", \ #leftchg , "right changed ", rightchg, "INPUT= ", m, $0; chgtotal += change; next } # parse if comma separated or return value if no comma function parse(str, localval, localarray,localcount) { localcount=split(str, localarray, ",") if(localcount == 1) localval = 1; else localval = (localarray[localcount]+0 - \ localarray[localcount-1] +1) #print "DEBUG return value", localval, str return(localval); } (/d/) { n=split($0,tmparray,"d"); #uses line range before the d deleted = parse(tmparray[1]); deltotal += deleted; #print "deleted " deleted, "DEBUG", $0; next } (/a/) { # print "DEBUG:", file1, file2, $0 n=split($0,tmparray,"a"); # uses line range after the a added = parse(tmparray[n]); addtotal += added; #print "added ", added , "DEBUG", m, $0; next } { print "?????????", $0 } END { eof(); printf("%d\t%d\t%d\tTOTAL\n", taddtotal, tdeltotal, tchgtotal); } ' } # Need to pick up 'decomment' PATH=$PATH:$(dirname $0) goodawk if [ X$1 = X-n ] then DECOMMENT=cat shift 1 else DECOMMENT=decomment fi if [ $# != 2 ] then cat >&2 < $TMPDIR/A $DECOMMENT $2 > $TMPDIR/B $DECOMMENT $dir2/$fname | diff -bw -- $TMPDIR/A $TMPDIR/B } | parsediff rm -fr $TMPDIR exit fi dir1=$1 dir2=$2 printf '%s' "$dir1 ..." >&2 FIND $dir1 > $TMPDIR/A printf '\n%s' "$dir2 ..." >&2 FIND $dir2 > $TMPDIR/B echo >&2 comm $TMPDIR/A $TMPDIR/B | while IFS="" read f do set -- $f fname=$1 case $f in " "*) echo "diff $dir1/$fname $dir2/$fname" $DECOMMENT $dir1/$fname > $TMPDIR/C $DECOMMENT $dir2/$fname | diff -bw -- $TMPDIR/C - ;; " "*) lines=$($DECOMMENT $dir2/$fname | wc -l) echo "Add $dir2/$fname $lines" ;; *) lines=$($DECOMMENT $dir1/$fname | wc -l) echo "Delete $dir1/$fname $lines" ;; esac done | tee $TMPDIR/D | parsediff $dir1 $dir2 rm -fr $TMPDIR pmccabe-v2.8/codechanges.1000066400000000000000000000041331400136053700154700ustar00rootroot00000000000000.TH "codechanges" 1 17Jan2021 .SH NAME codechanges \- computes the amount of code changes between two code trees or single files .SH SYNOPSIS .B codechanges [-n] old-directory new-directory .P .B codechanges [-n] old-file new-file .SH DESCRIPTION .I codechanges recursively compares the two named directories (or files) calculating new/deleted/changed lines, not including comments or blank lines, in files which appear to be source files (C, C++, shell, and Makefiles). To include comments and blank lines, use the .B -n option. .SH APPLICATIONS .I codechanges is purpose designed to measure the amount of code change between milestones in a project's life. The following output is from two stages, plus some artificial test cases, in the .I pmccabe code stream: .nf NEW DELETED CHANGED Old File, New File 11 19 4 old.pmccabe/./Makefile pmccabe/./Makefile 214 10 39 old.pmccabe/./cparse.c pmccabe/./cparse.c 463 0 0 NEWFILE pmccabe/./decomment.c 147 4 39 old.pmccabe/./dmain.c pmccabe/./dmain.c 10 0 0 NEWFILE pmccabe/./dmain.h 407 0 0 NEWFILE pmccabe/./getopt.c 48 0 0 NEWFILE pmccabe/./getopt.h 9 18 12 old.pmccabe/./gettoken.c pmccabe/./gettoken.c 18 18 15 old.pmccabe/./io.c pmccabe/./io.c 175 43 20 old.pmccabe/./nmain.c pmccabe/./nmain.c 194 11 22 old.pmccabe/./pmccabe.c pmccabe/./pmccabe.c 42 0 20 old.pmccabe/./pmccabe.h pmccabe/./pmccabe.h 0 1318 0 old.pmccabe/./test/langMode.c DELETED 24 0 0 NEWFILE pmccabe/./test006/Grapher.H 620 0 0 NEWFILE pmccabe/./test006/Handler.H 442 0 0 NEWFILE pmccabe/./test006/NodeArc.H 764 0 0 NEWFILE pmccabe/./w/parser.C 95 0 0 NEWFILE pmccabe/./w/tokens.h 4 0 0 NEWFILE pmccabe/./x.sh 3687 1441 171 TOTAL .fi .SH DIAGNOSTICS There aren't many at this time. .SH BUGS .I codechanges thinks it knows what source files are interesting and the user may not agree with its choices. It's a script and should be easy to modify. Ultimately this should probably be configurable. .P .I codechanges uses a program called .I decomment which guesses how to de-comment a file based on its file name and it's not always perfect. .SH AUTHOR Paul Bame .SH "SEE ALSO" .IR pmccabe (1), .IR decomment (1) pmccabe-v2.8/combined.c000066400000000000000000000002111400136053700150600ustar00rootroot00000000000000#include "cparse.c" #include "dmain.c" #include "gettoken.c" #include "nmain.c" #include "pmccabe.c" #include "getopt.c" #include "io.c" pmccabe-v2.8/cparse.c000066400000000000000000000324631400136053700145730ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ #include #include #include #include #include "pmccabe.h" #include "dmain.h" /* $Id: cparse.c,v 1.24 2001/01/26 23:00:30 bame Exp $ */ // handles C++ function/identifier names, destructors etc // also silently discards 'class' if it is preceeded by 'enum' int fancygettoken(char *buf, int classflag, int *line, int *nLine) { int c, c2; char tmpbuf[2048]; if ((c = gettoken(buf, line, nLine)) == T_IDENT) { if ((c = gettoken(tmpbuf, NULL, NULL)) == ':') { if ((c = ncss_Getchar()) == ':') { buf += strlen(buf); *buf++ = ':'; *buf++ = ':'; *buf = '\0'; switch (c = gettoken(tmpbuf, NULL, NULL)) { case T_OPERATOR: strcat(buf, tmpbuf); buf += strlen(buf); getoverloadedop(buf); break; case T_IDENT: /* ident::ident - could be recursive */ ncss_Ungets(tmpbuf); if ((c = fancygettoken(buf, 1, NULL, NULL)) != T_IDENT) ncss_Ungetc(c); break; case '~': /* destructor, collect the identifier */ *buf++ = c; gettoken(buf, NULL, NULL); break; default: ncss_Ungetc(c); *buf++ = '\0'; break; } } else { /* only got ':', who knows what this is */ ncss_Ungets("::"); } } else { ungettoken(c, tmpbuf); } c = T_IDENT; } else if (c == T_ENUM) { if ((c2 = gettoken(tmpbuf, NULL, NULL)) != T_CLASS) { ungettoken(c2, tmpbuf); } } else if (classflag && c == T_OPERATOR) { /* strcat(buf, tmpbuf); */ buf += strlen(buf); getoverloadedop(buf); } else if (classflag && c == '~') { *buf++ = c; c = gettoken(buf, NULL, NULL); if (c != T_IDENT) { fprintf(stderr, "fatal error file %s line %d\n", __FILE__, __LINE__); exit(3); } } return c; } int toplevelstatement(stats_t * stats) /* * At the top level of a C file, the statements are blocks of * tokens ending in either ; or are function definitions which * end in }. Interesting types of statements include class * and struct definitions - because they may contain inline functions, * and function definitions. All others are merely counted. */ { bool endofstatement = false; int c; char buf[1024]; int functionFirstLine = -1; int functionFirstNLine = -1; int functionDefLine; int line, nLine; bool maybenamespace(void); buf[0] = '\0'; c = skipws(); ncss_Ungetc(c); /* gettoken eats whitespace */ while (!endofstatement && (c = fancygettoken(buf, stats->type == STATS_CLASS, &line, &nLine)) != EOF) { if (functionFirstLine == -1) { functionFirstLine = line; functionFirstNLine = nLine; } switch (c) { case T_CLASS: case T_STRUCT: case T_UNION: if (maybeclass()) { stats->nsemicolons--; endofstatement = true; } break; case T_NAMESPACE: if (maybenamespace()) { /* no trailing semicolon for namespaces */ endofstatement = true; } break; case '(': /* possible start of function */ functionDefLine = Line; possiblefn(stats, buf, functionFirstLine, functionDefLine, functionFirstNLine); endofstatement = true; break; case '}': case ')': Exit = 2; { char _buf[100]; sprintf(_buf, "too many %c's", c); fileerror(_buf); } break; case '{': c = matchcurly(); break; case ':': /* This should catch C++ "class foo { public: } */ case ';': /* end of statement */ endofstatement = true; break; default: break; } } return c; } int findchar(char fc) { int c; while ((c = ncss_Getchar()) != EOF && c != fc) { } return c; } bool maybeclass() /* * We've just seen "class" at the top level in a file so * we may be entering a definition of same. If so, we want to be * on the lookout for inline functions. Return 1 if this is a * class definition else restore the function name and return 0. */ { char classname[2048], dummy[2048]; bool isclass = false; int c; if ((c = gettoken(classname, NULL, NULL)) == T_IDENT) { /* "class name" */ switch (c = gettoken(dummy, NULL, NULL)) { case '{': /* "class name {" */ break; case ':': c = gettoken(dummy, NULL, NULL); /* "struct namespace::name" ---- declaration, not definition */ if (c == ':') { return 0; } /* "class name : ---- look for { */ while ((c = gettoken(dummy, NULL, NULL)) != '{') { } break; default: /* if we fail to get "class name [:.*] {" */ ungettoken(c, dummy); } } else if (c == '{') /* Unnamed class */ { /* "class {" */ strcpy(classname, "unnamed"); } else { /* "class BOGUS" -- perhaps this is C code using a variable "class" */ ungettoken(c, dummy); } if (c == '{') { isclass = true; stats_t *class = stats_push(classname, STATS_CLASS); while ((c = gettoken(dummy, NULL, NULL)) != '}') { if (c == EOF) { fileerror("expected closing } for class scope, but got EOF"); break; } else ungettoken(c, dummy); toplevelstatement(class); } stats_pop(class); } return isclass; } bool maybenamespace() /* * We've just seen "namespace" at the top level in a file so * we may be entering a definition of same (if we next find "token {"). * Return 1 if this is a * namespace definition else restore the name and return 0. */ { char nsname[2048], dummy[2048]; bool isns = false; int c; if ((c = gettoken(nsname, NULL, NULL)) == T_IDENT) { /* "namespace name" */ switch (c = gettoken(dummy, NULL, NULL)) { case '{': /* "namespace name {" */ break; default: /* if we fail to get "namespace name {" */ ungettoken(c, dummy); } } else if (c == '{') /* Unnamed namespace */ { /* "namespace {" */ strcpy(nsname, "anonymous_namespace"); } else { /* "namespace BOGUS" -- is C code using a variable "namespace"? */ ungettoken(c, dummy); } if (c == '{') { isns = true; stats_t *ns = stats_push(nsname, STATS_NAMESPACE); while ((c = gettoken(dummy, NULL, NULL)) != '}') { if (c == EOF) { fileerror("expected closing } for namespace, but got EOF"); break; } else ungettoken(c, dummy); toplevelstatement(ns); } stats_pop(ns); } return isns; } void findsemicolon() { int c; while ((c = ncss_Getchar()) != EOF && c != ';') { switch (c) { case '(': c = matchparen(); break; case '{': c = matchcurly(); break; } } if (c == EOF) { Exit = 5; fileerror("expected ';' got EOF"); } } int getoverloadedop(char *buf) /* * Having just read ident::operator, try to read the operator into buf. * If the first non-WS character is a '(', the overloaded thing is a * function call. Otherwise it's some type of real operator and we * terminate normally on '('. If we read ; or { we probably should * print a warning and bail out. */ { char tmpbuf[2048]; int c = gettoken(tmpbuf, NULL, NULL); if (c == '(') { /* overloaded function call syntax */ *buf++ = c; /* Match the paren */ while (c != ')') { if ((c = skipws()) == EOF) break; *buf++ = c; } } else if (c == T_IDENT) { /* class::operator int() */ /* Overloaded typecast */ *buf++ = '_'; *buf = '\0'; strcat(buf, tmpbuf); buf += strlen(buf); *buf++ = '('; *buf++ = ')'; *buf = '\0'; } else if (c != EOF) { *buf++ = c; while ((c = ncss_Getchar()) != EOF) { if (!ISSPACE(c)) { if (c == '(' || c == ';') { ncss_Ungetc(c); break; } else *buf++ = c; } } } *buf = '\0'; return c; } bool is_c_plus_plus(stats_t * stats, const char *name) { return strchr(name, ':') != NULL || stats->type == STATS_CLASS || stats->type == STATS_NAMESPACE; } bool is_reserved_word(const char *word) { return STREQUAL(word, "struct") || STREQUAL(word, "enum") || STREQUAL(word, "void") || STREQUAL(word, "int") || STREQUAL(word, "char") || STREQUAL(word, "const"); return false; } void possiblefn(stats_t * stats, const char *name, int line1, int defline, int nLine1) /* * We've just read an open parenthesis. If there's a legal identifier * in name we may be within a function definition. */ { char dummy[2048]; int nstatements = 0; /* in case there's code prior to the { */ int c; if (strlen(name) == 0) { /* no function name - must not be a function - return */ findsemicolon(); return; } if ((c = matchparen()) != EOF) { c = gettoken(dummy, NULL, NULL); switch (c) { case T_CONST: if (is_c_plus_plus(stats, name)) { /* foo::foo() const ^ [;] { */ /* This'll either be a ; for a declaration or a { */ /* or a throw() and/or __attribute__() annotation */ c = gettoken(dummy, NULL, NULL); break; } /* foo() const ^ char *a; { */ /*** FALL THROUGH ***/ case T_IDENT: if (is_c_plus_plus(stats, name)) { /* there is no K&R C++ ;) */ /* also, throw() and/or __attribute__ come after */ break; } /* FALL THROUGH IN flat C case */ case T_STRUCT: case T_UNION: /* K&R function, T_IDENT is part of first parm defn */ /* Read up to that first '{' */ /* function foo(a, b, c) int a; */ /* ^ */ while ((c = ncss_Getchar()) != EOF && c != '{') ; break; case '{': /* open { of the function */ break; case '(': /* weird possibility in C++ - what we thought was the */ /* parameter list was really part of an overloaded */ /* operator overloading of an odd typecast or something. */ /* The function name will be wrong but who cares :-> */ c = matchparen(); if (c != EOF) c = gettoken(dummy, NULL, NULL); break; case ':': /* Another C++-ism: main(args): ident(args), ident(args) */ c = prefunction(&nstatements); break; case EOF: fileerror ("expected pretty much anything after closing paren of function, but got EOF\n"); return; } /* we check for throw, volatile, and __attribute__ outside of the switch() above, * because they are combinable in a single function declaration and might happen * IN ADDITION TO a const() */ if (c == T_VOLATILE) { /* skip the volatile keyword */ c = gettoken(dummy, NULL, NULL); } if (c == T_THROW) { /* detect void f() throw() */ c = gettoken(dummy, NULL, NULL); if (c != '(') { char error_message[100]; sprintf(error_message, "expected opening paren for method throw declaration, but got '%c'", c); fileerror(error_message); return; } c = matchparen(); if (c == EOF) { fileerror ("expected closing paren for method throw declaration, but saw EOF"); return; } c = gettoken(dummy, NULL, NULL); } if (c == T_IDENT) { /* detect void f() __attribute__(...) */ /* and void f() GCC_PRINTF(...) */ c = gettoken(dummy, NULL, NULL); if (c == '(') { c = matchparen(); if (c == EOF) { fileerror ("expected closing paren for __attribute__ (or macro), but saw EOF"); return; } } /* if there wasn't a paren after the likely-attribute macro, * the compiler-attribute arguments within the macro definition itself */ c = gettoken(dummy, NULL, NULL); } if (c == '{') { if (is_reserved_word(name)) { char error_message[1000]; snprintf(error_message, sizeof (error_message) - 1, "got '%s' as a name for a function, which means a probable bug in our parser", name); fileerror(error_message); return; } /* This really is a function */ stats_t *fn = stats_push(name, STATS_FUNCTION); fn->nfunctions = 1; fn->firstline = line1; fn->defline = defline; fn->nsemicolons = nstatements; c = countfunction(fn); fn->nLines = ncss_Line - nLine1; stats->nLines -= fn->nLines; if (!Totalsonly && !Filesonly) printstats(fn); stats_pop(fn); } } } int prefunction(int *nstatements) /* * Handle C++ ident(args) : ident(args), ident(args). Count each * ident(args) after function declaration as a statement. */ { int c; (*nstatements)++; while ((c = ncss_Getchar()) != EOF) { switch (c) { case '(': c = matchparen(); break; case ',': (*nstatements)++; break; case '{': return c; } } Exit = 9; fileerror("expected { got EOF"); return c; } int countfunction(stats_t * fn) { int nest = 1; int c; char id[512]; while (nest > 0 && (c = gettoken2(id, NULL, NULL)) != EOF) { switch (c) { case ';': fn->nsemicolons++; break; case '{': nest++; break; case '}': nest--; break; case '?': fn->nq++; break; case T_LOGICAL: fn->nor++; break; case T_CLASS: case T_UNION: case T_STRUCT: if (maybeclass()) fn->nsemicolons--; break; default: countword(fn, c); break; } } fn->lastline = Line; if (nest > 0 /* && c == EOF */ ) { Exit = 6; fileerror("not enough }'s"); } return c; } void countword(stats_t * fn, int id) { switch (id) { case T_IF: fn->nif++; break; case T_FOR: fn->nfor++; break; case T_WHILE: fn->nwhile++; break; case T_SWITCH: fn->nswitch++; break; case T_CASE: fn->ncase++; break; } } pmccabe-v2.8/decomment.1000066400000000000000000000013361400136053700152020ustar00rootroot00000000000000.TH "decomment" 1 17Jan2021 .SH NAME decomment \- remove comments from C and C++ files .SH SYNOPSIS .B decomment [file(s)] .SH DESCRIPTION .I decomment processes the named files, or standard input if none are named, copying their contents to standard output with comments removed. Line numbers in the input file(s) and out file(s) are unchanged, that is, if \fCmain()\fR occurs on line 40 in the input, it will also appear on line 40 in the output despite comment removal. .SH APPLICATIONS \fIdecomment\fR may be used to remove comments in order to simply other programs which process source code. .SH DIAGNOSTICS No parsing-related diagnostics. .SH WARNINGS .SH AUTHOR Paul Bame .SH "SEE ALSO" .IR pmccabe (1), .IR codechanges (1) pmccabe-v2.8/decomment.c000066400000000000000000000161471400136053700152720ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ #ifdef __hpux #define _XOPEN_SOURCE 1 #endif #ifdef __unix #include #endif #ifdef WIN32 #include "getopt.h" #endif #ifdef NEED_OPTIND extern int optind; #endif #include #include #include #include static int G_removeBlankLines = 1; static const char *G_lang; static void blankline(char *buf, char **bp) { char *ptr; *(*bp) = '\0'; if (G_removeBlankLines) { for (ptr = buf; *ptr != '\0'; ptr++) { if (!isspace(*ptr)) { fputs(buf, stdout); break; } } } else { fputs(buf, stdout); } *bp = buf; } static void decomment_sh(FILE * in) { register int c, c1; char outbuf[4 * 1024]; char *op = outbuf; enum { NORMAL, SH_COMMENT, DOUBLEQUOTESTRING, SINGLEQUOTESTRING } state = NORMAL; while ((c = getc(in)) != EOF) { switch (state) { case NORMAL: switch (c) { case '\'': state = SINGLEQUOTESTRING; *op++ = c; break; case '"': state = DOUBLEQUOTESTRING; *op++ = c; break; case '#': state = SH_COMMENT; break; case '\\': *op++ = c; c1 = getc(in); *op++ = c1; break; default: *op++ = c; break; } break; case SH_COMMENT: /* C++ comment */ if (c == '\n') { state = NORMAL; } break; case DOUBLEQUOTESTRING: *op++ = c; switch (c) { case '"': state = NORMAL; break; case '\\': /* handle quoted quotes */ c1 = getc(in); *op++ = c1; break; } break; case SINGLEQUOTESTRING: *op++ = c; switch (c) { case '\'': state = NORMAL; break; case '\\': getc(in); break; } break; } /* If we just stuffed a \n into the output buffer... */ if (op > outbuf && op[-1] == '\n') { blankline(outbuf, &op); } } } static void decomment_asm(FILE * in) { register int c, c1; char outbuf[4 * 1024]; char *op = outbuf; enum { NORMAL, ASM_COMMENT, STRINGLITERAL, CHARLITERAL } state = NORMAL; while ((c = getc(in)) != EOF) { switch (state) { case NORMAL: switch (c) { case '\'': state = CHARLITERAL; *op++ = c; break; case '"': state = STRINGLITERAL; *op++ = c; break; case ';': state = ASM_COMMENT; break; default: *op++ = c; break; } break; case ASM_COMMENT: /* C++ comment */ if (c == '\n') { state = NORMAL; } break; case STRINGLITERAL: *op++ = c; switch (c) { case '"': state = NORMAL; break; case '\\': /* handle quoted quotes */ c1 = getc(in); *op++ = c1; break; } break; case CHARLITERAL: *op++ = c; switch (c) { case '\'': state = NORMAL; break; case '\\': getc(in); break; } break; } /* If we just stuffed a \n into the output buffer... */ if (op > outbuf && op[-1] == '\n') { blankline(outbuf, &op); } } } static void decomment_c(FILE * in) { register int c, c1; char outbuf[4 * 1024]; char *op = outbuf; enum { NORMAL, C_COMMENT, CC_COMMENT, STRINGLITERAL, CHARLITERAL } state = NORMAL; while ((c = getc(in)) != EOF) { switch (state) { case NORMAL: switch (c) { case '\'': state = CHARLITERAL; *op++ = c; break; case '"': state = STRINGLITERAL; *op++ = c; break; case '/': c1 = getc(in); switch (c1) { case '/': state = CC_COMMENT; break; case '*': state = C_COMMENT; break; case EOF: break; default: *op++ = c; ungetc(c1, in); break; } break; default: *op++ = c; break; } break; case C_COMMENT: /* K&R C comment */ if (c == '*') { c1 = getc(in); if (c1 == '/') { state = NORMAL; } else { ungetc(c1, in); } } break; case CC_COMMENT: /* C++ comment */ if (c == '\n') { state = NORMAL; } break; case STRINGLITERAL: *op++ = c; switch (c) { case '"': state = NORMAL; break; case '\\': /* handle quoted quotes */ c1 = getc(in); *op++ = c1; break; } break; case CHARLITERAL: *op++ = c; switch (c) { case '\'': state = NORMAL; break; case '\\': getc(in); break; } break; } /* If we just stuffed a \n into the output buffer... */ if (op > outbuf && op[-1] == '\n') { blankline(outbuf, &op); } }; } static void doit(FILE * in) { switch (*G_lang) { case 's': decomment_sh(in); break; case 'c': decomment_c(in); break; case 'a': decomment_asm(in); break; default: abort(); break; } } static void usage(const char *progname) { fprintf(stderr, "%s - Remove comments and blank lines from files\n\n" "Usage: %s [options] [files]\n" " -b Don't remove blank lines\n" " -l language Specify language of files\n" " c = C and C++ (default)\n" " sh = Bourne/Posix shell-like\n" " asm = Assembler\n" " NOTE: Normally the language is derived from\n" " the file name. '-l' overrides this entirely\n" " and is especially useful when %s is used as\n" " a filter.\n", progname, progname, progname); exit(2); } int main(int argc, char *argv[]) { char *langoverride = NULL; int c; while ((c = getopt(argc, argv, "bl:")) != EOF) { switch (c) { case 'b': G_removeBlankLines = 0; break; case 'l': if (!(strcmp(optarg, "c") == 0 || strcmp(optarg, "sh") == 0 || strcmp(optarg, "asm") == 0)) { usage(argv[0]); } langoverride = optarg; break; default: usage(argv[0]); break; } } if (optind == argc) { if (langoverride != NULL) { G_lang = langoverride; } else { G_lang = "c"; } doit(stdin); } else { while (optind < argc) { const char *fname = argv[optind]; G_lang = NULL; if (langoverride != NULL) { G_lang = langoverride; } else { const char *basename; const char *ext; if ((basename = strrchr(fname, '/')) == NULL) { basename = fname; } else { basename++; } if ((ext = strrchr(basename, '.')) != NULL) { ext++; if (*ext != '\0') { if (ext[1] == '\0') { switch (ext[0]) { case 'c': case 'C': case 'h': case 'H': G_lang = "c"; break; case 's': G_lang = "asm"; break; } } else if (ext[0] == 'C' || ext[0] == 'c') { G_lang = "c"; } else if (strstr(ext, "sh") != NULL || strstr(ext, "mak") != NULL || strstr(ext, "mk") != NULL) { G_lang = "sh"; } } } else { if (strstr(basename, "akefile") != NULL) { G_lang = "sh"; } } } if (G_lang == NULL) { G_lang = "c"; } if (strcmp(fname, "-") == 0) { doit(stdin); } else { FILE *f; if ((f = fopen(fname, "r")) == NULL) { perror(fname); continue; } doit(f); fclose(f); } optind++; } } return 0; } pmccabe-v2.8/dmain.c000066400000000000000000000275241400136053700144100ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ #include #include #include "dmain.h" #include "pmccabe.h" /* Global */ int ncss_Line; /* $Id: dmain.c,v 1.16 2001/01/26 23:00:32 bame Exp $ */ static int Lastc = '\n'; short Pipe[PIPESIZE]; short *Piperead = Pipe; short *Pipewrite = Pipe; short *Pipeend = Pipe + PIPESIZE; bool skipping = false; FILE *Input; char Inputfile[1030]; bool Cppflag = false; enum { PREPROCESSOR_POSITIVE_IF, PREPROCESSOR_NEGATIVE_IF, PREPROCESSOR_NEVER_IF, PREPROCESSOR_ELSE, PREPROCESSOR_ENDIF, PREPROCESSOR_INCLUDE, PREPROCESSOR_DEFINE, PREPROCESSOR_UNKNOWN }; void skip_within_line(char char_to_skip) { int c; while ((c = getc(Input)) != EOF && c != '\n' && c == char_to_skip) ; if (c == EOF) { char error_message[100]; sprintf(error_message, "expected '%c' before end of line, but got EOF", char_to_skip); fileerror(error_message); } ungetc(c, Input); } void skip_whitespace_within_line() { skip_within_line(' '); skip_within_line('\t'); skip_within_line(' '); skip_within_line('\t'); } const char * string_for_preprocessor_token(int preprocessor_token) { switch (preprocessor_token) { case PREPROCESSOR_DEFINE: return "#define"; case PREPROCESSOR_POSITIVE_IF: return "#ifdef"; case PREPROCESSOR_NEGATIVE_IF: return "#ifndef"; case PREPROCESSOR_NEVER_IF: return "#if 0"; case PREPROCESSOR_ELSE: return "#else"; case PREPROCESSOR_ENDIF: return "#endif"; case PREPROCESSOR_INCLUDE: return "#include"; default: return "#UNKNOWN"; } } int get_preprocessor_token() { skip_whitespace_within_line(); char first_letter = getc(Input); char second_letter; switch (first_letter) { case 'd': /* #define */ case 'u': /* #undef */ return PREPROCESSOR_DEFINE; case 'e': second_letter = getc(Input); if (second_letter == 'l') { /* #else or #elif */ return PREPROCESSOR_ELSE; } else if (second_letter == 'n') { /* #endif */ return PREPROCESSOR_ENDIF; } return PREPROCESSOR_UNKNOWN; case 'i': second_letter = getc(Input); if (second_letter == 'n') { /* #include */ return PREPROCESSOR_INCLUDE; } if (second_letter == 'f') { char third_letter = getc(Input); switch (third_letter) { case 'n': /* #ifndef */ return PREPROCESSOR_NEGATIVE_IF; case 'd': /* #ifdef */ return PREPROCESSOR_POSITIVE_IF; case ' ': case '\t': case '(': skip_whitespace_within_line(); skip_within_line('('); char logical_identifier = getc(Input); switch (logical_identifier) { case '0': /* #if 0 */ return PREPROCESSOR_NEVER_IF; case '!': /* #if ! */ return PREPROCESSOR_NEGATIVE_IF; case 'f': if (getc(Input) == 'a' && getc(Input) == 'l' && getc(Input) == 's') { /* #if false */ return PREPROCESSOR_NEVER_IF; } break; case 'd': if (getc(Input) == 'e' && getc(Input) == 'f' && getc(Input) == 'i' && getc(Input) == 'n') { /* #if defined() */ return PREPROCESSOR_POSITIVE_IF; } break; default: return PREPROCESSOR_POSITIVE_IF; } } } } return PREPROCESSOR_UNKNOWN; } static void better_decomment() { enum { NORMAL, C_COMMENT, PREPROCESSOR_DIRECTIVE, CC_COMMENT, STRINGLITERAL, CHARLITERAL } state = NORMAL; register int c, c1; /* FIXME: decomment() gets called multiple times if a file is longer than the PIPESIZE macro */ /* in that case, this variable being reset mid-file may cause issues. */ /* Making the variable static (alone) isn't a solution, in missing #endif cases */ int endifs_required = 0; Piperead = Pipewrite = Pipe; do { if ((c = getc(Input)) == EOF) { if (skipping || endifs_required > 0) { fileerror("expected #endif before EOF"); } PUTCHAR_REGARDLESS_OF_SKIPPING(EOF); break; } switch (state) { case NORMAL: switch (c) { case '#': if (!ISSPACE(Lastc)) { PUTCHAR(c); continue; } state = PREPROCESSOR_DIRECTIVE; if (Cppflag) { PUTS("cpp"); } int preprocessor_token = get_preprocessor_token(); switch (preprocessor_token) { case PREPROCESSOR_ELSE: /* FIXME: to keep things simple (by avoiding recursive descent), * the code below means incorrect behavior with: * #if 0 * #else * #endif */ if (!skipping) { endifs_required++; } skipping = true; break; case PREPROCESSOR_NEVER_IF: skipping = true; endifs_required++; break; case PREPROCESSOR_NEGATIVE_IF: case PREPROCESSOR_POSITIVE_IF: if (skipping) { endifs_required++; } break; case PREPROCESSOR_ENDIF: if (skipping) { endifs_required--; } } if (skipping && endifs_required == 0) { skipping = false; } if (endifs_required < 0) { fileerror("expected fewer #endif statements"); } break; case '\'': state = CHARLITERAL; if (!skipping) PUTS("CHARLITERAL"); break; case '"': state = STRINGLITERAL; if (!skipping) PUTS("STRINGLITERAL"); break; case '/': c1 = getc(Input); switch (c1) { case '/': state = CC_COMMENT; break; case '*': state = C_COMMENT; break; case EOF: /* ending star-slash comment right before EOF is okay */ break; default: PUTCHAR(c); ungetc(c1, Input); break; } break; default: PUTCHAR(c); break; } break; case C_COMMENT: /* K&R C comment */ if (c == '\n') { PUTCHAR(c); } else if (c == '*') { c1 = getc(Input); if (c1 == '/') { state = NORMAL; } else { ungetc(c1, Input); } } break; case PREPROCESSOR_DIRECTIVE: switch (c) { case '\n': PUTCHAR(c); c1 = getc(Input); if (c1 != '\\') { ungetc(c1, Input); state = NORMAL; break; } /* FALL THROUGH */ case '\\': c1 = getc(Input); if (c1 == '\n') { PUTCHAR(c1); if (Cppflag) { PUTS("cpp"); } } break; } break; case CC_COMMENT: /* C++ comment */ if (c == '\n') { PUTCHAR(c); state = NORMAL; } break; case STRINGLITERAL: switch (c) { case '\n': PUTCHAR(c); break; case '"': state = NORMAL; break; /* preserve embedded nulines */ case '\\': c1 = getc(Input); if (c1 == '\n') PUTCHAR(c1); break; } break; case CHARLITERAL: switch (c) { case '\n': PUTCHAR(c); break; case '\'': state = NORMAL; break; case '\\': getc(Input); break; } break; } Lastc = c; } while (state != NORMAL || Pipewrite - Piperead < PIPESIZE / 2); return; } static void rudimentary_decomment() { register int c, c1; enum { NORMAL, C_COMMENT, CPP, CC_COMMENT, STRINGLITERAL, CHARLITERAL } state = NORMAL; Piperead = Pipewrite = Pipe; do { if ((c = getc(Input)) == EOF) { PUTCHAR(EOF); break; } if (c == '\r') continue; switch (state) { case NORMAL: switch (c) { case '#': if (Lastc == '\n') { state = CPP; if (Cppflag) PUTS("cpp"); } else { PUTCHAR(c); } break; case '\'': state = CHARLITERAL; PUTS("CHARLITERAL"); break; case '"': state = STRINGLITERAL; PUTS("STRINGLITERAL"); break; case '/': c1 = getc(Input); switch (c1) { case '/': state = CC_COMMENT; break; case '*': state = C_COMMENT; break; case EOF: break; default: PUTCHAR(c); ungetc(c1, Input); break; } break; default: PUTCHAR(c); break; } break; case C_COMMENT: /* K&R C comment */ if (c == '\n') { PUTCHAR(c); } else if (c == '*') { c1 = getc(Input); if (c1 == '/') { state = NORMAL; } else { ungetc(c1, Input); } } break; case CPP: switch (c) { case '\n': PUTCHAR(c); state = NORMAL; break; case '\\': c1 = getc(Input); if (c1 == '\n') { PUTCHAR(c1); if (Cppflag) PUTS("cpp"); } break; } break; case CC_COMMENT: /* C++ comment */ if (c == '\n') { PUTCHAR(c); state = NORMAL; } break; case STRINGLITERAL: switch (c) { case '\n': PUTCHAR(c); break; case '"': state = NORMAL; break; /* preserve embedded nulines */ case '\\': c1 = getc(Input); if (c1 == '\n') PUTCHAR(c1); break; } break; case CHARLITERAL: switch (c) { case '\n': PUTCHAR(c); break; case '\'': state = NORMAL; break; case '\\': getc(Input); break; } break; } Lastc = c; } while (state != NORMAL || Pipewrite - Piperead < PIPESIZE / 2); } void decomment() { extern bool BetterDecomment; if (BetterDecomment) better_decomment(); else rudimentary_decomment(); } void decomment_file(FILE * f) { int c; extern bool Cppflag; Input = f; Cppflag = true; while ((c = Getchar()) != EOF) { putc(c, stdout); } } int decomment_files(int argc, char *argv[]) { int result = 0; if (argc == 1) { decomment_file(stdin); } else { while (argc > 1) { FILE *f; if ((f = fopen(argv[1], "r")) == NULL) { result = 2; perror(argv[1]); } else { decomment_file(f); fclose(f); } SHIFT(1); } } return result; } void ncss_Ungetc(int c) { if (c == T_NCNULINE) { ncss_Line--; } Ungetc(c); } void ncss_Ungets(char *s) { Ungets(s); } int ncss_Getchar() { int c; static int blankline = 1; if ((c = Getchar()) != EOF) { if (blankline) { if (!ISSPACE(c)) { blankline = 0; } } else { if (c == '\n') { c = T_NCNULINE; blankline = 1; } } } else { blankline = 1; } if (c == T_NCNULINE) ncss_Line++; return c; } void ncss(int *linesp, int *nclinesp) { int c; int lines = 0; int nclines = 0; int boline = 1; while ((c = Getchar()) != EOF) { if (c == '\n') { lines++; boline = 1; } else if (boline && !ISSPACE(c)) { boline = 0; nclines++; } } *linesp = lines; *nclinesp = nclines; } void ncss_file(char *fname, FILE * f, int *linesp, int *nclinesp) { extern bool Cppflag; int lines, nclines; Input = f; Cppflag = true; ncss(&lines, &nclines); if (!Totalsonly) { if (lines != 0) { int pct_csl = (int) (0.4999999 + 100.0 * (lines - nclines) / lines); printf("%6d%4d%6d%4d%7d %-s\n", lines - nclines, pct_csl, nclines, 100 - pct_csl, lines, fname); } else { printf("%6d n/a%6d n/a%7d %-s\n", lines - nclines, nclines, lines, fname); } } *linesp += lines; *nclinesp += nclines; } int ncss_files(int argc, char *argv[]) { int result = 0; int lines = 0, nclines = 0; int nfiles = argc - 1; if (Verbose) puts(" CSL PCT NCSL PCT TOTAL FILENAME"); if (argc == 1) { ncss_file("stdin", stdin, &lines, &nclines); } else { while (argc > 1) { FILE *f; if ((f = fopen(argv[1], "r")) == NULL) { result = 2; perror(argv[1]); } else { ncss_file(argv[1], f, &lines, &nclines); fclose(f); } SHIFT(1); } } if (Totals) { if (lines != 0) { int pct_csl = (int) (0.4999999 + 100.0 * (lines - nclines) / lines); printf("%6d%4d%6d%4d%7d (total files: %d)\n", lines - nclines, pct_csl, nclines, 100 - pct_csl, lines, nfiles); } else { printf("%6d n/a%6d n/a%7d (total files: %d)\n", lines - nclines, nclines, lines, nfiles); } } return result; } pmccabe-v2.8/dmain.h000066400000000000000000000011301400136053700143760ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ /* $Id: dmain.h,v 1.8 2001/01/26 23:00:36 bame Exp $ */ #define EOINPUT 999 #define PIPESIZE (1024 * 1024) extern short Pipe[PIPESIZE]; extern short *Piperead; extern short *Pipewrite; extern short *Pipeend; #define PUTCHAR(c) {if ((Pipewrite < Pipeend) && (!skipping || c == '\n')) *Pipewrite++ = c;} #define PUTCHAR_REGARDLESS_OF_SKIPPING(c) { if (Pipewrite < Pipeend) *Pipewrite++ = c;} #define PUTS(s) {char *a = s; while (*a != '\0') PUTCHAR_REGARDLESS_OF_SKIPPING(*a++);} extern FILE *Input; extern char Inputfile[1030]; pmccabe-v2.8/getopt.c000066400000000000000000000530151400136053700146140ustar00rootroot00000000000000#define HAVE_STRING_H /* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, 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, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #ifdef HAVE_CONFIG_H #if defined (emacs) || defined (CONFIG_BROKETS) /* We use instead of "config.h" so that a compilation using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h (which it would do because it found this file in $srcdir). */ #include #else #include "config.h" #endif #endif #ifndef __STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include #ifdef HAVE_STRING_H #include #endif /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #endif /* GNU C library. */ /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #ifndef lint static char rcsid[] = "$CVSid: @(#)getopt.c 1.10 94/09/21 $"; #endif #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* XXX 1003.2 says this must be 1 before any call. */ int optind = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ char *getenv(); static char * my_index(str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ #ifndef __STDC__ /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen(const char *); #endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void exchange(argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ static const char * _getopt_initialize(optstring) const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind = 1; nextchar = NULL; posixly_correct = getenv("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns `EOF'. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal(argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (optind == 0) optstring = _getopt_initialize(optstring); if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0')) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp(argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return EOF; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) { if (ordering == REQUIRE_ORDER) return EOF; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index(optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp(p->name, nextchar, nameend - nextchar)) { if (nameend - nextchar == (int) strlen(p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf(stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[optind]); nextchar += strlen(nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); else /* +option or -option */ fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen(nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], argv[optind - 1]); nextchar += strlen(nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen(nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index(optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf(stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); else /* +option or -option */ fprintf(stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index(optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c); else fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); } optopt = c; return '?'; } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf(stderr, "%s: option requires an argument -- %c\n", argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt(argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal(argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main(argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt(argc, argv, "abc:d:0123456789"); if (c == EOF) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf("option %c\n", c); break; case 'a': printf("option a\n"); break; case 'b': printf("option b\n"); break; case 'c': printf("option c with value `%s'\n", optarg); break; case '?': break; default: printf("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); } exit(0); } #endif /* TEST */ pmccabe-v2.8/getopt.h000066400000000000000000000106001400136053700146120ustar00rootroot00000000000000/* Declarations for getopt. Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, 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, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* $CVSid: @(#)getopt.h 1.7 94/09/21 $ */ #ifndef _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if __STDC__ #if defined(__GNU_LIBRARY__) /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt(int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt(); #endif /* not __GNU_LIBRARY__ */ extern int getopt_long(int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only(int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal(int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt(); extern int getopt_long(); extern int getopt_long_only(); extern int _getopt_internal(); #endif /* not __STDC__ */ #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ pmccabe-v2.8/gettoken.c000066400000000000000000000106511400136053700151310ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ #include #include "pmccabe.h" #include "dmain.h" int matchcurly() { int c; int nest = 1; while (nest > 0 && (c = ncss_Getchar()) != EOF) { switch (c) { case '{': nest++; break; case '}': nest--; break; } } if (nest > 0 /* && c == EOF */ ) { Exit = 7; fileerror("not enough }'s"); } return c; } int matchparen() { int c; int nest = 1; while (nest > 0 && (c = ncss_Getchar()) != EOF) { switch (c) { case '(': nest++; break; case ')': nest--; break; } } if (nest > 0 /* && c == EOF */ ) { Exit = 8; fileerror("not enough )'s"); } return c; } int skipws() { int c; /* skip whitespace */ while ((c = ncss_Getchar()) != EOF && ISSPACE(c)) { } return c; } int getsimpleident(char *buf) { int c = 0; while (c != EOF) { c = ncss_Getchar(); if (ISIDENT(c)) { *buf++ = c; } else { *buf++ = '\0'; break; } } return c; } int identify(const char *ident) { int r = T_IDENT; switch (*ident) { case 'i': if (STREQUAL(ident, "if")) r = T_IF; break; case 'w': if (STREQUAL(ident, "while")) r = T_WHILE; break; case 'c': if (STREQUAL(ident, "case")) r = T_CASE; else if (STREQUAL(ident, "class")) r = T_CLASS; else if (STREQUAL(ident, "const")) r = T_CONST; break; case 's': if (STREQUAL(ident, "switch")) r = T_SWITCH; else if (STREQUAL(ident, "struct")) r = T_STRUCT; break; case 'f': if (STREQUAL(ident, "for")) r = T_FOR; break; case 'u': if (STREQUAL(ident, "union")) r = T_UNION; break; case 'o': if (STREQUAL(ident, "operator")) r = T_OPERATOR; break; case 'n': if (STREQUAL(ident, "namespace")) r = T_NAMESPACE; break; case 't': if (STREQUAL(ident, "throw")) r = T_THROW; break; case 'v': if (STREQUAL(ident, "volatile")) r = T_VOLATILE; break; case 'e': if (STREQUAL(ident, "enum")) r = T_ENUM; break; } return r; } void ungettoken(int c, char *s) { if (c >= T_WORDS) { ncss_Ungets(s); } else { ncss_Ungetc(c); } } int gettoken(char *buf, int *line, int *nLine) /* * Callers depend on the fact that gettoken() doesn't modify buf except * when T_IDENT is parsed. */ { int c = skipws(); if (line != NULL) *line = Line; if (nLine != NULL) *nLine = ncss_Line; if (ISIDENT1(c)) { *buf++ = c; ncss_Ungetc(getsimpleident(buf)); c = identify(buf - 1); } return c; } int gettoken2(char *buf, int *line, int *nLine) /* * This one can additionally return T_ASSIGN and T_LOGICAL. But note * that the caller isn't given enough data to know what specifically * was parsed. */ { int c, c1, c2; /* skip whitespace */ c = skipws(); if (line != NULL) *line = Line; if (nLine != NULL) *nLine = ncss_Line; switch (c) { case '*': /* OP= */ case '/': case '%': case '^': c1 = ncss_Getchar(); if (c1 == '=') { c = T_ASSIGN; } else { ncss_Ungetc(c1); } break; case '+': /* +=, ++ */ case '-': /* -=, -- */ c1 = ncss_Getchar(); if (c1 == '=' || c1 == c) { c = T_ASSIGN; } else { ncss_Ungetc(c1); } break; case '&': /* &=, && */ case '|': /* |=, || */ c1 = ncss_Getchar(); if (c1 == '=') { c = T_ASSIGN; } else if (c1 == c) { c = T_LOGICAL; } else { ncss_Ungetc(c1); } break; case '<': /* >>= */ case '>': /* <<= */ c1 = ncss_Getchar(); if (c1 == c) { c2 = ncss_Getchar(); if (c2 == '=') { c = T_ASSIGN; } else { ncss_Ungetc(c2); } } else { ncss_Ungetc(c1); } break; } if (ISIDENT1(c)) { *buf++ = c; ncss_Ungetc(getsimpleident(buf)); c = identify(buf - 1); } return c; } void operatorident(char *s, int c) /* * We're in an operator-overloaded C++ identifier. This isn't * perfect but we read until either ( or ; to guess the identifier's * name. In this pass we also replace whitespace with _ for printing. */ { while (c != EOF) { if (ISSPACE(c)) { ncss_Ungetc(skipws()); *s++ = '_'; } else if (c == '(' || c == ';') { ncss_Ungetc(c); break; } else { *s++ = c; } c = ncss_Getchar(); } if (s[-1] == '_') s[-1] = '\0'; else s[0] = '\0'; } pmccabe-v2.8/io.c000066400000000000000000000012561400136053700137210ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ #include #include "dmain.h" #include "pmccabe.h" int Line; int Unbuf[256]; int *Unptr = Unbuf; void Ungetc(int c) { if (c == '\n') { Line--; } *Unptr++ = c; } void Ungets(char *s) { int c; char *ptr; ptr = s + strlen(s); do { c = *--ptr; if (!ISSPACE(c)) { if (c == '\n') { Line--; } } *Unptr++ = c; } while (ptr != s); } int Getchar() { int c; if (Unptr == Unbuf) { if (Piperead >= Pipewrite) decomment(); c = *Piperead++; } else { c = *--Unptr; } if (c == '\n') Line++; return c; } pmccabe-v2.8/makefile.c6000066400000000000000000000005321400136053700151510ustar00rootroot00000000000000CC = CL -DMSC6 CFLAGS = -AS -G2 LDFLAGS = -F 8000 LD = CL MAKEFILE = Makefile CFILES = cparse.c \ dmain.c \ gettoken.c \ io.c \ nmain.c \ pmccabe.c OFILES = $(CFILES:.c=.obj) PROGRAM = pmccabe.exe all: $(PROGRAM) $(PROGRAM): $(OFILES) $(LD) $(CFLAGS) $(LDFLAGS) $(OFILES) -o $(PROGRAM) pmccabe-v2.8/nmain.c000066400000000000000000000121451400136053700144130ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ #include #if defined MSC6 || defined WIN32 #define MAXPATHLEN 1024 #else #include /* for MAXPATHLEN */ #endif #include #include #include "pmccabe.h" #include "dmain.h" /* $Id: nmain.c,v 1.23 2001/01/26 23:00:37 bame Exp $ */ int Exit = 0; void file(char *fname, FILE * f) { stats_t *filestats; extern int Unbuf[], *Unptr; extern int Pass1; Input = f; if (Pass1) { int c; extern bool Cppflag; Cppflag = true; while ((c = Getchar()) != EOF) { putc(c, stdout); } return; } Unptr = Unbuf; Line = 1; ncss_Line = 0; ZERO(filestats); filestats = stats_push(fname, STATS_FILE); filestats->firstline = 1; while (toplevelstatement(filestats) != EOF) { filestats->nsemicolons++; } filestats->lastline = Line - 1; /* Not 100% sure why I need to subtract 1 here */ filestats->nLines += ncss_Line - 1; if (Files) printstats(filestats); stats_pop(filestats); } void cycoprintstats(stats_t * fs, stats_t * fn) { int basic, cycloswitch, cyclocase; basic = fn->nfor + fn->nwhile + fn->nif + fn->nand + fn->nor + fn->nq; cycloswitch = 1 + basic + fn->nswitch; cyclocase = 1 + basic + fn->ncase; printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\t%s\n", cycloswitch, cyclocase, fn->nstatements, fn->firstline, fn->defline, fn->lastline, fn->lastline - fn->firstline + 1, fs->name, fn->name); } void softbuildprintstats(stats_t * fs, stats_t * fn) { int basic, cycloswitch, cyclocase; basic = fn->nfor + fn->nwhile + fn->nif + fn->nand + fn->nor + fn->nq; cycloswitch = 1 + basic + fn->nswitch; cyclocase = 1 + basic + fn->ncase; printf("\"%s\", line %d: %s%%\t%d\t%d\t%d\t%d\t%d\n", fs->name, fn->defline, fn->name, cycloswitch, cyclocase, fn->nstatements, fn->firstline, fn->lastline - fn->firstline + 1); } static void printname(stats_t * sp) { if (sp != NULL) { printname(sp->prev); switch (sp->type) { case STATS_TOTAL: case STATS_FILE: break; case STATS_FUNCTION: printf("%s", sp->name); break; case STATS_CLASS: if (sp->prev != NULL && sp->prev->type == STATS_FUNCTION) printf("/"); printf("%s::", sp->name); break; case STATS_NAMESPACE: printf("%s::", sp->name); break; } } } void printstats(stats_t * sp) { int basic, cycloswitch, cyclocase; int snlines; stats_t *fsp; basic = sp->nfor + sp->nwhile + sp->nif + sp->nand + sp->nor + sp->nq; sp->nstatements = basic - sp->nand - sp->nor + sp->nsemicolons; cycloswitch = sp->nfunctions + basic + sp->nswitch; cyclocase = sp->nfunctions + basic + sp->ncase; /* fix bug observed by Ahmad Jbara */ /* where #statements weren't counting switch */ sp->nstatements += sp->nswitch; if (Threshold != 0 && cycloswitch < Threshold) { return; } for (fsp = sp; fsp != NULL && fsp->type != STATS_FILE; fsp = fsp->prev) { } if (Ncssfunction) { snlines = sp->nLines + 1; } else { snlines = sp->lastline - sp->firstline + 1; } switch (sp->type) { case STATS_TOTAL: if (Softbuild) { printf("\"n/a\", line n/a: %s", sp->name); printf("%%\t%d\t%d\t%d\tn/a\t%d\n", cycloswitch, cyclocase, sp->nstatements, snlines); } else if (Cyco) { printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\n", cycloswitch, cyclocase, sp->nstatements, sp->firstline, sp->defline, sp->lastline, snlines, "Total"); } else { printf("%d\t%d\t%d\tn/a\t%d\t", cycloswitch, cyclocase, sp->nstatements, snlines); printf("Total\n"); } break; case STATS_FILE: assert(fsp != NULL); if (Softbuild) { printf("\"%s\", line 1: n/a", fsp->name); printf("%%\t%d\t%d\t%d\t%d\t%d\n", cycloswitch, cyclocase, sp->nstatements, sp->firstline, snlines); } else if (Cyco) { printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\n", cycloswitch, cyclocase, sp->nstatements, sp->firstline, sp->defline, sp->lastline, snlines, fsp->name); } else { printf("%d\t%d\t%d\t%d\t%d\t", cycloswitch, cyclocase, sp->nstatements, sp->firstline, snlines); printf("%s\n", fsp->name); } break; case STATS_FUNCTION: assert(fsp != NULL); if (Softbuild) { printf("\"%s\", line %d: ", fsp->name, sp->defline); printname(sp); printf("%%\t%d\t%d\t%d\t%d\t%d\n", cycloswitch, cyclocase, sp->nstatements, sp->firstline, snlines); } else if (Cyco) { printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s\t", cycloswitch, cyclocase, sp->nstatements, sp->firstline, sp->defline, sp->lastline, snlines, fsp->name); printname(sp); putchar('\n'); } else { printf("%d\t%d\t%d\t%d\t%d\t", cycloswitch, cyclocase, sp->nstatements, sp->firstline, snlines); printf("%s(%d): ", fsp->name, sp->defline); printname(sp); printf("\n"); } break; case STATS_CLASS: abort(); if (Softbuild) { } else if (Cyco) { } else { } break; } } pmccabe-v2.8/pdiff000077500000000000000000000042421400136053700141620ustar00rootroot00000000000000#!/bin/sh case $# in 2) olddir=$1; newdir=$2; usefind=true;; 4) olddir=$1; oldlist=$2; newdir=$3; newlist=$4; usefind=false;; *) echo "Usage: $0 old-code-directory new-code-directory" >&2 echo "Usage: $0 old-code-directory old-files-list new-code-directory new-files-list" >&2 exit 2 ;; esac pmccabe -V >&2 cycocvt() { local line while read line do set -- $line printf "%s/%s\t%s\t%s\t%s\t%s\n" $8, $9, $1, $2, $3, $7 done } find_sources() { find . -type f -print | grep \ -e '\.[cChH]$' \ -e '\.cpp$' \ -e '\.cxx$' \ -e '\.c++$' \ -e '\.cc$' } trap "rm -f old.1 new.1" 0 1 2 3 15 printf 'Analyzing %s ...' "$olddir" >&2 ( cd $olddir if $usefind then find_sources else cat $oldlist fi | xargs pmccabe -C ) | cycocvt | sort >old.1 printf "\nAnalyzing %s ..." "$newdir" >&2 ( cd $newdir if $usefind then find_sources else cat $oldlist fi | xargs pmccabe -C ) | cycocvt | sort >new.1 echo >&2 echo >&2 { echo "@@@@@ common" join old.1 new.1 echo "@@@@@ old" join -v 1 old.1 new.1 echo "@@@@@ new" join -v 2 old.1 new.1 } | awk ' BEGIN { OFS = "\t" print "", "Modified McCabe Cyclomatic Complexity" print "", "| Traditional McCabe Cyclomatic Complexity" print "", "| | # Statements in function" print "", "| | | # lines in function" print "", "+-------+--------+------+---------------file name/function name" } ($1 == "@@@@@") { file = $2; next } (file == "common") { print "", total($6 - $2, $7 - $3, $8 - $4, $9 - $5), $1 } (file == "old") { print "Deleted", total(-$2, -$3, -$4, -$5), $1 } (file == "new") { print "New", total($2, $3, $4, $5), $1 } function total(m1, m2, statements, lines, s) { tm1 += m1 tm2 += m2 tstatements += statements tlines += lines if (m1 > 0) s = s "+"; s = s m1 "\t"; if (m2 > 0) s = s "+"; s = s m2 "\t"; if (statements > 0) s = s "+"; s = s statements "\t"; if (lines > 0) s = s "+"; s = s lines "\t"; return s } END { print "-----", total(tm1, tm2, tstatements, tlines), "Total" } ' pmccabe-v2.8/pkg-linux000077500000000000000000000003571400136053700150130ustar00rootroot00000000000000#!/bin/ksh mkdir -p pkg pkg/usr/local/bin pkg/usr/local/man/man1 cp -f pmccabe decomment codechanges pkg/usr/local/bin cp -f pmccabe.1 codechanges.1 pkg/usr/local/man/man1 (cd pkg && tar cvfz ../pmccabe.tar.gz $(find . -type f -print)) pmccabe-v2.8/pmccabe.1000066400000000000000000000161061400136053700146220ustar00rootroot00000000000000.TH "pmccabe" 1 17Jan2021 .SH NAME pmccabe \- calculate McCabe cyclomatic complexity or non-commented line counts for C and C++ programs .SH SYNOPSIS .B pmccabe [-bCdfFntTvVxX?] [file(s)] .SH DESCRIPTION .I pmccabe processes the named files, or standard input if none are named. In default mode it calculates statistics including McCabe cyclomatic complexity for each function. The files are expected to be either C (ANSI or K&R) or C++. .TP .B -? Print an informative usage message. .TP .B -v Print column headers .TP .B -V Print .I pmccabe version number .SS De-commenting mode .TP .B -d Intended to help count non-commented source lines via something like: .IP \fCpmccabe -d *.c | grep -v '^[]*$' | wc -l\fR Comments are removed, .I cpp directives are replaced by \fBcpp\fR, string literals are replaced by \fBSTRINGLITERAL\fR, character constants are replaced by \fBCHARLITERAL\fR. The resulting source code is much easier to parse. This is the first step performed by .I pmccabe so that its parser can be simpler. .P Only .B -X and .B -x work sensibly with .BR -d . .TP .B -X instructs .I pmccabe to use a better approximation of the C preprocessor (courtesy of Matt Hargett) than the original one. .B WARNING! if you have archived results using the old algorithm, they may break because .B -X is now the default. .TP .B -x .I pmccabe uses the original rudimentary approximation of the C preprocessor (described below). .B WARNING! This is no longer the default algorithm as of version 2.8 and may be removed after version 2.8. .SS Line-counting mode .TP .B -n Counts non-commented source lines. The output format is identical to that of the .I anac program except that column headers and totals must be requested if desired. If you want column headers add .BR -v . If you want totals add .BR -t . If all you want is totals add .BR -T . .SS Complexity mode (default) .TP .B -C Custom output format - don't use it. .TP .B -c Report non-commented, non-blank lines per function (and file) instead of the raw number of lines. .B "Note that pre-processor directives are NOT counted." .TP .B -b Output format compatible with compiler error browsing tools which understand "classic" compiler errors. Numerical sorting on this format is possible using: .IP "" \fCsort -n +1 -t%\fR .TP .B -t Print column totals. Note the total number of lines is *NOT* the number of non-commented source lines - it's the same as would be reported by \fC"wc -l"\fR. .TP .B -T Print column totals *ONLY*. .TP .B -f Include per-file totals along with the per-function totals. .TP .B -F Print per-file totals but NOT per-function totals. .SS Parsing .I pmccabe ignores all .I cpp preprocessor directives - calculating the complexity of the appearance of the code rather than the complexity after the preprocessor mangles the code. This is especially important since simple things like .I getchar(3) expand into macros which increase complexity. .SS "Output Format" A line is written to standard output for each function found of the form: .IP .nf \fCModified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 5 6 11 34 27 gettoken.c(35): matchparen\fR .fi .PP Column 1 contains cyclomatic complexity calculated by adding 1 (for the function) to the occurrences of .BR for , .BR if , .BR while , .BR switch , .BR && , .BR || , and .BR ? . Unlike "normal" McCabe cyclomatic complexity, each case in a switch statement is not counted as additional complexity. This treatment of switch statements and complexity may be more useful than the "normal" measure for judging maintenance effort and code difficulty. Column 2 is the cyclomatic complexity calculated in the "usual" way with regard to switch statements. Specifically it is calculated as in column 1 but counting each .BR case rather than the .BR switch and may be more useful than column 1 for judging testing effort. Column 3 contains a statement count. It is calculated by adding each occurrence of .BR for , " if" , " while" , .BR switch , .BR ? , and semicolon within the function. One possible surprise is that .BR for statements have a minimum statement count of 3. This is realistic since .BR "for(A; B; C){...}" is really shorthand for .BR "A; while (B) { ... C;}" . The number of statements within a file is the sum of the number of statements for each function implemented within that file, plus one for each of those functions (because functions are statements too), plus one for each other file-scoped statement (usually declarations). Column 4 contains the first line number in the function. This is not necessarily the same line on which the function name appears. Column 5 is the number of lines of the function, from the number in column 4 through the line containing the closing curly brace. The final column contains the file name, line number on which the function name occurs, and the name of the function. .SH APPLICATIONS The obvious application of \fIpmccabe\fR is illustrated by the following which gives a list of the "top ten" most complex functions: .IP .nf \fCpmccabe *.c | sort -nr | head -10\fR .fi .PP Many files contain more than one C function and sometimes it would be useful to extract each function separately. \fBmatchparen()\fR (see example output above) can be extracted from gettoken.c by extracting 27 lines starting with line 34. This can form the basis of tools which operate on functions instead of files (e.g., use as a front-end for \fIdiff(1)\fR). .SH DIAGNOSTICS .I pmccabe returns a nonzero exit status if files could not be opened and upon encountering some parsing errors. Error messages to standard error, usually explaining that the parser is confused about something, mimic classic C compiler error messages. .SH WARNINGS .I pmccabe is confused by unmatched curly braces or parentheses which sometimes occur with hasty use of .I cpp directives. In these cases a diagnostic is printed and the complexity results for the files named may be unreliable. Most times the "#ifdef" directives may be modified such that the curly braces match. Note that if .I pmccabe is confused by a .I cpp directive, most pretty printers will be too. In some cases, preprocessing with .IR unifdef (1) may be appropriate. Statement counting could arguably be improved by: counting occurrences of the comma operator, multiple assignments, assignments within conditional tests, and logical conjunction. However since there is no crisp statement definition from the language or from people I've queried, statement counting will probably not be improved. If you have a crisp definition I'll be happy to consider it. Templates cause .IR pmccabe 's scanner to exit. It's a shame that .I ctags output isn't provided. .SH AUTHOR Paul Bame .SH "SEE ALSO" .IR codechanges (1), .IR decomment (1), .IR vifn (1), .IR sort (1), .IR diff (1), .IR wc (1), .IR grep (1), .IR unifdef (1), .IR head (1), .IR anac (1) https://gitlab.com/pmccabe/pmccabe pmccabe-v2.8/pmccabe.c000066400000000000000000000145051400136053700147050ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ #ifdef __hpux /* Required for access to 'optind' for getopt() on HP-UX 9 */ #define _HPUX_SOURCE 1 #endif #include #include #include #include #include #include "pmccabe.h" #ifdef WIN32 #include "getopt.h" #endif #ifdef NEED_OPTIND extern int optind; #endif #ifdef NEED_OPTARG extern char *optarg; #endif static const char _Version[] = "@(#) pmccabe 2.8"; int Cyco = 0; int Softbuild = 0; int Verbose = 0; int Pass1 = 0; int Totals = 0; int Totalsonly = 0; int Threshold = 0; int Files = 0; int Filesonly = 0; int Ncss = 0; int Ncssfunction = 0; bool BetterDecomment = true; static char Normalheader[] = "Modified McCabe Cyclomatic Complexity\n" "| Traditional McCabe Cyclomatic Complexity\n" "| | # Statements in function\n" "| | | First line of function\n" "| | | | # lines in function\n" "| | | | | filename(definition line number):function\n" "| | | | | |\n"; static char NCSSheader[] = "Modified McCabe Cyclomatic Complexity\n" "| Traditional McCabe Cyclomatic Complexity\n" "| | # Statements in function\n" "| | | First line of function\n" "| | | | # uncommented nonblank lines in function\n" "| | | | | filename(definition line number):function\n" "| | | | | |\n"; static char Usage[] = "Usage: %s [-vdCbtTfFVn]\n" "\t-V\tPrint pmccabe version information\n" "\t-v\tVerbose - print column headers (nonsense with -b or -C)\n" "\t-t\tPrint totals\n" "\t-T\tPrint totals only\n" "\tMajor Modes:\n" "\t -d\tDe-comment only - can be used to count non-commented\n" "\t \tsource lines for example.\n" "\t -n\tCount non-commented source lines\n" "\t *\tDefault mode: count complexity, #statements, etc...\n" "\t\t-C\tA custom output format\n" "\t\t-c\tCount noncommented lines/function instead of\n" "\t\t\traw lines/function\n" "\t\t-b\tAn output format compatible with softbuild and other\n" "\t\t\ttools which understand traditional compiler errors\n" "\t\t-f\tPrint per-file complexity totals\n" "\t\t-F\tPrint per-file complexity totals only\n" "\t\t-X\tUse the better de-commenting/CPP algorithm\n" "\t\t-x\tUse the rudimentary de-commenting/CPP algorithm (temporary default)\n" "\t\t-r COMPLEXITY\tOnly output if complexity beyond the specified threshold\n"; int main(int argc, char *argv[]) { int result = 0; int c; char *progname = argv[0]; /* grab command-line options */ while ((c = getopt(argc, argv, "CvbdTtfFVncr:Xx")) != EOF) { switch (c) { case 'c': Ncssfunction = 1; break; case 'C': Cyco = 1; break; case 'v': Verbose = 1; break; case 'b': Softbuild = 1; break; case 'd': Pass1 = 1; break; case 'T': Totalsonly = 1; Totals = 1; break; case 't': Totals = 1; break; case 'f': Files = 1; break; case 'F': Filesonly = 1; Files = 1; break; case 'V': puts(_Version); return 0; break; case 'n': Ncss = 1; break; case 'x': BetterDecomment = false; break; case 'X': BetterDecomment = true; break; case 'r': Threshold = atoi(optarg); if (Threshold < 2) { fprintf(stderr, "Threshold must be greater than 1\n"); exit(3); } break; case '?': default: fprintf(stderr, Usage, progname); exit(3); break; } } SHIFT(optind - 1); if (Pass1) result = decomment_files(argc, argv); else if (Ncss) result = ncss_files(argc, argv); else { stats_t *total = stats_push("Total", STATS_TOTAL); total->firstline = 1; if (Verbose && !Cyco && !Softbuild) { fputs(Ncssfunction ? NCSSheader : Normalheader, stdout); } if (argc == 1) { file("stdin", stdin); } else { while (argc > 1) { FILE *f; if ((f = fopen(argv[1], "r")) == NULL) { result = 2; perror(argv[1]); } else { file(argv[1], f); fclose(f); } SHIFT(1); } } if (Totals) { printstats(total); } } return result; } static stats_t Stats[MAXDEPTH]; int Nstats = 0; /* These are cheating */ #define STOTAL Stats[0] #define SFILE Stats[1] stats_t * stats_push(const char *name, int type) { stats_t *sp; if (Nstats == MAXDEPTH) { fprintf(stderr, "Maximum name nesting depth (%d) exceed - exit\n", MAXDEPTH); exit(3); } sp = &Stats[Nstats++]; ZERO(*sp); if (Nstats > 1) sp->prev = sp - 1; sp->name = strdup(name); sp->type = type; return sp; } stats_t * stats_current() { if (Nstats < 1) { fprintf(stderr, "stats_current() called with Nstats < 1 -- exit\n"); exit(3); } return Stats + Nstats - 1; } stats_t * stats_pop(stats_t * sp) { assert(sp != NULL); if (sp != NULL) { if (sp != stats_current()) { fprintf(stderr, "stats_pop() popped value not current value - exit\n"); exit(3); } } if (Nstats == 0) { fprintf(stderr, "stats_pop() can't pop zero-length stack - exit\n"); exit(3); } stats_accumulate(sp); free(sp->name); Nstats--; return stats_current(); } static void stats_add(stats_t * result, stats_t * sp) { result->nfor += sp->nfor; result->nwhile += sp->nwhile; result->nif += sp->nif; result->nand += sp->nand; result->nor += sp->nor; result->nq += sp->nq; result->nsemicolons += sp->nsemicolons; result->nswitch += sp->nswitch; result->ncase += sp->ncase; result->nstatements += sp->nstatements; result->nfunctions += sp->nfunctions; result->lastline += sp->lastline - sp->firstline + 1; result->nLines += sp->nLines; } void stats_accumulate(stats_t * sp) { stats_t *result; for (result = sp->prev; result != NULL; result = result->prev) { if (result->type == STATS_FILE || result->type == STATS_TOTAL) break; } if (result == NULL) { fprintf(stderr, "Error in stats_accumulate() - exit\n"); exit(3); } stats_add(result, sp); } void fileerror(const char *error) { fprintf(stderr, "\"%s\", line %d: %s\n", SFILE.name, Line, error); } pmccabe-v2.8/pmccabe.dsp000066400000000000000000000074021400136053700152470ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="pmccabe" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 5.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=pmccabe - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "pmccabe.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "pmccabe.mak" CFG="pmccabe - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "pmccabe - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "pmccabe - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "pmccabe - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib /nologo /subsystem:console /machine:I386 /out:"win32/pmccabe.exe" # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "pmccabe - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib /nologo /subsystem:console /debug /machine:I386 /out:"win32/pmccabed.exe" /pdbtype:sept # SUBTRACT LINK32 /pdb:none !ENDIF # Begin Target # Name "pmccabe - Win32 Release" # Name "pmccabe - Win32 Debug" # Begin Source File SOURCE=.\cparse.c # End Source File # Begin Source File SOURCE=.\dmain.c # End Source File # Begin Source File SOURCE=.\dmain.h # End Source File # Begin Source File SOURCE=.\getopt.c # End Source File # Begin Source File SOURCE=.\getopt.h # End Source File # Begin Source File SOURCE=.\gettoken.c # End Source File # Begin Source File SOURCE=.\io.c # End Source File # Begin Source File SOURCE=.\nmain.c # End Source File # Begin Source File SOURCE=.\pmccabe.c # End Source File # Begin Source File SOURCE=.\pmccabe.h # End Source File # End Target # End Project pmccabe-v2.8/pmccabe.h000066400000000000000000000073671400136053700147220ustar00rootroot00000000000000/* Copyright (c) 2002 Hewlett-Packard under GPL version 2 or later */ #ifndef _PMCCABE_H_ #define _PMCCABE_H_ #include #include #include #include #ifdef __hpux #include #endif #include /* Returned by gettoken() */ #define T_BASE 256 #define T_ASSIGN (T_BASE + 0) #define T_LOGICAL (T_BASE + 1) /* non-commented nuline returned by ncss_Getchar() */ #define T_NCNULINE (T_BASE + 1) #define T_WORDS (T_BASE + 20) #define T_IDENT (T_WORDS + 2) #define T_IF (T_WORDS + 3) #define T_WHILE (T_WORDS + 4) #define T_CASE (T_WORDS + 5) #define T_SWITCH (T_WORDS + 6) #define T_FOR (T_WORDS + 7) #define T_UNION (T_WORDS + 8) #define T_STRUCT (T_WORDS + 9) #define T_CLASS (T_WORDS + 10) #define T_OPERATOR (T_WORDS + 11) #define T_CONST (T_WORDS + 12) #define T_NAMESPACE (T_WORDS + 13) #define T_THROW (T_WORDS + 14) #define T_VOLATILE (T_WORDS + 15) #define T_ENUM (T_WORDS + 16) #define STREQUAL(a, b) (strcmp((a),(b)) == 0) #define ZERO(x) memset(&x, 0, sizeof x) #define SHIFT(n) argc -= (n); argv += (n) /* values for stats_t.type */ #define STATS_TOTAL 0 #define STATS_FILE 1 #define STATS_FUNCTION 2 #define STATS_CLASS 3 #define STATS_NAMESPACE 4 struct stats_t { char *name; int nstatements; int nfunctions; int firstline; int lastline; int defline; int nLines; int nfor, nwhile, nswitch, ncase, nif; int nand, nor, nq; int nsemicolons; struct stats_t *prev; char type; }; typedef struct stats_t stats_t; /* can only nest this many names, including Total and file name */ #define MAXDEPTH 100 extern int Line, Linetokens, ncss_Line; extern int Exit; /* pmccabe.c - command-line options */ extern int Cyco; extern int Softbuild; extern int Verbose; extern int Pass1; extern int Totals; extern int Totalsonly; extern int Files; extern int Filesonly; extern int Threshold; extern int Line; extern int Ncss; extern int Ncssfunction; extern int Unbuf[256]; extern int *Unptr; /* cparse.c */ int fancygettoken(char *buf, int classflag, int *line, int *nLine); int toplevelstatement(stats_t * stats); int findchar(char fc); bool maybeclass(void); bool maybenamespace(void); void findsemicolon(); int getoverloadedop(char *buf); int fancyfunction(char *buf, stats_t * fs, stats_t * fn); void possiblefn(stats_t * stats, const char *name, int line1, int defline, int nLine1); int prefunction(int *nstatements); int countfunction(stats_t * fn); void countword(stats_t * fn, int id); bool is_c_plus_plus(stats_t * stats, const char *name); /* dmain.c */ void decomment(void); int decomment_files(int argc, char *argv[]); int ncss_files(int argc, char *argv[]); /* gettoken.c */ int matchcurly(); int matchparen(void); int skipws(void); int getsimpleident(char *buf); void ungettoken(int c, char *s); int gettoken(char *buf, int *line, int *nLine); int gettoken2(char *buf, int *line, int *nLine); void operatorident(char *s, int c); int identify(const char *ident); void Ungetc(int c); void ncss_Ungetc(int c); void Ungets(char *s); void ncss_Ungets(char *s); int Getchar(void); int ncss_Getchar(void); /* nmain.c */ void file(char *fname, FILE * f); void cycoprintstats(stats_t * fs, stats_t * fn); void softbuildprintstats(stats_t * fs, stats_t * fn); void printstats(stats_t * sp); void fileerror(const char *s); /* pmccabe.c */ int main(int argc, char *argv[]); stats_t *stats_push(const char *name, int type); stats_t *stats_current(void); stats_t *stats_pop(stats_t * sp); void stats_accumulate(stats_t * sp); #define ISSPACE(c) ((c) == T_NCNULINE || (c) == '\n' \ || (c) == '\t' || (c) == ' ' \ || (c) == '\r') #define ISIDENT1(c) (((c) >= 'a' && (c) <= 'z') \ || ((c) >= 'A' && (c) <= 'Z') \ || ((c) == '_')) #define ISIDENT(c) ((ISIDENT1(c)) || ((c) >= '0' && (c) <= '9')) #endif pmccabe-v2.8/test017.out000066400000000000000000000007361400136053700151100ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 8 Total CSL PCT NCSL PCT TOTAL FILENAME 1 12 7 88 8 test017 1 12 7 88 8 (total files: 1) pmccabe-v2.8/test018.out000066400000000000000000000007701400136053700151070ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 5 1 test018(5): foo 1 1 1 n/a 5 Total CSL PCT NCSL PCT TOTAL FILENAME 2 40 3 60 5 test018 2 40 3 60 5 (total files: 1) pmccabe-v2.8/test019.out000066400000000000000000000007371400136053700151130ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 23 Total CSL PCT NCSL PCT TOTAL FILENAME 4 17 19 83 23 test019 4 17 19 83 23 (total files: 1) pmccabe-v2.8/test020.out000066400000000000000000000007371400136053700151030ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 21 Total CSL PCT NCSL PCT TOTAL FILENAME 0 0 21 100 21 test020 0 0 21 100 21 (total files: 1) pmccabe-v2.8/test021.out000066400000000000000000000010211400136053700150670ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 4 4 4 14 24 test021(14): total_lack_of_modularity 4 4 5 n/a 41 Total CSL PCT NCSL PCT TOTAL FILENAME 12 29 29 71 41 test021 12 29 29 71 41 (total files: 1) pmccabe-v2.8/test022.out000066400000000000000000000007361400136053700151040ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 0 n/a 6 Total CSL PCT NCSL PCT TOTAL FILENAME 1 17 5 83 6 test022 1 17 5 83 6 (total files: 1) pmccabe-v2.8/test023.out000066400000000000000000000007371400136053700151060ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 0 n/a 10 Total CSL PCT NCSL PCT TOTAL FILENAME 5 50 5 50 10 test023 5 50 5 50 10 (total files: 1) pmccabe-v2.8/test024.out000066400000000000000000000010241400136053700150750ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 3 11 test024(3): RescaleBlock_5x1555_To_4x1555 1 1 1 n/a 13 Total CSL PCT NCSL PCT TOTAL FILENAME 8 62 5 38 13 test024 8 62 5 38 13 (total files: 1) pmccabe-v2.8/test025.out000066400000000000000000000007371400136053700151100ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 49 Total CSL PCT NCSL PCT TOTAL FILENAME 3 6 46 94 49 test025 3 6 46 94 49 (total files: 1) pmccabe-v2.8/test026.out000066400000000000000000000026261400136053700151100ustar00rootroot00000000000000Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 49 3 test026(49): Tinsel::TinselEngine::getGameID 1 1 1 53 3 test026(53): Tinsel::TinselEngine::getFeatures 1 1 1 57 3 test026(57): Tinsel::TinselEngine::getLanguage 1 1 1 61 3 test026(61): Tinsel::TinselEngine::getPlatform 1 1 1 65 3 test026(65): Tinsel::TinselEngine::getVersion 1 1 1 107 1 test026(107): TinselMetaEngine::TinselMetaEngine 1 1 1 109 3 test026(109): TinselMetaEngine::getName 1 1 1 113 3 test026(113): TinselMetaEngine::getOriginalCopyright 3 3 1 126 6 test026(126): TinselMetaEngine::hasFeature 1 1 1 133 8 test026(133): Tinsel::TinselEngine::hasFeature 3 3 22 146 30 test026(146): TinselMetaEngine::listSaves 2 2 4 177 7 test026(177): TinselMetaEngine::createInstance 38 38 109 197 155 test026(197): TinselMetaEngine::fallbackDetect 1 1 1 353 1 test026(353): TinselMetaEngine::getMaximumSaveSlot 1 1 5 355 8 test026(355): TinselMetaEngine::removeSaveState 4 4 14 372 42 test026(372): Tinsel::TinselEngine::loadGameState 61 61 182 n/a 425 Total CSL PCT NCSL PCT TOTAL FILENAME 155 36 270 64 425 test026 155 36 270 64 425 (total files: 1) pmccabe-v2.8/tests/000077500000000000000000000000001400136053700143045ustar00rootroot00000000000000pmccabe-v2.8/tests/test000000066400000000000000000000021071400136053700154260ustar00rootroot00000000000000 #include #include Add::Add(Expr *e1, Expr *e2) { _result.TypePtr(e1->eval_type()); _left = e1; _right = e2; } Add::~Add() { delete _left; delete _right; } void Add::print(ostream &o) const { PrintBinaryExpression(o,*_left,"+",*_right); } const TypedValue &Add::eval(ValueStore &t) { const TypedValue &left = _left->eval(t); const TypedValue &right = _right->eval(t); if(!left.HasValue() || !right.HasValue()) { _result.ResetValue(); return _result; } switch(left.Type()) { case TypeInt: case TypeTime: _result = (int)left + (int)right; break; case TypeFloat: _result = (float)left + (float)right; break; case TypeString: { Str s=(const char *)left; s += (const char *)right; _result = strdup(s); } break; case TypeDate: _result = (time_t)left + (time_t)right; break; default: _result.ResetValue(); } return _result; } Boolean Add::modified_attributes(ConstCharPtrArray *arr, Boolean /*in_lvalue*/) { return _left->modified_attributes(arr,FALSE) + _right->modified_attributes(arr,FALSE); } pmccabe-v2.8/tests/test000.ref000066400000000000000000000024311400136053700162010ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test000 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 3 6 6 test000(6): Add::Add 1 1 2 13 5 test000(13): Add::~Add 1 1 1 19 4 test000(19): Add::print 4 8 18 24 35 test000(24): Add::eval 1 1 1 60 4 test000(60): Add::modified_attributes 8 12 30 n/a 64 Total RUN: ../pmccabe -X -vnt test000 CSL PCT NCSL PCT TOTAL FILENAME 10 16 54 84 64 test000 10 16 54 84 64 (total files: 1) RUN: ../pmccabe -x -vt test000 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 3 6 6 test000(6): Add::Add 1 1 2 13 5 test000(13): Add::~Add 1 1 1 19 4 test000(19): Add::print 4 8 18 24 35 test000(24): Add::eval 1 1 1 60 4 test000(60): Add::modified_attributes 8 12 30 n/a 64 Total pmccabe-v2.8/tests/test001000066400000000000000000000006521400136053700154320ustar00rootroot00000000000000 start() { } storage_class type some_class :: ~ some_class (){} destructor :: ~ destructor (int a) {} destructor2::~ destructor (int a) {} int main(int argc, char *argv[]): ident(args), ident(args) { body1; body2; } xyzzy :: operator () (int a, int b) {} class named_class { private: int member_function(){}; }; class /* unnamed_class */ { int member_function(){}; } xyzzy :: operator += (int a, int b) { } pmccabe-v2.8/tests/test001.ref000066400000000000000000000032531400136053700162050ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test001 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 2 3 test001(2): start 1 1 0 7 6 test001(12): some_class::~some_class 1 1 0 14 1 test001(14): destructor::~destructor 1 1 0 15 1 test001(15): destructor2::~destructor 1 1 4 17 4 test001(17): main 1 1 0 22 1 test001(22): xyzzy::operator() 1 1 0 27 1 test001(27): named_class::member_function 1 1 0 32 1 test001(32): unnamed::member_function 1 1 0 35 3 test001(36): xyzzy::operator+= 9 9 12 n/a 37 Total RUN: ../pmccabe -X -vnt test001 CSL PCT NCSL PCT TOTAL FILENAME 9 24 28 76 37 test001 9 24 28 76 37 (total files: 1) RUN: ../pmccabe -x -vt test001 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 2 3 test001(2): start 1 1 0 7 6 test001(12): some_class::~some_class 1 1 0 14 1 test001(14): destructor::~destructor 1 1 0 15 1 test001(15): destructor2::~destructor 1 1 4 17 4 test001(17): main 1 1 0 22 1 test001(22): xyzzy::operator() 1 1 0 27 1 test001(27): named_class::member_function 1 1 0 32 1 test001(32): unnamed::member_function 1 1 0 35 3 test001(36): xyzzy::operator+= 9 9 12 n/a 37 Total pmccabe-v2.8/tests/test002000066400000000000000000000002001400136053700154200ustar00rootroot00000000000000class1::class2::class3::member (int a) {stuff;} class1::class2::operator +=(int a) {impl;} class4::operator +=(int a) {impl;} pmccabe-v2.8/tests/test002.ref000066400000000000000000000022771400136053700162130ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test002 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 1 1 test002(1): class1::class2::class3::member 1 1 1 3 1 test002(3): class1::class2::operator+= 1 1 1 5 1 test002(5): class4::operator+= 3 3 6 n/a 5 Total RUN: ../pmccabe -X -vnt test002 CSL PCT NCSL PCT TOTAL FILENAME 2 40 3 60 5 test002 2 40 3 60 5 (total files: 1) RUN: ../pmccabe -x -vt test002 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 1 1 test002(1): class1::class2::class3::member 1 1 1 3 1 test002(3): class1::class2::operator+= 1 1 1 5 1 test002(5): class4::operator+= 3 3 6 n/a 5 Total pmccabe-v2.8/tests/test003000066400000000000000000000003051400136053700154270ustar00rootroot00000000000000 class T1 { int i; operator long(){return;}; }; class T2 { float f; operator long(); }; T1::operator long() { return long(i); } T2::operator long() { return long(f); } pmccabe-v2.8/tests/test003.ref000066400000000000000000000022471400136053700162110ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test003 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 6 1 test003(6): T1::operator_long() 1 1 1 15 4 test003(15): T1::operator_long() 1 1 1 20 4 test003(20): T2::operator_long() 3 3 7 n/a 24 Total RUN: ../pmccabe -X -vnt test003 CSL PCT NCSL PCT TOTAL FILENAME 6 25 18 75 24 test003 6 25 18 75 24 (total files: 1) RUN: ../pmccabe -x -vt test003 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 6 1 test003(6): T1::operator_long() 1 1 1 15 4 test003(15): T1::operator_long() 1 1 1 20 4 test003(20): T2::operator_long() 3 3 7 n/a 24 Total pmccabe-v2.8/tests/test004000066400000000000000000000003451400136053700154340ustar00rootroot00000000000000 class T1 { int i; operator long(); class /* unnamed */ { int member(int a) { return a; }; }; class T11 { class T12 { int member(int a, int b) { return a = b; }; } } }; pmccabe-v2.8/tests/test004.ref000066400000000000000000000021211400136053700162010ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test004 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 8 4 test004(8): T1::unnamed::member 1 1 1 17 4 test004(17): T1::T11::T12::member 2 2 0 n/a 23 Total RUN: ../pmccabe -X -vnt test004 CSL PCT NCSL PCT TOTAL FILENAME 1 4 22 96 23 test004 1 4 22 96 23 (total files: 1) RUN: ../pmccabe -x -vt test004 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 8 4 test004(8): T1::unnamed::member 1 1 1 17 4 test004(17): T1::T11::T12::member 2 2 0 n/a 23 Total pmccabe-v2.8/tests/test005000066400000000000000000000061301400136053700154330ustar00rootroot00000000000000#ifndef TYPEDVALUE_H #define TYPEDVALUE_H #include #include class TypedValue { const ValueType *_type; SimpleValue _simplevalue; SimpleValue *_valueptr; unsigned int _has_value:1; unsigned int _use_valueptr:1; static ValueType _StaticIntType; static ValueType _StaticFloatType; static ValueType _StaticDateType; static ValueType _StaticBooleanType; static ValueType _StaticStringType; static ValueType _StaticTimeType; public: Boolean HasValue() const {return _has_value;} void HasValue(Boolean flag) {_has_value = flag;} void ResetValue() {HasValue(FALSE);} void ResetValuePtr() {_use_valueptr=0; ResetValue();} const SimpleValue &Value() const {if(_use_valueptr) return (*_valueptr) ; else return _simplevalue;} SimpleValue &ValueRef() {if(_use_valueptr) return (*_valueptr); else re turn _simplevalue;} void Value(SimpleValue &v) {_valueptr = &v; _use_valueptr=1; HasValue(T RUE);} TypedValue() {_type = NULL; _has_value=0; _use_valueptr=0;} TypedValue(BaseType type); //TypedValue(TypedValue &); TypedValue(const ValueType *t) {_type = t; _has_value=0; _use_valueptr= 0;} TypedValue(const ValueType *t, SimpleValue *v) {_type = t; Value(*v);} ~TypedValue(); void DestroyValue() {} void Ref(TypedValue &); // set typed value to point to another typed va lue Boolean HasType() const {return _type!=NULL;} BaseType Type() const {return _type->Type();} void Type(BaseType); void TypePtr(const ValueType *t) {_type = t;} const ValueType *TypePtr() const {return _type;} Boolean operator=(const int v); Boolean operator=(const float v); Boolean operator=(const time_t v); Boolean operator=(const Boolean v); Boolean operator=(const char *s); Boolean operator=(const TypedValue &t); Boolean Assign(const char *s) {return this->operator=(s);} Boolean operator += (const TypedValue &t); boolean operator==(const TypedValue &)const; // test equality of typ e *and* value void print_type(ostream &o) const { if(_type)_type->print(o); else o << "no type";} void print_value(ostream &o) const; operator int() const; operator float() const; operator Boolean() const; operator time_t() const; operator char *() const; operator Str() const; // when value is an array, get (and create if not created) a reference to the element // returns TRUE if the element was created, FALSE otherwise Boolean GetElementReference(const char *, TypedValue &result); // when value is an array, get (but don't create) a value for the eleme nt // returns TRUE if value is put in result, FALSE otherwise Boolean GetElementValue(const char *, TypedValue &result) const; // return TRUE if element with given name exists in array Boolean FindElement(const char *); // when value is an array, remove element // returns TRUE if an element was removed, FALSE otherwise Boolean RemoveElement(const char *); // return number of elements in array long ArraySize() const; // get array indices of array value // returns TRUE if indices were put in array, FALSE otherwise Boolean GetIndices(StrArray &arr) const; friend ostream &operator<<(ostream &,const TypedValue &); }; #endif pmccabe-v2.8/tests/test005.ref000066400000000000000000000046551400136053700162200ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test005 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 22 1 test005(22): TypedValue::HasValue 1 1 1 23 1 test005(23): TypedValue::HasValue 1 1 1 24 1 test005(24): TypedValue::ResetValue 1 1 2 25 1 test005(25): TypedValue::ResetValuePtr 2 2 3 27 2 test005(27): TypedValue::Value 2 2 3 29 2 test005(29): TypedValue::ValueRef 1 1 3 31 2 test005(31): TypedValue::Value 1 1 3 34 1 test005(34): TypedValue::TypedValue 1 1 3 37 2 test005(37): TypedValue::TypedValue 1 1 2 39 1 test005(39): TypedValue::TypedValue 1 1 0 41 1 test005(41): TypedValue::DestroyValue 1 1 1 44 2 test005(45): TypedValue::HasType 1 1 1 46 1 test005(46): TypedValue::Type 1 1 1 49 1 test005(49): TypedValue::TypePtr 1 1 1 50 1 test005(50): TypedValue::TypePtr 1 1 1 58 1 test005(58): TypedValue::Assign 2 2 3 63 4 test005(65): TypedValue::print_type 20 20 31 n/a 103 Total RUN: ../pmccabe -X -vnt test005 CSL PCT NCSL PCT TOTAL FILENAME 32 31 71 69 103 test005 32 31 71 69 103 (total files: 1) RUN: ../pmccabe -x -vt test005 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 22 1 test005(22): TypedValue::HasValue 1 1 1 23 1 test005(23): TypedValue::HasValue 1 1 1 24 1 test005(24): TypedValue::ResetValue 1 1 2 25 1 test005(25): TypedValue::ResetValuePtr 2 2 3 27 2 test005(27): TypedValue::Value 2 2 3 29 2 test005(29): TypedValue::ValueRef 1 1 3 31 2 test005(31): TypedValue::Value 1 1 3 34 1 test005(34): TypedValue::TypedValue 1 1 3 37 2 test005(37): TypedValue::TypedValue 1 1 2 39 1 test005(39): TypedValue::TypedValue 1 1 0 41 1 test005(41): TypedValue::DestroyValue 1 1 1 44 2 test005(45): TypedValue::HasType 1 1 1 46 1 test005(46): TypedValue::Type 1 1 1 49 1 test005(49): TypedValue::TypePtr 1 1 1 50 1 test005(50): TypedValue::TypePtr 1 1 1 58 1 test005(58): TypedValue::Assign 2 2 3 63 4 test005(65): TypedValue::print_type 20 20 31 n/a 103 Total pmccabe-v2.8/tests/test006/000077500000000000000000000000001400136053700155115ustar00rootroot00000000000000pmccabe-v2.8/tests/test006/Grapher.H000066400000000000000000000015001400136053700172060ustar00rootroot00000000000000 /************************************************************************\ Grapher declaration \************************************************************************/ #define GrapherParent IlvGrapher #define GrapherParentPtr IlvGrapher* class Grapher: public GrapherParent { protected: XeGraphPtr xeg; static IlvDrawSelection* select(IlvManager* mgr, IlvGraphic* object); public: Grapher(XeGraphPtr g, IlvDisplay* display, int layers = 2, IlvBoolean useacc = IlvTrue, unsigned short maxInList = IlvMaxObjectsInList, unsigned short maxInNode = IlvMaxObjectsInList) : GrapherParent(display, layers, useacc, maxInList, maxInNode) { xeg = g; setMakeSelection(Grapher::select); } ~Grapher() { } XeGraphPtr xegraph() { return xeg; } }; pmccabe-v2.8/tests/test006/Grapher.H.ref000066400000000000000000000024011400136053700177620ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test006/Grapher.H Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 3 16 11 test006/Grapher.H(16): Grapher::Grapher 1 1 0 27 1 test006/Grapher.H(27): Grapher::~Grapher 1 1 1 29 1 test006/Grapher.H(29): Grapher::xegraph 3 3 5 n/a 32 Total RUN: ../pmccabe -X -vnt test006/Grapher.H CSL PCT NCSL PCT TOTAL FILENAME 11 34 21 66 32 test006/Grapher.H 11 34 21 66 32 (total files: 1) RUN: ../pmccabe -x -vt test006/Grapher.H Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 3 16 11 test006/Grapher.H(16): Grapher::Grapher 1 1 0 27 1 test006/Grapher.H(27): Grapher::~Grapher 1 1 1 29 1 test006/Grapher.H(29): Grapher::xegraph 3 3 5 n/a 32 Total pmccabe-v2.8/tests/test006/Handler.H000066400000000000000000000454441400136053700172120ustar00rootroot00000000000000 /************************************************************************\ classes used by GraphHandler \************************************************************************/ class ActionHandler; /* public IlvManagerViewInteractor */ class MotionHandler; /* public ActionHandler */ class Selector; /* public MotionHandler */ class SweepSelector; /* public Selector */ class SubgraphSelector; /* public Selector */ class ArcHandler; /* public MotionHandler */ class ArcMaker; /* public ArcHandler */ class ArcChanger; /* public ArcHandler */ class NodeMaker; /* public MotionHandler */ class ItemMover; /* public ActionHandler */ class NodeMover; /* public ItemMover */ class SelectionMover; /* public ItemMover */ class MenuHandler; /* public ActionHandler */ /************************************************************************\ GraphHandler declaration and implementation \************************************************************************/ #define GraphHandlerParent IlvManagerViewInteractor #define GraphHandlerParentPtr IlvManagerViewInteractor* class GraphHandler: public GraphHandlerParent { protected: IlvGraphic* _target; SweepSelector* _sweepSelector; SubgraphSelector* _subgraphSelector; Selector* _toggleSelector; Selector* _selector; NodeMover* _nodeMover; SelectionMover* _selectionMover; ArcMaker* _arcMaker; ArcChanger* _arcChanger; NodeMaker* _nodeMaker; MenuHandler* _menuHandler; public: GraphHandler(GrapherPtr graph, GraphViewPtr view); ~GraphHandler(); virtual void handleEvent(IlvEvent& event); virtual void doIt(IlvGraphic* graphic,const IlvPoint&); }; #define ActionHandlerParent IlvManagerViewInteractor #define ActionHandlerParentPtr IlvManagerViewInteractor* class ActionHandler: public ActionHandlerParent { protected: GraphHandler* _caller; IlvGraphic* _target; void returnControl() { if (_caller) { getManager()->setInteractor(_caller, getView()); } else { getManager()->removeInteractor(getView()); } } ActionHandler(GraphHandler* caller, GrapherPtr manager, IlvView* view) : ActionHandlerParent(manager, view), _caller(caller), _target(nil) { } public: void target(IlvGraphic* t) { _target = t; } IlvGraphic* target() { return _target; } IlvBoolean targetted() { return (_target) ? IlvTrue : IlvFalse; } virtual void handleEvent(IlvEvent& event); virtual void init() { ActionHandlerParent::init(); target(nil); } void takeCharge(IlvEvent& event, IlvGraphic* under = nil) { getManager()->setInteractor(this); target(under); handleEvent(event); } void abort() { ActionHandlerParent::abort(); target(nil); } }; #define MotionHandlerParent ActionHandler #define MotionHandlerParentPtr ActionHandler* class MotionHandler: public MotionHandlerParent { protected: // for rubber-banding IlvPoint _first; IlvPoint _current; virtual void initializeData(IlvEvent& event) { _first.move(event.x(), event.y()); } virtual void updateData(IlvEvent& event, IlvView*, IlvManager*) { _current.move(event.x(), event.y()); } virtual void startMotion(IlvEvent& event) { initializeData(event); drawGhost(); updateMotion(event); } virtual void updateMotion(IlvEvent& event) { drawGhost(); updateData(event, getView(), getManager()); ensureVisible(IlvPoint(event.x(), event.y())); drawGhost(); } virtual void endMotion(IlvEvent& event) { updateData(event, getView(), getManager()); drawGhost(); doIt(); returnControl(); } virtual void drawGhost() { } virtual void doIt() { } MotionHandler(GraphHandler* caller, GrapherPtr manager, IlvView* view) : MotionHandlerParent(caller, manager, view) { } public: virtual IlvBoolean isInitialEvent(IlvEvent&) { return IlvTrue; } virtual IlvBoolean isOkInitialTarget(IlvGraphic*) { return IlvTrue; } virtual IlvBoolean isOkFinalTarget(IlvGraphic*) { return IlvTrue; } virtual void handleEvent(IlvEvent& event); }; #define ArcHandlerParent MotionHandler #define ArcHandlerParentPtr MotionHandler* class ArcHandler: public ArcHandlerParent { protected: IlvCursor* originalCursor; IlvCursor* initialTargetCursor; IlvCursor* noTargetCursor; IlvCursor* finalTargetCursor; void indicateInitialTarget() { IlvDisplay* display = getView()->getDisplay(); originalCursor = display->defaultCursor(); display->setCursor(getView(), initialTargetCursor); // setCursor(originalCursor); } void indicateNoTarget() { getView()->getDisplay()->setCursor(getView(), noTargetCursor); // setCursor(originalCursor); } void indicateFinalTarget() { getView()->getDisplay()->setCursor(getView(), finalTargetCursor); // setCursor(originalCursor); } void indicatePreviousCursor() { getView()->getDisplay()->setCursor(getView(), originalCursor); } virtual void drawGhost() { if ((_current.x() != _first.x()) || (_current.y() != _first.y())) { IlvPoint tf = _first; IlvTransformer* t = getTransformer(); if (t) { t->apply(tf); } getManager()->getDisplay()->drawLine(getView(), getManager()->getPalette(), tf, _current); } } virtual IlvBoolean isInitialEvent(IlvEvent& event) { return (IlvBoolean) (event.modifiers() & IlvCtrlModifier); } virtual IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (t) ? IlvTrue : IlvFalse; } virtual IlvBoolean isOkFinalTarget(IlvGraphic* t) { return (t) ? IlvTrue : IlvFalse; } void initCursors(); void deleteCursors(); /* protected constructor... cannot instantiate one of these */ ArcHandler(GraphHandler* caller, GrapherPtr manager, IlvView* view) : ArcHandlerParent(caller, manager, view) { initCursors(); } ~ArcHandler() { deleteCursors(); } public: }; #define ArcMakerParent ArcHandler #define ArcMakerParentPtr ArcHandler* class ArcMaker: public ArcMakerParent { protected: IlvBoolean exitedTarget; IlvGraphic* finalTarget; virtual void initializeData(IlvEvent& event) { IlvRect bbox; target()->boundingBox(bbox); _first.move(bbox.centerx(), bbox.centery()); _current.move(event.x(), event.y()); exitedTarget = IlvFalse; finalTarget = nil; } virtual void startMotion(IlvEvent& event) { if (!targetted()) { returnControl(); } else { initializeData(event); drawGhost(); indicateInitialTarget(); updateMotion(event); } } virtual void updateMotion(IlvEvent& event) { drawGhost(); IlvPoint p(event.x(), event.y()); IlvManager* mgr = getManager(); IlvView* view = getView(); updateData(event, view, mgr); if (!exitedTarget) { if (mgr->lastContains(p, view) != target()) { exitedTarget = IlvTrue; } } if (exitedTarget) { IlvGraphic* newTarget = mgr->lastContains(p, view); if (finalTarget) { if (newTarget != finalTarget) { if (isOkFinalTarget(newTarget)) { finalTarget = newTarget; } else { finalTarget = nil; } } } else { // no previous final target if (isOkFinalTarget(newTarget)) { finalTarget = newTarget; } } } if (finalTarget) { indicateFinalTarget(); } else if (exitedTarget) { indicateNoTarget(); } // else leave as it was... ensureVisible(IlvPoint(event.x(), event.y())); drawGhost(); } virtual void endMotion(IlvEvent& event) { updateData(event, getView(), getManager()); indicatePreviousCursor(); drawGhost(); if (targetted() && exitedTarget && (finalTarget != nil)) { doIt(); } returnControl(); } virtual void doIt() { XeNodePtr tail = ((LabelledNodePtr) target())->xeNode(); XeNodePtr head = ((LabelledNodePtr) finalTarget)->xeNode(); XeGraphPtr graph = ((GrapherPtr)getManager())->xegraph(); // This will need to be replaced with a call to XeGraph::notify(ArcCreate ) XeArcPtr arc = new XeArc(head, tail, "New Arc", True); } virtual IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (t != nil) && ((GrapherPtr)getManager())->isNode(t); } virtual IlvBoolean isOkFinalTarget(IlvGraphic* t) { return isOkInitialTarget(t); } public: ArcMaker(GraphHandler* caller, GrapherPtr manager, IlvView* view) : ArcMakerParent(caller, manager, view) { } }; #define ArcChangerParent ArcHandler #define ArcChangerParentPtr ArcHandler* class ArcChanger: public ArcChangerParent { protected: IlvGraphic* finalTarget; virtual IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (t != nil) && ((GrapherPtr)getManager())->isLink(t); } virtual IlvBoolean isOkFinalTarget(IlvGraphic* t) { return (t != nil) && ((GrapherPtr)getManager())->isNode(t); } virtual void initializeData(IlvEvent& event) { // decide which end was the initial target. For now, // only allow change of head IlvLinkImage* arc = (IlvLinkImage*) target(); IlvGraphic* node = arc->getFrom(); target(node); IlvRect bbox; node->boundingBox(bbox); _first.move(bbox.centerx(), bbox.centery()); _current.move(event.x(), event.y()); finalTarget = nil; } virtual void startMotion(IlvEvent& event) { if (!targetted()) { returnControl(); } else { initializeData(event); drawGhost(); // this will change to indicate appropriate target. indicateNoTarget(); updateMotion(event); } } virtual void updateMotion(IlvEvent& event) { drawGhost(); IlvPoint p(event.x(), event.y()); IlvManager* mgr = getManager(); IlvView* view = getView(); updateData(event, view, mgr); IlvGraphic* newTarget = mgr->lastContains(p, view); if (finalTarget) { if (newTarget != finalTarget) { if (isOkFinalTarget(newTarget)) { finalTarget = newTarget; } else { finalTarget = nil; } } } else { // no previous final target if (isOkFinalTarget(newTarget)) { finalTarget = newTarget; } } if (finalTarget) { indicateFinalTarget(); } else { indicateNoTarget(); } ensureVisible(IlvPoint(event.x(), event.y())); drawGhost(); } virtual void endMotion(IlvEvent& event) { updateData(event, getView(), getManager()); indicatePreviousCursor(); drawGhost(); if (targetted() && (finalTarget != nil)) { doIt(); } returnControl(); } virtual void doIt(); public: ArcChanger(GraphHandler* caller, GrapherPtr manager, IlvView* view) : ArcChangerParent(caller, manager, view) { } }; #define NodeMakerParent MotionHandler #define NodeMakerParentPtr MotionHandler* class NodeMaker: public NodeMakerParent { protected: IlvRect _xor_rectangle; virtual void drawGhost() { if (_xor_rectangle.w()) { getManager()->getDisplay()->drawRectangle(getView(), getManager()->getPalette(), _xor_rectangle); } } virtual IlvBoolean isInitialEvent(IlvEvent& event) { return (IlvBoolean) (event.modifiers() & IlvCtrlModifier); } virtual IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (t) ? IlvFalse : IlvTrue; } virtual void initializeData(IlvEvent& event) { _xor_rectangle.move(event.x(), event.y()); _xor_rectangle.resize(100, 40); } virtual void updateData(IlvEvent& event, IlvView* view, IlvManager* mgr) { NodeMakerParent::updateData(event, view, mgr); _xor_rectangle.move(event.x(), event.y()); } virtual void doIt(); public: NodeMaker(GraphHandler* caller, GrapherPtr manager, IlvView* view) : NodeMakerParent(caller, manager, view) { } }; const int ObjectLayer = 0; const int HighlightLayer = 1; typedef enum { NewSelection, AddSelection, ToggleSelection } SelectionType; #define SelectorParent MotionHandler #define SelectorParentPtr MotionHandler* class Selector: public SelectorParent { protected: // used to determine actions in various modes SelectionType _type; IlvPoint _p; IlvPoint _tp; IlvRegion _region; // for manipulating an individual object IlvBoolean _wasSelected; // for outlining individual graphical objects Outliner* _outliner; void deselect() { getManager()->deSelectAll(); } virtual void updateData(IlvEvent& event, IlvView* view, IlvManager* mgr) { SelectorParent::updateData(event, view, mgr); _p.move(event.x(), event.y()); _tp = _p; IlvTransformer* xform = getTransformer(); if (xform) { xform->apply(_tp); } } virtual IlvBoolean isInitialEvent(IlvEvent& event) { return (IlvBoolean) ((!event.modifiers()) || (event.modifiers() & IlvCtrlModifier)); } virtual IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (IlvBoolean)(t != nil); // && ((GrapherPtr) getManager())->isNode(target())); } public: Selector(GraphHandler* caller, GrapherPtr manager, IlvView* view) : SelectorParent(caller, manager, view) , _type(NewSelection) , _wasSelected(IlvFalse) , _outliner(nil) { } virtual void init(); virtual void startMotion(IlvEvent& event); virtual void updateMotion(IlvEvent& event); virtual void endMotion(IlvEvent& event); }; #define SweepSelectorParent Selector #define SweepSelectorParentPtr Selector* class SweepSelector: public SweepSelectorParent { protected: // for sweeping out rectangles for selection IlvRect _xor_rectangle; IlvPos _firstx; IlvPos _firsty; void updateData(IlvEvent& event, IlvView* view, IlvManager* mgr) { SweepSelectorParent::updateData(event, view, mgr); _xor_rectangle.move(IlvMin(_firstx, event.x()), IlvMin(_firsty, event.y())); _xor_rectangle.resize((IlvDim)(IlvMax(_firstx, event.x()) - _xor_rectangle.x()), (IlvDim)(IlvMax(_firsty, event.y()) - _xor_rectangle.y())); } virtual void startMotion(IlvEvent& event) { if (targetted()) { returnControl(); } else { _firstx = event.x(); _firsty = event.y(); _xor_rectangle.w(0); #if 0 deselect(); #endif updateMotion(event); } } virtual void updateMotion(IlvEvent& event) { if (_xor_rectangle.w()) drawGhost(); updateData(event, getView(), getManager()); ensureVisible(IlvPoint(event.x(), event.y())); drawGhost(); } virtual void endMotion(IlvEvent& event) { deselect(); updateData(event, getView(), getManager()); if (_xor_rectangle.w()) { drawGhost(); doIt(); _xor_rectangle.w(0); } returnControl(); } virtual void doIt(); virtual void drawGhost() { if (_xor_rectangle.w()) { getManager()->getDisplay()->drawRectangle(getView(), getManager()->getPalette(), _xor_rectangle); } } IlvBoolean isInitialEvent(IlvEvent& event) { return (IlvBoolean) !event.modifiers(); } IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (IlvBoolean)(t == nil); } public: SweepSelector(GraphHandler* caller, GrapherPtr manager, IlvView* view) : SweepSelectorParent(caller, manager, view) { } }; #define SubgraphSelectorParent Selector #define SubgraphSelectorParentPtr Selector* class SubgraphSelector: public SubgraphSelectorParent { protected: // for selecting subgraph -- _target holds topmost node... IlvUInt _nSubgraphNodes; LabelledNodePtr* _subgraph; Outliner** _subgraphOutliners; virtual void startMotion(IlvEvent& event); virtual void updateMotion(IlvEvent& event); virtual void endMotion(IlvEvent& event); IlvBoolean isInitialEvent(IlvEvent& event) { return (IlvBoolean) (event.modifiers() & IlvShiftModifier); } IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (IlvBoolean)(t && ((GrapherPtr) getManager())->isNode(target())); } public: SubgraphSelector(GraphHandler* caller, GrapherPtr manager, IlvView* view) : SubgraphSelectorParent(caller, manager, view) { } }; #define ItemMoverParent ActionHandler #define ItemMoverParentPtr ActionHandler* class ItemMover: public ItemMoverParent { protected: virtual void startMove(IlvEvent&) { } virtual void updateMove(IlvEvent&) { } virtual void endMove(IlvEvent&) { } virtual IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (t != nil) && ((GrapherPtr) getManager())->isNode(t); } public: ItemMover(GraphHandler* caller, GrapherPtr manager, IlvView* view) : ItemMoverParent(caller, manager, view) { } void handleEvent(IlvEvent& event); }; #define NodeMoverParent ItemMover #define NodeMoverParentPtr ItemMover* class NodeMover: public NodeMoverParent { protected: IlvPos _deltax, _deltay; void startMove(IlvEvent& event) { IlvRect bbox; target()->boundingBox(bbox, getTransformer()); _deltax = event.x() - bbox.x(); _deltay = event.y() - bbox.y(); } virtual void updateMove(IlvEvent& event) { IlvRect bbox; target()->boundingBox(bbox, getTransformer()); IlvPoint newOrigin(event.x() - _deltax, event.y() - _deltay); if(getTransformer()) getTransformer()->inverse(newOrigin); target()->boundingBox(bbox); IlvDeltaPoint dp((IlvDeltaPos)(newOrigin.x()-bbox.x()), (IlvDeltaPos)(newOrigin.y()-bbox.y())); doIt(target(), dp); } virtual void endMove(IlvEvent&) { target(nil); } virtual void doIt(IlvGraphic* graphic,const IlvDeltaPoint& p); public: NodeMover(GraphHandler* caller, GrapherPtr manager, IlvView* view) : NodeMoverParent(caller, manager, view) { } }; #define SelectionMoverParent NodeMover #define SelectionMoverParentPtr NodeMover* class SelectionMover: public SelectionMoverParent { protected: virtual IlvBoolean isOkInitialTarget(IlvGraphic* t) { return (IlvBoolean) (t && getManager()->isSelected(t) && ((GrapherPtr)getManager())->isNode(t)); } virtual void doIt(IlvGraphic* graphic, const IlvDeltaPoint& p); public: SelectionMover(GraphHandler* caller, GrapherPtr manager, IlvView* view) : SelectionMoverParent(caller, manager, view) { } }; #define MenuHandlerParent ActionHandler #define MenuHandlerParentPtr ActionHandler* class MenuHandler : public MenuHandlerParent { public: MenuHandler(GraphHandler* caller, GrapherPtr manager, IlvView* view) : MenuHandlerParent(caller, manager, view) { } void handleEvent(IlvEvent& event); }; extern void PopupMenu(XegPopupMenuPtr menu, Widget w, IlvEvent* event); pmccabe-v2.8/tests/test006/Handler.H.ref000066400000000000000000000246031400136053700177570ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test006/Handler.H Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 2 2 3 68 8 test006/Handler.H(68): ActionHandler::returnControl 1 1 3 77 4 test006/Handler.H(77): ActionHandler::ActionHandler 1 1 1 83 1 test006/Handler.H(83): ActionHandler::target 1 1 1 84 1 test006/Handler.H(84): ActionHandler::target 2 2 2 85 1 test006/Handler.H(85): ActionHandler::targetted 1 1 2 89 4 test006/Handler.H(89): ActionHandler::init 1 1 3 94 6 test006/Handler.H(94): ActionHandler::takeCharge 1 1 2 101 4 test006/Handler.H(101): ActionHandler::abort 1 1 1 117 4 test006/Handler.H(117): MotionHandler::initializeData 1 1 1 122 4 test006/Handler.H(122): MotionHandler::updateData 1 1 3 127 5 test006/Handler.H(127): MotionHandler::startMotion 1 1 4 132 6 test006/Handler.H(132): MotionHandler::updateMotion 1 1 4 138 6 test006/Handler.H(138): MotionHandler::endMotion 1 1 0 145 1 test006/Handler.H(145): MotionHandler::drawGhost 1 1 0 146 1 test006/Handler.H(146): MotionHandler::doIt 1 1 1 148 4 test006/Handler.H(148): MotionHandler::MotionHandler 1 1 1 155 1 test006/Handler.H(155): MotionHandler::isInitialEvent 1 1 1 156 1 test006/Handler.H(156): MotionHandler::isOkInitialTarget 1 1 1 157 1 test006/Handler.H(157): MotionHandler::isOkFinalTarget 1 1 3 174 6 test006/Handler.H(174): ArcHandler::indicateInitialTarget 1 1 1 180 4 test006/Handler.H(180): ArcHandler::indicateNoTarget 1 1 1 184 4 test006/Handler.H(184): ArcHandler::indicateFinalTarget 1 1 1 188 3 test006/Handler.H(188): ArcHandler::indicatePreviousCursor 4 4 6 192 15 test006/Handler.H(192): ArcHandler::drawGhost 1 1 1 208 4 test006/Handler.H(208): ArcHandler::isInitialEvent 2 2 2 213 4 test006/Handler.H(213): ArcHandler::isOkInitialTarget 2 2 2 217 4 test006/Handler.H(217): ArcHandler::isOkFinalTarget 1 1 2 227 5 test006/Handler.H(227): ArcHandler::ArcHandler 1 1 1 232 4 test006/Handler.H(232): ArcHandler::~ArcHandler 1 1 6 250 10 test006/Handler.H(250): ArcMaker::initializeData 2 2 6 260 10 test006/Handler.H(260): ArcMaker::startMotion 10 10 23 271 37 test006/Handler.H(271): ArcMaker::updateMotion 4 4 6 309 11 test006/Handler.H(309): ArcMaker::endMotion 1 1 4 321 10 test006/Handler.H(321): ArcMaker::doIt 2 2 1 332 4 test006/Handler.H(332): ArcMaker::isOkInitialTarget 1 1 1 336 4 test006/Handler.H(336): ArcMaker::isOkFinalTarget 1 1 1 342 4 test006/Handler.H(342): ArcMaker::ArcMaker 2 2 1 356 4 test006/Handler.H(356): ArcChanger::isOkInitialTarget 2 2 1 360 4 test006/Handler.H(360): ArcChanger::isOkFinalTarget 1 1 8 365 12 test006/Handler.H(365): ArcChanger::initializeData 2 2 6 378 12 test006/Handler.H(378): ArcChanger::startMotion 6 6 18 391 30 test006/Handler.H(391): ArcChanger::updateMotion 3 3 6 422 11 test006/Handler.H(422): ArcChanger::endMotion 1 1 1 436 4 test006/Handler.H(436): ArcChanger::ArcChanger 2 2 2 451 8 test006/Handler.H(451): NodeMaker::drawGhost 1 1 1 459 4 test006/Handler.H(459): NodeMaker::isInitialEvent 2 2 2 464 4 test006/Handler.H(464): NodeMaker::isOkInitialTarget 1 1 2 469 5 test006/Handler.H(469): NodeMaker::initializeData 1 1 2 474 5 test006/Handler.H(474): NodeMaker::updateData 1 1 1 482 4 test006/Handler.H(482): NodeMaker::NodeMaker 1 1 1 515 3 test006/Handler.H(515): Selector::deselect 2 2 6 519 10 test006/Handler.H(519): Selector::updateData 2 2 1 530 5 test006/Handler.H(530): Selector::isInitialEvent 1 1 1 536 5 test006/Handler.H(536): Selector::isOkInitialTarget 1 1 4 543 7 test006/Handler.H(543): Selector::Selector 1 1 3 570 10 test006/Handler.H(570): SweepSelector::updateData 2 2 6 581 13 test006/Handler.H(581): SweepSelector::startMotion 2 2 5 595 7 test006/Handler.H(595): SweepSelector::updateMotion 2 2 7 603 10 test006/Handler.H(603): SweepSelector::endMotion 2 2 2 616 8 test006/Handler.H(616): SweepSelector::drawGhost 1 1 1 625 4 test006/Handler.H(625): SweepSelector::isInitialEvent 1 1 1 630 4 test006/Handler.H(630): SweepSelector::isOkInitialTarget 1 1 1 636 4 test006/Handler.H(636): SweepSelector::SweepSelector 1 1 1 658 4 test006/Handler.H(658): SubgraphSelector::isInitialEvent 2 2 1 663 4 test006/Handler.H(663): SubgraphSelector::isOkInitialTarget 1 1 1 669 4 test006/Handler.H(669): SubgraphSelector::SubgraphSelector 1 1 0 681 1 test006/Handler.H(681): ItemMover::startMove 1 1 0 682 1 test006/Handler.H(682): ItemMover::updateMove 1 1 0 683 1 test006/Handler.H(683): ItemMover::endMove 2 2 1 685 3 test006/Handler.H(685): ItemMover::isOkInitialTarget 1 1 1 689 4 test006/Handler.H(689): ItemMover::ItemMover 1 1 4 706 6 test006/Handler.H(706): NodeMover::startMove 2 2 8 712 11 test006/Handler.H(712): NodeMover::updateMove 1 1 1 723 3 test006/Handler.H(723): NodeMover::endMove 1 1 1 728 4 test006/Handler.H(728): NodeMover::NodeMover 3 3 1 740 4 test006/Handler.H(740): SelectionMover::isOkInitialTarget 1 1 1 746 4 test006/Handler.H(746): SelectionMover::SelectionMover 1 1 1 758 4 test006/Handler.H(758): MenuHandler::MenuHandler 122 122 245 n/a 770 Total RUN: ../pmccabe -X -vnt test006/Handler.H CSL PCT NCSL PCT TOTAL FILENAME 152 20 618 80 770 test006/Handler.H 152 20 618 80 770 (total files: 1) RUN: ../pmccabe -x -vt test006/Handler.H Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 2 2 3 68 8 test006/Handler.H(68): ActionHandler::returnControl 1 1 3 77 4 test006/Handler.H(77): ActionHandler::ActionHandler 1 1 1 83 1 test006/Handler.H(83): ActionHandler::target 1 1 1 84 1 test006/Handler.H(84): ActionHandler::target 2 2 2 85 1 test006/Handler.H(85): ActionHandler::targetted 1 1 2 89 4 test006/Handler.H(89): ActionHandler::init 1 1 3 94 6 test006/Handler.H(94): ActionHandler::takeCharge 1 1 2 101 4 test006/Handler.H(101): ActionHandler::abort 1 1 1 117 4 test006/Handler.H(117): MotionHandler::initializeData 1 1 1 122 4 test006/Handler.H(122): MotionHandler::updateData 1 1 3 127 5 test006/Handler.H(127): MotionHandler::startMotion 1 1 4 132 6 test006/Handler.H(132): MotionHandler::updateMotion 1 1 4 138 6 test006/Handler.H(138): MotionHandler::endMotion 1 1 0 145 1 test006/Handler.H(145): MotionHandler::drawGhost 1 1 0 146 1 test006/Handler.H(146): MotionHandler::doIt 1 1 1 148 4 test006/Handler.H(148): MotionHandler::MotionHandler 1 1 1 155 1 test006/Handler.H(155): MotionHandler::isInitialEvent 1 1 1 156 1 test006/Handler.H(156): MotionHandler::isOkInitialTarget 1 1 1 157 1 test006/Handler.H(157): MotionHandler::isOkFinalTarget 1 1 3 174 6 test006/Handler.H(174): ArcHandler::indicateInitialTarget 1 1 1 180 4 test006/Handler.H(180): ArcHandler::indicateNoTarget 1 1 1 184 4 test006/Handler.H(184): ArcHandler::indicateFinalTarget 1 1 1 188 3 test006/Handler.H(188): ArcHandler::indicatePreviousCursor 4 4 6 192 15 test006/Handler.H(192): ArcHandler::drawGhost 1 1 1 208 4 test006/Handler.H(208): ArcHandler::isInitialEvent 2 2 2 213 4 test006/Handler.H(213): ArcHandler::isOkInitialTarget 2 2 2 217 4 test006/Handler.H(217): ArcHandler::isOkFinalTarget 1 1 2 227 5 test006/Handler.H(227): ArcHandler::ArcHandler 1 1 1 232 4 test006/Handler.H(232): ArcHandler::~ArcHandler 1 1 6 250 10 test006/Handler.H(250): ArcMaker::initializeData 2 2 6 260 10 test006/Handler.H(260): ArcMaker::startMotion 10 10 23 271 37 test006/Handler.H(271): ArcMaker::updateMotion 4 4 6 309 11 test006/Handler.H(309): ArcMaker::endMotion 1 1 4 321 10 test006/Handler.H(321): ArcMaker::doIt 2 2 1 332 4 test006/Handler.H(332): ArcMaker::isOkInitialTarget 1 1 1 336 4 test006/Handler.H(336): ArcMaker::isOkFinalTarget 1 1 1 342 4 test006/Handler.H(342): ArcMaker::ArcMaker 2 2 1 356 4 test006/Handler.H(356): ArcChanger::isOkInitialTarget 2 2 1 360 4 test006/Handler.H(360): ArcChanger::isOkFinalTarget 1 1 8 365 12 test006/Handler.H(365): ArcChanger::initializeData 2 2 6 378 12 test006/Handler.H(378): ArcChanger::startMotion 6 6 18 391 30 test006/Handler.H(391): ArcChanger::updateMotion 3 3 6 422 11 test006/Handler.H(422): ArcChanger::endMotion 1 1 1 436 4 test006/Handler.H(436): ArcChanger::ArcChanger 2 2 2 451 8 test006/Handler.H(451): NodeMaker::drawGhost 1 1 1 459 4 test006/Handler.H(459): NodeMaker::isInitialEvent 2 2 2 464 4 test006/Handler.H(464): NodeMaker::isOkInitialTarget 1 1 2 469 5 test006/Handler.H(469): NodeMaker::initializeData 1 1 2 474 5 test006/Handler.H(474): NodeMaker::updateData 1 1 1 482 4 test006/Handler.H(482): NodeMaker::NodeMaker 1 1 1 515 3 test006/Handler.H(515): Selector::deselect 2 2 6 519 10 test006/Handler.H(519): Selector::updateData 2 2 1 530 5 test006/Handler.H(530): Selector::isInitialEvent 1 1 1 536 5 test006/Handler.H(536): Selector::isOkInitialTarget 1 1 4 543 7 test006/Handler.H(543): Selector::Selector 1 1 3 570 10 test006/Handler.H(570): SweepSelector::updateData 2 2 7 581 13 test006/Handler.H(581): SweepSelector::startMotion 2 2 5 595 7 test006/Handler.H(595): SweepSelector::updateMotion 2 2 7 603 10 test006/Handler.H(603): SweepSelector::endMotion 2 2 2 616 8 test006/Handler.H(616): SweepSelector::drawGhost 1 1 1 625 4 test006/Handler.H(625): SweepSelector::isInitialEvent 1 1 1 630 4 test006/Handler.H(630): SweepSelector::isOkInitialTarget 1 1 1 636 4 test006/Handler.H(636): SweepSelector::SweepSelector 1 1 1 658 4 test006/Handler.H(658): SubgraphSelector::isInitialEvent 2 2 1 663 4 test006/Handler.H(663): SubgraphSelector::isOkInitialTarget 1 1 1 669 4 test006/Handler.H(669): SubgraphSelector::SubgraphSelector 1 1 0 681 1 test006/Handler.H(681): ItemMover::startMove 1 1 0 682 1 test006/Handler.H(682): ItemMover::updateMove 1 1 0 683 1 test006/Handler.H(683): ItemMover::endMove 2 2 1 685 3 test006/Handler.H(685): ItemMover::isOkInitialTarget 1 1 1 689 4 test006/Handler.H(689): ItemMover::ItemMover 1 1 4 706 6 test006/Handler.H(706): NodeMover::startMove 2 2 8 712 11 test006/Handler.H(712): NodeMover::updateMove 1 1 1 723 3 test006/Handler.H(723): NodeMover::endMove 1 1 1 728 4 test006/Handler.H(728): NodeMover::NodeMover 3 3 1 740 4 test006/Handler.H(740): SelectionMover::isOkInitialTarget 1 1 1 746 4 test006/Handler.H(746): SelectionMover::SelectionMover 1 1 1 758 4 test006/Handler.H(758): MenuHandler::MenuHandler 122 122 246 n/a 770 Total pmccabe-v2.8/tests/test006/NodeArc.H000066400000000000000000000334771400136053700171530ustar00rootroot00000000000000 /************************************************************************\ LabelledNode declaration \************************************************************************/ class Shaper; #define LabelledNodeParent IlvListLabel #define LabelledNodeParentPtr IlvListLabel* class LabelledNode: public LabelledNodeParent { private: protected: char* label_; IlvColor* border_; IlvShort bwidth_; XeNodePtr xeNode_; ShapeType shapeType_; Shaper* shaper_; virtual void drawShape(IlvDisplay* dpy, IlvPort* dst, IlvPalette* palette, IlvTransformer* t, IlvRect& r) ; virtual void baseBoundingBox(IlvRect& r, IlvTransformer* t=0); public: LabelledNode(XeNodePtr xenode, IlvDisplay* dpy, const IlvPoint& p, char* lbl , IlvShort bwidth, IlvPalette* palette = nil); ~LabelledNode() { ; } void label(char*); char* label() { return (label_); } void borderColor(char*); void shape(ShapeType type); ShapeType shapeType() { return shapeType_; } IlvShort borderWidth() { return bwidth_; } void borderWidth(IlvShort w) { bwidth_ = w; } XeNodePtr xeNode() { return xeNode_; } void xeNode(XeNodePtr n) { xeNode_ = n; } virtual void draw(IlvPort* dst, IlvTransformer* t, IlvRegion* rect=0); virtual void boundingBox(IlvRect& r, IlvTransformer* t=0); virtual IlvBoolean contains(const IlvPoint& p, const IlvPoint& tp, IlvTransformer* t); virtual void computeRegion(IlvRegion& r, IlvTransformer* t=0); static LabelledNode* makeShapedNode(XeNodePtr node, IlvDisplay* dpy, const ShapeType type, const IlvPoint& p, char* label, IlvShort bwidth); DeclareTypeInfo(); }; typedef enum { FixedPosition = 0x0, RelativePosition = 0x1 } ArcEndType; /************************************************************************\ LabelledArc declaration and implementation \************************************************************************/ typedef IlvLinkImage ArcRootClass; class TextList; #define RECURSIVE_BEZIER_ARCS 1 // IlvDisplay::drawArrow(dst, transform, start, end, atPos) requires // atPos in the range [0.0,1.0]. 0.0 means draw the arrow at the // beginning of line, 1.0 means draw at end... const float ArrowAtStart = 0.0; const float ArrowAtEnd = 1.0; const int NodeBorderAllowance = 4; #define LabelledArcParent IlvLinkImage #define LabelledArcParentPtr IlvLinkImage* class LabelledArc: public LabelledArcParent { protected: XeArcPtr arc; char* label; Boolean labelVisible; char* labelColorString; IlvColor* labelColor; TextList* tlist; #if RECURSIVE_BEZIER_ARCS IlvPoint _points[7]; IlvShort _nPoints; IlvPoint _labelOrigin; #else IlvPoint _points[4]; IlvInt _nPoints; IlvPoint _labelOrigin; #endif IlvBoolean arrowContains(const IlvPoint& p, const IlvPoint& tp, IlvTransformer*t=0); virtual IlvBoolean arcContains(const IlvPoint& p, const IlvPoint& tp, IlvTransformer*t=0) { IlvBoolean isIn; isIn = IlvPointInLine(p, _points[0], _points[1]); if (!isIn) { isIn = arrowContains(p, tp, t); } return isIn; } virtual IlvBoolean labelContains(const IlvPoint& p, const IlvPoint& tp, IlvTransformer*t=0) { IlvRect r; labelBoundingBox(r, t); IlvBoolean isIn; if (t) { isIn = r.contains(tp); } else { isIn = r.contains(p); } return isIn; } // calculate the origination point for the label, using the // indicated transformation virtual void getLabelOrigin(IlvPoint& origin, IlvTransformer* t=0) { IlvRect r; arcBoundingBox(r, t); origin.move(r.centerx(), r.centery()); } virtual void arrowPoints(IlvPoint* points, IlvTransformer* t=0) { // This should really calculate the points then apply the transformer... IlvPoint from = _points[0], to = _points[1]; if (t) { t->apply(from); t->apply(to); } IlvComputeArrow(from, to, ArrowAtEnd, points); } virtual void arrowBoundingBox(IlvRect& r, IlvTransformer* t=0) { IlvPoint pts[3]; arrowPoints(pts, t); r.resize(0,0); r.move(pts[0]); r.add(pts[1]); r.add(pts[2]); } virtual void arcBoundingBox(IlvRect& r, IlvTransformer* t=0) { r.move(_points[0]); r.resize(0,0); r.add(_points[1]); if (t) t->apply(r); IlvRect arrowBox; arrowBoundingBox(arrowBox, t); if (arrowBox.w() != 0 && arrowBox.h() != 0) { r.add(arrowBox); } } // find the label's origin relative to the non-transformed bounding // box, then calculate the label's bounding box using the // indicated transformation... virtual void labelBoundingBox(IlvRect& r, IlvTransformer* t=0); virtual void drawArrow(IlvPort* dst, IlvTransformer* t=0, IlvRegion* = 0) { IlvPoint start = _points[0], end = _points[1]; if (t) { t->apply(start); t->apply(end); } getDisplay()->drawArrow(dst, getPalette(), start, end, ArrowAtEnd); } virtual void drawArc(IlvPort* dst, IlvTransformer* t=0, IlvRegion* rect=0); virtual void drawLabel(IlvPort* dst, IlvTransformer* t, IlvRegion* clip=0); virtual void computePoints(IlvGraphic* f, IlvGraphic* t); public: LabelledArc(XeArcPtr owner, IlvDisplay* dpy, char* lbl, UIPtr tail, UIPtr head, Boolean showLabel = True); ~LabelledArc(); XeArcPtr owner() { return arc; } char* getLabel() { return label; } void setLabel(char* s); char* getLabelColor() { return labelColorString; } void setLabelColor(char* c); Boolean getLabelVisible() { return labelVisible; } void setLabelVisible(Boolean v); virtual IlvBoolean contains(const IlvPoint& p, const IlvPoint& tp, IlvTransformer*t =0); virtual void draw(IlvPort* dst, IlvTransformer* t=0, IlvRegion* rect=0); virtual void boundingBox(IlvRect&, IlvTransformer*t =0); virtual void computeRegion(IlvRegion& r, IlvTransformer* t); DeclareTypeInfo(); }; /************************************************************************\ sibling computation code -- perhaps this should be a nested class of arcs \************************************************************************/ class SiblingList { protected: XeArcPtr* arcs; int nSlots; int nArcs; void listAppend(XeArcPtr sib); void listRemove(XeArcPtr sib); public: SiblingList() { nSlots = 0; nArcs = 0; arcs = nil; } ~SiblingList() { delete arcs; } int count() { return nArcs; } int max() { return nSlots; } void insert(XeArcPtr sib); void remove(XeArcPtr sib); int rank(XeArcPtr); IlvBoolean isSibling(XeArcPtr sib) { IlvBoolean isSib = IlvFalse; for(int i = 0; i < nArcs; i++) { if (arcs[i] == sib) { isSib = IlvTrue; break; } } return isSib; } }; #if RECURSIVE_BEZIER_ARCS const IlvFloat RankedArcArrowPosition = ArrowAtEnd; #else const IlvFloat RankedArcArrowPosition = 0.6; #endif #define RankedArcParent LabelledArc #define RankedArcParentPtr LabelledArc* class RankedArc: public RankedArcParent { protected: IlvGraphic* _selfNode; #if !RECURSIVE_BEZIER_ARCS EllipseInfo* _eInfo; #endif int currentRank; // Compute the control points for our curve based on rank and // current position of head and tail of arc virtual void computePoints(IlvGraphic* f, IlvGraphic* t); virtual void arrowPoints(IlvPoint* points, IlvTransformer* t=0) { // This should really calculate the points then apply the transformer... IlvPoint from, to; IlvFloat arrowPos = ArrowAtEnd; if (currentRank == 0 && !selfish()) { RankedArcParent::arrowPoints(points, t); return; } if (selfish()) { #if RECURSIVE_BEZIER_ARCS arrowPos = RankedArcArrowPosition; from = _points[5]; to = _points[6]; #else arrowPos = RankedArcArrowPosition; from = _eInfo->startArrow(); to = _eInfo->endArrow(); #endif } else { from = _points[2]; to = _points[3]; } if (t) { t->apply(from); t->apply(to); } IlvComputeArrow(from, to, arrowPos, points); } int computeRank() { return owner()->siblings() ? owner()->siblings()->rank(owner()): 0; } IlvBoolean selfish() { return _selfNode ? IlvTrue : IlvFalse; } virtual IlvBoolean arcContains(const IlvPoint& p, const IlvPoint& tp, IlvTransformer*t=0) { IlvBoolean isIn = IlvFalse; currentRank = computeRank(); IlvGraphic* tail = getFrom(); IlvGraphic* head = getTo(); computePoints(tail, head); if (currentRank == 0 && !selfish()) { isIn = RankedArcParent::arcContains(p, tp, t); } else { if (t) { #if RECURSIVE_BEZIER_ARCS IlvPoint points[8]; #else IlvPoint points[4]; #endif for (int i = 0; i < _nPoints; i++) { points[i] = _points[i]; t->apply(points[i]); } // check the "transformed point" supplied by Views manager... #if RECURSIVE_BEZIER_ARCS isIn = IlvPointInSpline(tp, _nPoints, points); #else if (selfish()) { IlvRect r = _eInfo->rect(); t->apply(r); isIn = PointOnArc(tp, r, _eInfo->startAngle(), _eInfo->deltaAngle(), /* tolerance */ 2); } else { isIn = IlvPointInSpline(tp, _nPoints, points); } #endif } else { #if RECURSIVE_BEZIER_ARCS isIn = IlvPointInSpline(p, _nPoints, _points); #else if (selfish()) { isIn = PointOnArc(p, _eInfo->rect(), _eInfo->startAngle(), _eInfo->deltaAngle(), /* tolerance */ 2); } else { isIn = IlvPointInSpline(p, _nPoints, _points); } #endif } if (!isIn) { isIn = arrowContains(p, tp, t); } } return isIn; } // calculate the origination point for the label, using the // indicated transformation virtual void getLabelOrigin(IlvPoint& origin, IlvTransformer* t=0) { currentRank = computeRank(); IlvGraphic* tail = getFrom(); IlvGraphic* head = getTo(); computePoints(tail, head); if (currentRank == 0 && !selfish()) { RankedArcParent::getLabelOrigin(origin, t); } else { origin = _labelOrigin; if (t) { t->apply(origin); } } } virtual void arcBoundingBox(IlvRect& r, IlvTransformer* t=0) { currentRank = computeRank(); IlvGraphic* tail = getFrom(); IlvGraphic* head = getTo(); computePoints(tail, head); if (currentRank == 0 && !selfish()) { RankedArcParent::arcBoundingBox(r, t); } else { #if RECURSIVE_BEZIER_ARCS r.move(_points[0]); r.resize(0,0); r.add(_points[1]); r.add(_points[2]); r.add(_points[3]); if (selfish()) { // only valid for self arcs... r.add(_points[4]); r.add(_points[5]); r.add(_points[6]); } #else if (selfish()) { IlvComputeArcBBox(_eInfo->rect(), _eInfo->startAngle(), _eInfo->deltaAngle(), r); } else { r.move(_points[0]); r.resize(0,0); r.add(_points[1]); r.add(_points[2]); r.add(_points[3]); } #endif IlvRect arrowBox; arrowBoundingBox(arrowBox, 0); r.add(arrowBox); if (t) t->apply(r); } } virtual void drawArc(IlvPort* dst, IlvTransformer* t=0, IlvRegion* rect=0) { currentRank = computeRank(); IlvGraphic* tail = getFrom(); IlvGraphic* head = getTo(); computePoints(tail, head); if (currentRank == 0 && !selfish()) { RankedArcParent::drawArc(dst, t, rect); } else { // how do we draw the arrow??? drawArrow(dst, t, rect); drawRankedArc(currentRank, dst, t, rect); } } virtual void drawRankedArc(int rank, IlvPort* dst, IlvTransformer* t=0, IlvR egion* rect=0) { #if RECURSIVE_BEZIER_ARCS if (selfish() || rank > 0) { if (!t) { getDisplay()->drawBezier(dst, getPalette(), _nPoints, _points); } else { IlvPoint points[8]; for (int i = 0; i < _nPoints; i++) { points[i] = _points[i]; t->apply(points[i]); } getDisplay()->drawBezier(dst, getPalette(), _nPoints, points); } } else { // shouldn't reach this point... RankedArcParent::drawArc(dst, t, rect); } #else if (selfish()) { IlvRect r = _eInfo->rect(); if (t) t->apply(r); getDisplay()->drawArc(dst, getPalette(), r, (IlvFloat) _eInfo->startAngle(), (IlvFloat) _eInfo->deltaAngle()); } else if (rank > 0) { if (t) { IlvPoint points[4]; for (int i = 0; i < _nPoints; i++) { points[i] = _points[i]; t->apply(points[i]); } getDisplay()->drawBezier(dst, getPalette(), _nPoints, points); } else { getDisplay()->drawBezier(dst, getPalette(), _nPoints, _points); } } else { // shouldn't reach this point... RankedArcParent::drawArc(dst, t, rect); } #endif } virtual void drawArrow(IlvPort* dst, IlvTransformer* t=0, IlvRegion* r=0) { IlvBoolean selfArc = selfish(); if (!selfArc && currentRank == 0) { RankedArcParent::drawArrow(dst, t, r); } else { IlvPoint start, end; IlvFloat arrowPos = ArrowAtEnd; #if RECURSIVE_BEZIER_ARCS if (selfArc) { start = _points[5]; end = _points[6]; arrowPos = RankedArcArrowPosition; } else { start = _points[2]; end = _points[3]; } #else if (selfArc) { start = _eInfo->startArrow(); end = _eInfo->endArrow(); arrowPos = RankedArcArrowPosition; } else { // we use the control points of our spline to determine direction // and "slope" of arrow's center... start = _points[2]; end = _points[3]; } #endif if (t) { t->apply(start); t->apply(end); } getDisplay()->drawArrow(dst, getPalette(), start, end, arrowPos); } } public: RankedArc(XeArcPtr owner, IlvDisplay* dpy, char* lbl, UIPtr tail, UIPtr head, Boolean showLabel = True); ~RankedArc() { _nPoints = 0; #if !RECURSIVE_BEZIER_ARCS if (_selfNode) delete _eInfo; #endif } DeclareTypeInfo(); }; pmccabe-v2.8/tests/test006/NodeArc.H.ref000066400000000000000000000115111400136053700177070ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test006/NodeArc.H Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 31 1 test006/NodeArc.H(31): LabelledNode::~LabelledNode 1 1 1 33 1 test006/NodeArc.H(33): LabelledNode::label 1 1 1 37 1 test006/NodeArc.H(37): LabelledNode::shapeType 1 1 1 39 1 test006/NodeArc.H(39): LabelledNode::borderWidth 1 1 1 40 1 test006/NodeArc.H(40): LabelledNode::borderWidth 1 1 1 42 1 test006/NodeArc.H(42): LabelledNode::xeNode 1 1 1 43 1 test006/NodeArc.H(43): LabelledNode::xeNode 2 2 5 107 10 test006/NodeArc.H(107): LabelledArc::arcContains 2 2 7 118 13 test006/NodeArc.H(118): LabelledArc::labelContains 1 1 3 134 6 test006/NodeArc.H(134): LabelledArc::getLabelOrigin 2 2 5 141 10 test006/NodeArc.H(141): LabelledArc::arrowPoints 1 1 6 152 9 test006/NodeArc.H(152): LabelledArc::arrowBoundingBox 4 4 9 162 12 test006/NodeArc.H(162): LabelledArc::arcBoundingBox 2 2 5 179 9 test006/NodeArc.H(179): LabelledArc::drawArrow 1 1 1 200 1 test006/NodeArc.H(200): LabelledArc::owner 1 1 1 202 1 test006/NodeArc.H(202): LabelledArc::getLabel 1 1 1 205 1 test006/NodeArc.H(205): LabelledArc::getLabelColor 1 1 1 208 1 test006/NodeArc.H(208): LabelledArc::getLabelVisible 1 1 3 234 1 test006/NodeArc.H(234): SiblingList::SiblingList 1 1 1 235 1 test006/NodeArc.H(235): SiblingList::~SiblingList 1 1 1 237 1 test006/NodeArc.H(237): SiblingList::count 1 1 1 238 1 test006/NodeArc.H(238): SiblingList::max 3 3 8 244 11 test006/NodeArc.H(244): SiblingList::isSibling 5 5 15 279 28 test006/NodeArc.H(279): RankedArc::arrowPoints 2 2 2 308 3 test006/NodeArc.H(308): RankedArc::computeRank 2 2 2 312 1 test006/NodeArc.H(312): RankedArc::selfish 6 6 19 314 52 test006/NodeArc.H(314): RankedArc::arcContains 4 4 9 369 15 test006/NodeArc.H(369): RankedArc::getLabelOrigin 5 5 20 385 40 test006/NodeArc.H(385): RankedArc::arcBoundingBox 3 3 8 426 14 test006/NodeArc.H(426): RankedArc::drawArc 5 5 11 441 43 test006/NodeArc.H(441): RankedArc::drawRankedArc 5 5 15 485 36 test006/NodeArc.H(485): RankedArc::drawArrow 2 2 3 526 7 test006/NodeArc.H(526): RankedArc::~RankedArc 71 71 181 n/a 539 Total RUN: ../pmccabe -X -vnt test006/NodeArc.H CSL PCT NCSL PCT TOTAL FILENAME 161 30 378 70 539 test006/NodeArc.H 161 30 378 70 539 (total files: 1) RUN: ../pmccabe -x -vt test006/NodeArc.H Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 31 1 test006/NodeArc.H(31): LabelledNode::~LabelledNode 1 1 1 33 1 test006/NodeArc.H(33): LabelledNode::label 1 1 1 37 1 test006/NodeArc.H(37): LabelledNode::shapeType 1 1 1 39 1 test006/NodeArc.H(39): LabelledNode::borderWidth 1 1 1 40 1 test006/NodeArc.H(40): LabelledNode::borderWidth 1 1 1 42 1 test006/NodeArc.H(42): LabelledNode::xeNode 1 1 1 43 1 test006/NodeArc.H(43): LabelledNode::xeNode 2 2 5 107 10 test006/NodeArc.H(107): LabelledArc::arcContains 2 2 7 118 13 test006/NodeArc.H(118): LabelledArc::labelContains 1 1 3 134 6 test006/NodeArc.H(134): LabelledArc::getLabelOrigin 2 2 5 141 10 test006/NodeArc.H(141): LabelledArc::arrowPoints 1 1 6 152 9 test006/NodeArc.H(152): LabelledArc::arrowBoundingBox 4 4 9 162 12 test006/NodeArc.H(162): LabelledArc::arcBoundingBox 2 2 5 179 9 test006/NodeArc.H(179): LabelledArc::drawArrow 1 1 1 200 1 test006/NodeArc.H(200): LabelledArc::owner 1 1 1 202 1 test006/NodeArc.H(202): LabelledArc::getLabel 1 1 1 205 1 test006/NodeArc.H(205): LabelledArc::getLabelColor 1 1 1 208 1 test006/NodeArc.H(208): LabelledArc::getLabelVisible 1 1 3 234 1 test006/NodeArc.H(234): SiblingList::SiblingList 1 1 1 235 1 test006/NodeArc.H(235): SiblingList::~SiblingList 1 1 1 237 1 test006/NodeArc.H(237): SiblingList::count 1 1 1 238 1 test006/NodeArc.H(238): SiblingList::max 3 3 8 244 11 test006/NodeArc.H(244): SiblingList::isSibling 5 5 18 279 28 test006/NodeArc.H(279): RankedArc::arrowPoints 2 2 2 308 3 test006/NodeArc.H(308): RankedArc::computeRank 2 2 2 312 1 test006/NodeArc.H(312): RankedArc::selfish 8 8 28 314 52 test006/NodeArc.H(314): RankedArc::arcContains 4 4 9 369 15 test006/NodeArc.H(369): RankedArc::getLabelOrigin 6 6 27 385 40 test006/NodeArc.H(385): RankedArc::arcBoundingBox 3 3 8 426 14 test006/NodeArc.H(426): RankedArc::drawArc 10 10 27 441 43 test006/NodeArc.H(441): RankedArc::drawRankedArc 6 6 21 485 36 test006/NodeArc.H(485): RankedArc::drawArrow 2 2 3 526 7 test006/NodeArc.H(526): RankedArc::~RankedArc 80 80 223 n/a 539 Total pmccabe-v2.8/tests/test007000066400000000000000000000007501400136053700154370ustar00rootroot00000000000000int a() { if (a == 1) a = 1; if (a == 1) a = 1; if (a == 1) a = 1; if (a == 1) a = 1; a = 1; a = 1; } int a() { if (a == 1) a = 1; if (a == 1) a = 1; if (a == 1) a = 1; if (a == 1) a = 1; a = 1; a = 1; } int a() { if (a == 1) a = 1; if (a == 1) a = 1; if (a == 1) a = 1; if (a == 1) a = 1; a = 1; a = 1; } int a() { if (a == 1) a = 1; if (a == 1) a = 1; if (a == 1) a = 1; if (a == 1) a = 1; a = 1; a = 1; } pmccabe-v2.8/tests/test007.ref000066400000000000000000000021711400136053700162110ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test007 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 5 5 10 1 8 test007(1): a 5 5 10 9 8 test007(9): a 5 5 10 17 8 test007(17): a 5 5 10 25 8 test007(25): a 20 20 44 n/a 32 Total RUN: ../pmccabe -X -vnt test007 CSL PCT NCSL PCT TOTAL FILENAME 0 0 32 100 32 test007 0 0 32 100 32 (total files: 1) RUN: ../pmccabe -x -vt test007 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 5 5 10 1 8 test007(1): a 5 5 10 9 8 test007(9): a 5 5 10 17 8 test007(17): a 5 5 10 25 8 test007(25): a 20 20 44 n/a 32 Total pmccabe-v2.8/tests/test008000066400000000000000000000002011400136053700154270ustar00rootroot00000000000000/* XOR test */ fn1() { if ((a > 1) && (b > 2)) { x(1); } } fn2() { if ((a > 1) ^ (b > 2)) { x(1); } } pmccabe-v2.8/tests/test008.ref000066400000000000000000000020171400136053700162110ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test008 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 3 3 2 2 7 test008(2): fn1 2 2 2 10 7 test008(10): fn2 5 5 6 n/a 16 Total RUN: ../pmccabe -X -vnt test008 CSL PCT NCSL PCT TOTAL FILENAME 2 12 14 88 16 test008 2 12 14 88 16 (total files: 1) RUN: ../pmccabe -x -vt test008 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 3 3 2 2 7 test008(2): fn1 2 2 2 10 7 test008(10): fn2 5 5 6 n/a 16 Total pmccabe-v2.8/tests/test009000066400000000000000000000003761400136053700154450ustar00rootroot00000000000000 extern int bar(int); void function1() { class class1 { int amember(int i) { class class2 { int bmember(){return 1;}; } for (i = 0; i < 100; i++) bar(i); return i; }; }; class1 xx; xx.amember(100); } pmccabe-v2.8/tests/test009.ref000066400000000000000000000023131400136053700162110ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test009 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 13 1 test009(13): function1/class1::amember/class2::bmember 2 2 4 9 10 test009(9): function1/class1::amember 1 1 2 4 20 test009(5): function1 4 4 9 n/a 23 Total RUN: ../pmccabe -X -vnt test009 CSL PCT NCSL PCT TOTAL FILENAME 3 13 20 87 23 test009 3 13 20 87 23 (total files: 1) RUN: ../pmccabe -x -vt test009 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 13 1 test009(13): function1/class1::amember/class2::bmember 2 2 4 9 10 test009(9): function1/class1::amember 1 1 2 4 20 test009(5): function1 4 4 9 n/a 23 Total pmccabe-v2.8/tests/test010000066400000000000000000000001001400136053700154160ustar00rootroot00000000000000# define foo a \ multi \ line \ cpp \ directive int a = 1; pmccabe-v2.8/tests/test010.ref000066400000000000000000000016411400136053700162040ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test010 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 7 Total RUN: ../pmccabe -X -vnt test010 CSL PCT NCSL PCT TOTAL FILENAME 1 14 6 86 7 test010 1 14 6 86 7 (total files: 1) RUN: ../pmccabe -x -vt test010 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 7 Total pmccabe-v2.8/tests/test011000066400000000000000000000002221400136053700154240ustar00rootroot00000000000000 struct foo * function1(int a) { return 1; } struct foo function2(int a) { return 1; } struct foo & function3(int a) { return 1; } pmccabe-v2.8/tests/test011.ref000066400000000000000000000021471400136053700162070ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test011 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 2 5 test011(3): function1 1 1 1 8 5 test011(9): function2 1 1 1 14 5 test011(15): function3 3 3 6 n/a 18 Total RUN: ../pmccabe -X -vnt test011 CSL PCT NCSL PCT TOTAL FILENAME 3 17 15 83 18 test011 3 17 15 83 18 (total files: 1) RUN: ../pmccabe -x -vt test011 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 2 5 test011(3): function1 1 1 1 8 5 test011(9): function2 1 1 1 14 5 test011(15): function3 3 3 6 n/a 18 Total pmccabe-v2.8/tests/test012000066400000000000000000000000161400136053700154260ustar00rootroot00000000000000class foo {}; pmccabe-v2.8/tests/test012.ref000066400000000000000000000016411400136053700162060ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test012 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 1 Total RUN: ../pmccabe -X -vnt test012 CSL PCT NCSL PCT TOTAL FILENAME 0 0 1 100 1 test012 0 0 1 100 1 (total files: 1) RUN: ../pmccabe -x -vt test012 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 1 Total pmccabe-v2.8/tests/test013000066400000000000000000000000701400136053700154270ustar00rootroot00000000000000int foo(a, b) const char *a, *b; { a = b; return a; } pmccabe-v2.8/tests/test013.ref000066400000000000000000000017251400136053700162120ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test013 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 2 1 6 test013(1): foo 1 1 3 n/a 6 Total RUN: ../pmccabe -X -vnt test013 CSL PCT NCSL PCT TOTAL FILENAME 0 0 6 100 6 test013 0 0 6 100 6 (total files: 1) RUN: ../pmccabe -x -vt test013 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 2 1 6 test013(1): foo 1 1 3 n/a 6 Total pmccabe-v2.8/tests/test014000066400000000000000000000001551400136053700154340ustar00rootroot00000000000000/* test from xianjie zhang */ void main(void) { if ( test(var1, class)) { /* this line causes problem */ } } pmccabe-v2.8/tests/test014.ref000066400000000000000000000017271400136053700162150ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test014 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 2 2 1 2 6 test014(3): main 2 2 2 n/a 7 Total RUN: ../pmccabe -X -vnt test014 CSL PCT NCSL PCT TOTAL FILENAME 1 14 6 86 7 test014 1 14 6 86 7 (total files: 1) RUN: ../pmccabe -x -vt test014 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 2 2 1 2 6 test014(3): main 2 2 2 n/a 7 Total pmccabe-v2.8/tests/test015000066400000000000000000000015341400136053700154370ustar00rootroot00000000000000namespace Spreadsheetns { ACosFormula::ACosFormula() { //empty } ACosFormula::ACosFormula(IFormula* formula) : IOneArgFormula(formula) { if((formula->getResult() < -1) || (formula->getResult() > 1)) { throw DomainErrorException("acos is defined in de range [-1 , 1]"); } } double ACosFormula::getResult(){ if((fArgument->getResult() < -1) || (fArgument->getResult() > 1)) { throw DomainErrorException("acos is defined in de range [-1 , 1]"); } return (acos(fArgument->getResult()) * 180/DEF_PI); } } namespace foo { class bar { bar() {}; }; namespace foo1 { class bar { bar() {}; }; } int fff(void) { } }; class bar { bar() {}; }; namespace { class bar { bar() {}; }; } // Inspiration for adding namespaces and some of this test come // from Bart Van Rompaey pmccabe-v2.8/tests/test015.ref000066400000000000000000000032571400136053700162160ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test015 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 2 3 test015(2): Spreadsheetns::ACosFormula::ACosFormula 3 3 3 6 5 test015(6): Spreadsheetns::ACosFormula::ACosFormula 3 3 3 12 6 test015(12): Spreadsheetns::ACosFormula::getResult 1 1 0 21 1 test015(21): foo::bar::bar 1 1 0 25 1 test015(25): foo::foo1::bar::bar 1 1 0 28 2 test015(28): foo::fff 1 1 0 32 1 test015(32): bar::bar 1 1 0 36 1 test015(36): anonymous_namespace::bar::bar 12 12 8 n/a 40 Total RUN: ../pmccabe -X -vnt test015 CSL PCT NCSL PCT TOTAL FILENAME 5 12 35 88 40 test015 5 12 35 88 40 (total files: 1) RUN: ../pmccabe -x -vt test015 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 2 3 test015(2): Spreadsheetns::ACosFormula::ACosFormula 3 3 3 6 5 test015(6): Spreadsheetns::ACosFormula::ACosFormula 3 3 3 12 6 test015(12): Spreadsheetns::ACosFormula::getResult 1 1 0 21 1 test015(21): foo::bar::bar 1 1 0 25 1 test015(25): foo::foo1::bar::bar 1 1 0 28 2 test015(28): foo::fff 1 1 0 32 1 test015(32): bar::bar 1 1 0 36 1 test015(36): anonymous_namespace::bar::bar 12 12 8 n/a 40 Total pmccabe-v2.8/tests/test016000066400000000000000000000005231400136053700154350ustar00rootroot00000000000000class Foo { public: const struct XXX::XXX_Local_config *Get(void); /* this line caused an infinite loop looking for '{' */ Foo() : configuration(NULL) {} private: struct XXX::XXX_Local_config* configuration; /* this line caused an infinite loop looking for '{' */ void after_potential_parsing_hang() { return; } }; pmccabe-v2.8/tests/test016.ref000066400000000000000000000021251400136053700162100ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test016 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 5 1 test016(5): Foo::Foo 1 1 1 10 1 test016(10): Foo::after_potential_parsing_hang 2 2 3 n/a 12 Total RUN: ../pmccabe -X -vnt test016 CSL PCT NCSL PCT TOTAL FILENAME 4 33 8 67 12 test016 4 33 8 67 12 (total files: 1) RUN: ../pmccabe -x -vt test016 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 5 1 test016(5): Foo::Foo 1 1 1 10 1 test016(10): Foo::after_potential_parsing_hang 2 2 3 n/a 12 Total pmccabe-v2.8/tests/test017000077500000000000000000000004371400136053700154450ustar00rootroot00000000000000#include class Foo { void fmt(const char* fmt, ...) const __attribute__ ((format (printf,1,2))); char *timidity_ctl_command(const char *fmt, ...) GCC_PRINTF(2, 3); int64_t *command(const char *fmt, ...) const volatile throw() _ATTRIBUTE(1, 2); }; pmccabe-v2.8/tests/test017.ref000066400000000000000000000016411400136053700162130ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test017 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 8 Total RUN: ../pmccabe -X -vnt test017 CSL PCT NCSL PCT TOTAL FILENAME 1 12 7 88 8 test017 1 12 7 88 8 (total files: 1) RUN: ../pmccabe -x -vt test017 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 8 Total pmccabe-v2.8/tests/test018000077500000000000000000000000661400136053700154440ustar00rootroot00000000000000#define con("%x %x\n", \ 0x0) void foo() {} pmccabe-v2.8/tests/test018.ref000066400000000000000000000017651400136053700162230ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test018 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 5 1 test018(5): foo 1 1 1 n/a 5 Total RUN: ../pmccabe -X -vnt test018 CSL PCT NCSL PCT TOTAL FILENAME 2 40 3 60 5 test018 2 40 3 60 5 (total files: 1) RUN: ../pmccabe -x -vt test018 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 2 4 test018(5): foo 1 1 1 n/a 5 Total "test018", line 3: too many )'s pmccabe-v2.8/tests/test019000066400000000000000000000011141400136053700154350ustar00rootroot00000000000000#ifndef FLOW_ID_HPP_ #define FLOW_ID_HPP_ #include #include class FlowID : public Comparable { public: FlowID(const sockaddr& sourceAddress, const sockaddr& destAddress); FlowID(const TCPAddress& sourceAddress, const TCPAddress& destAddress); FlowID(const FlowID& flowID); ~FlowID() throw(); // throw() because of call from a ctor or dtor virtual int compareTo(const Comparable& anotherFlowID) const; TCPAddress source() const; TCPAddress destination() const; private: TCPAddress _source; TCPAddress _destination; }; #endif // FLOW_ID_HPP_ pmccabe-v2.8/tests/test019.ref000066400000000000000000000016431400136053700162170ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test019 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 23 Total RUN: ../pmccabe -X -vnt test019 CSL PCT NCSL PCT TOTAL FILENAME 4 17 19 83 23 test019 4 17 19 83 23 (total files: 1) RUN: ../pmccabe -x -vt test019 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 23 Total pmccabe-v2.8/tests/test020000077500000000000000000000016071400136053700154370ustar00rootroot00000000000000struct sniff_tcp { u_short th_sport; /* source port */ u_short th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ u_char th_offx2; /* data offset, rsvd */ #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4) u_char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECE 0x40 #define TH_CWR 0x80 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR) u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ }; pmccabe-v2.8/tests/test020.ref000066400000000000000000000016431400136053700162070ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test020 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 21 Total RUN: ../pmccabe -X -vnt test020 CSL PCT NCSL PCT TOTAL FILENAME 0 0 21 100 21 test020 0 0 21 100 21 (total files: 1) RUN: ../pmccabe -x -vt test020 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 21 Total pmccabe-v2.8/tests/test021000066400000000000000000000010351400136053700154300ustar00rootroot00000000000000#ifndef TEST021_INCLUDED #define TEST021_INCLUDED #if 0 namespace XXX { #endif #if 0 // never #else // always #endif void total_lack_of_modularity() { #ifdef UNIX # if FORCE_STORED if (true) { # else if (false) { # endif /* FORCE_STORED */ work(); #if !FORCE_STATIC } else if (42 == 42) { # endif /* ! FORCE_STATIC */ # if FORCE_STATIC } else if (1 != 0) { # else } else while (1) { # if 0 } # endif /* 0 */ # endif /* FORCE_STATIC */ } #endif /* UNIX */ } #undef UNIX #endif // TEST021_INCLUDED pmccabe-v2.8/tests/test021.ref000066400000000000000000000021161400136053700162040ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test021 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 4 4 4 14 24 test021(14): total_lack_of_modularity 4 4 5 n/a 41 Total RUN: ../pmccabe -X -vnt test021 CSL PCT NCSL PCT TOTAL FILENAME 12 29 29 71 41 test021 12 29 29 71 41 (total files: 1) RUN: ../pmccabe -x -vt test021 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 7 7 7 14 24 test021(14): XXX::total_lack_of_modularity 7 7 8 n/a 41 Total "test021", line 42: expected closing } for namespace, but got EOF pmccabe-v2.8/tests/test022000066400000000000000000000001441400136053700154310ustar00rootroot00000000000000#ifdef ENABLE_LOL #include "kyra/lol.h" #else // #if ENABLE_LOL #include "kyra/screen_v2.h" #endif pmccabe-v2.8/tests/test022.ref000066400000000000000000000016411400136053700162070ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test022 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 0 n/a 6 Total RUN: ../pmccabe -X -vnt test022 CSL PCT NCSL PCT TOTAL FILENAME 1 17 5 83 6 test022 1 17 5 83 6 (total files: 1) RUN: ../pmccabe -x -vt test022 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 0 n/a 6 Total pmccabe-v2.8/tests/test023000066400000000000000000000002011400136053700154240ustar00rootroot00000000000000#if defined(ANDROID_BACKEND) #if 0 static void checkGlError(const char* file, int line) { warning(""); } #else #endif #endif pmccabe-v2.8/tests/test023.ref000066400000000000000000000017061400136053700162120ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test023 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 0 n/a 10 Total RUN: ../pmccabe -X -vnt test023 CSL PCT NCSL PCT TOTAL FILENAME 5 50 5 50 10 test023 5 50 5 50 10 (total files: 1) RUN: ../pmccabe -x -vt test023 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 4 3 test023(4): checkGlError 1 1 2 n/a 10 Total pmccabe-v2.8/tests/test024000066400000000000000000000012361400136053700154360ustar00rootroot00000000000000// this code from scummvm triggered stack corruption in countfunction() static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3, u16 s4, u16 *dest) { #if 0 asm("and %0, %2, %1, lsr #5" : "=r"(gs4) : "r"(s4), "r"(mask) : ); asm("and %0, %2, %1, lsr #5" : "=r"(gs4) : "r"(s4), "r"(mask) : ); asm("and %0, %2, %1, lsr #5" : "=r"(gs4) : "r"(s4), "r"(mask) : ); asm("and %0, %2, %1, lsr #5" : "=r"(gs4) : "r"(s4), "r"(mask) : ); asm("and %0, %2, %1, lsr #5" : "=r"(gs4) : "r"(s4), "r"(mask) : ); asm("and %0, %2, %1, lsr #10" : "=r"(rs0) : "r"(s0), "r"(mask) : ); #endif } pmccabe-v2.8/tests/test024.ref000066400000000000000000000020151400136053700162050ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test024 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 3 11 test024(3): RescaleBlock_5x1555_To_4x1555 1 1 1 n/a 13 Total RUN: ../pmccabe -X -vnt test024 CSL PCT NCSL PCT TOTAL FILENAME 8 62 5 38 13 test024 8 62 5 38 13 (total files: 1) RUN: ../pmccabe -x -vt test024 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 6 3 11 test024(3): RescaleBlock_5x1555_To_4x1555 1 1 7 n/a 13 Total pmccabe-v2.8/tests/test025000066400000000000000000000055441400136053700154450ustar00rootroot00000000000000// highlighted some memory corruption that was found using valgrind namespace Base { #if X static const char HELP_STRING[] = " +g, ++FILTERZ+mode=MODE Select graphics scaler [1x,2x,3x,2xsai,super2xsai,\n" " supereagle,advmame2x,advmame3x,hq2x,hq3x,tv2x,\n" " dotmatrix]\n" " ++gui+theme=THEME Select GUI theme\n" " ++themepath=PATH Path to where GUI themes are stored\n" " ++list+themes Display list of all usable GUI themes\n" " +e, ++center+module=MODE Select center module [see README for details]\n" " +q, ++language=LANG Select language [en,de,fr,it,pt,es,jp,zh,kr,se,gb,\n" " hb,ru,cz]\n" " +m, ++center+volume=NUM Set the center volume, X+255 [default: 192]\n" " +s, ++sub+volume=NUM Set the sub volume, X+255 [default: 192]\n" " +r, ++rumble+volume=NUM Set the rumble volume, X+255 [default: 192]\n" " ++LOOP+gain=NUM Set the gain for LOOP playback, X+1XXX [default:\n" " 1XX] [only supported by some LOOP modules]\n" " +n, ++subtitles Enable subtitles [use with games that have voice]\n" " +b, ++boot+param=NUM Pass number to the boot script [boot param]\n" " +d, ++debuglevel=NUM Set debug verbosity level\n" " ++debugflags=FLAGS Enable engine specific debug flags\n" " [separated by commas]\n" " +u, ++dump+scripts Enable script dumping if a directory called 'dumps'\n" " exists in the current directory\n" "\n" " ++cdrom=NUM CD drive to play CD audio from [default: X = first\n" " drive]\n" " ++joystick[=NUM] Enable joystick input [default: X = first joystick]\n" " ++platform=WORD Specify platform of game [allowed values: 2gs, 3do,\n" " acorn, amiga, atari, c64, fmtowns, nes, mac, pc, pc98,\n" " pce, segacd, wii, windows]\n" " ++savepath=PATH Path to where savegames are stored\n" " ++extrapath=PATH Extra path to additional game data\n" " ++soundfont=FILE Select the SoundFont for LOOP playback [only\n" " supported by some LOOP modules]\n" " ++multi+LOOP Enable combination AdLib and native LOOP\n" " ++native+mt32 True Roland MT+32 [disable GM emulation]\n" " ++enable+gs Enable Roland GS mode for LOOP playback\n" " ++output+rate=RATE Select output sample rate in Hz [e.g. 22X5X]\n" " ++opl+module=DRIVER Select AdLib [OPL] emulator [db, mame]\n" " ++aspect+ratio Enable aspect ratio correction\n" " ++render+mode=MODE Enable additional render modes [cga, ega, hercGreen,\n" " hercAmber, amiga]\n" "\n"; #endif } // End of namespace Base pmccabe-v2.8/tests/test025.ref000066400000000000000000000016431400136053700162140ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test025 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 49 Total RUN: ../pmccabe -X -vnt test025 CSL PCT NCSL PCT TOTAL FILENAME 3 6 46 94 49 test025 3 6 46 94 49 (total files: 1) RUN: ../pmccabe -x -vt test025 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 0 0 1 n/a 49 Total pmccabe-v2.8/tests/test026000066400000000000000000000307041400136053700154420ustar00rootroot00000000000000/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/tinsel/detection.cpp $ * $Id: detection.cpp 49788 2010-06-15 10:59:23Z sev $ * */ #include "base/plugins.h" #include "engines/advancedDetector.h" #include "common/file.h" #include "common/md5.h" #include "common/savefile.h" #include "tinsel/bmv.h" #include "tinsel/cursor.h" #include "tinsel/tinsel.h" #include "tinsel/savescn.h" // needed by TinselMetaEngine::listSaves namespace Tinsel { struct TinselGameDescription { ADGameDescription desc; int gameID; int gameType; uint32 features; uint16 version; }; uint32 TinselEngine::getGameID() const { return _gameDescription->gameID; } uint32 TinselEngine::getFeatures() const { return _gameDescription->features; } Common::Language TinselEngine::getLanguage() const { return _gameDescription->desc.language; } Common::Platform TinselEngine::getPlatform() const { return _gameDescription->desc.platform; } uint16 TinselEngine::getVersion() const { return _gameDescription->version; } } static const PlainGameDescriptor tinselGames[] = { {"tinsel", "Tinsel engine game"}, {"dw", "Discworld"}, {"dw2", "Discworld 2: Missing Presumed ...!?"}, {0, 0} }; #include "tinsel/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure (const byte *)Tinsel::gameDescriptions, // Size of that superset structure sizeof(Tinsel::TinselGameDescription), // Number of bytes to compute MD5 sum for 5000, // List of all engine targets tinselGames, // Structure for autoupgrading obsolete targets 0, // Name of single gameid (optional) "tinsel", // List of files for file-based fallback detection (optional) 0, // Flags 0, // Additional GUI options (for every game} Common::GUIO_NONE, // Maximum directory depth 1, // List of directory globs 0 }; class TinselMetaEngine : public AdvancedMetaEngine { public: TinselMetaEngine() : AdvancedMetaEngine(detectionParams) {} virtual const char *getName() const { return "Tinsel Engine"; } virtual const char *getOriginalCopyright() const { return "Tinsel (C) Psygnosis"; } virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const; virtual bool hasFeature(MetaEngineFeature f) const; virtual SaveStateList listSaves(const char *target) const; virtual int getMaximumSaveSlot() const; virtual void removeSaveState(const char *target, int slot) const; }; bool TinselMetaEngine::hasFeature(MetaEngineFeature f) const { return (f == kSupportsListSaves) || (f == kSupportsLoadingDuringStartup) || (f == kSupportsDeleteSave); } bool Tinsel::TinselEngine::hasFeature(EngineFeature f) const { return #if 0 // FIXME: tinsel does not exit cleanly yet (f == kSupportsRTL) || #endif (f == kSupportsLoadingDuringRuntime); } namespace Tinsel { extern int getList(Common::SaveFileManager *saveFileMan, const Common::String &target); } SaveStateList TinselMetaEngine::listSaves(const char *target) const { Common::String pattern = target; pattern = pattern + ".???"; Common::StringArray files = g_system->getSavefileManager()->listSavefiles(pattern); sort(files.begin(), files.end()); // Sort (hopefully ensuring we are sorted numerically..) SaveStateList saveList; int slotNum = 0; for (Common::StringArray::const_iterator file = files.begin(); file != files.end(); ++file) { // Obtain the last 3 digits of the filename, since they correspond to the save slot slotNum = atoi(file->c_str() + file->size() - 3); const Common::String &fname = *file; Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fname); if (in) { in->readUint32LE(); // skip id in->readUint32LE(); // skip size in->readUint32LE(); // skip version char saveDesc[Tinsel::SG_DESC_LEN]; in->read(saveDesc, sizeof(saveDesc)); saveDesc[Tinsel::SG_DESC_LEN - 1] = 0; saveList.push_back(SaveStateDescriptor(slotNum, saveDesc)); delete in; } } return saveList; } bool TinselMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { const Tinsel::TinselGameDescription *gd = (const Tinsel::TinselGameDescription *)desc; if (gd) { *engine = new Tinsel::TinselEngine(syst, gd); } return gd != 0; } struct SizeMD5 { int size; char md5[32+1]; }; typedef Common::HashMap SizeMD5Map; typedef Common::HashMap FileMap; typedef Common::Array ADGameDescList; /** * Fallback detection scans the list of Discworld 2 targets to see if it can detect an installation * where the files haven't been renamed (i.e. don't have the '1' just before the extension) */ const ADGameDescription *TinselMetaEngine::fallbackDetect(const Common::FSList &fslist) const { Common::String extra; FileMap allFiles; SizeMD5Map filesSizeMD5; const ADGameFileDescription *fileDesc; const Tinsel::TinselGameDescription *g; if (fslist.empty()) return NULL; // First we compose a hashmap of all files in fslist. // Includes nifty stuff like removing trailing dots and ignoring case. for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (file->isDirectory()) { if (!scumm_stricmp(file->getName().c_str(), "dw2")) { // Probably Discworld 2 subfolder on CD, so add it's contents as well Common::FSList files; if (file->getChildren(files, Common::FSNode::kListAll)) { Common::FSList::const_iterator file2; for (file2 = files.begin(); file2 != files.end(); ++file2) { if (file2->isDirectory()) continue; Common::String fname = file2->getName(); allFiles[fname] = *file2; } } } continue; } Common::String tstr = file->getName(); allFiles[tstr] = *file; // Record the presence of this file } // Check which files are included in some dw2 ADGameDescription *and* present // in fslist without a '1' suffix character. Compute MD5s and file sizes for these files. for (g = &Tinsel::gameDescriptions[0]; g->desc.gameid != 0; ++g) { if (strcmp(g->desc.gameid, "dw2") != 0) continue; for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) { // Get the next filename, stripping off any '1' suffix character char tempFilename[50]; strcpy(tempFilename, fileDesc->fileName); char *pOne = strchr(tempFilename, '1'); if (pOne) { do { *pOne = *(pOne + 1); pOne++; } while (*pOne); } Common::String fname(tempFilename); if (allFiles.contains(fname) && !filesSizeMD5.contains(fname)) { SizeMD5 tmp; Common::File testFile; if (testFile.open(allFiles[fname])) { tmp.size = (int32)testFile.size(); if (!md5_file_string(testFile, tmp.md5, detectionParams.md5Bytes)) tmp.md5[0] = 0; } else { tmp.size = -1; tmp.md5[0] = 0; } filesSizeMD5[fname] = tmp; } } } ADGameDescList matched; int maxFilesMatched = 0; bool gotAnyMatchesWithAllFiles = false; // MD5 based matching uint i; for (i = 0, g = &Tinsel::gameDescriptions[0]; g->desc.gameid != 0; ++g) { if (strcmp(g->desc.gameid, "dw2") != 0) continue; bool fileMissing = false; if ((detectionParams.flags & kADFlagUseExtraAsHint) && !extra.empty() && g->desc.extra != extra) continue; bool allFilesPresent = true; // Try to match all files for this game for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) { // Get the next filename, stripping off any '1' suffix character char tempFilename[50]; strcpy(tempFilename, fileDesc->fileName); char *pOne = strchr(tempFilename, '1'); if (pOne) { do { *pOne = *(pOne + 1); pOne++; } while (*pOne); } Common::String tstr(tempFilename); if (!filesSizeMD5.contains(tstr)) { fileMissing = true; allFilesPresent = false; break; } if (fileDesc->md5 != NULL && 0 != strcmp(fileDesc->md5, filesSizeMD5[tstr].md5)) { fileMissing = true; break; } if (fileDesc->fileSize != -1 && fileDesc->fileSize != filesSizeMD5[tstr].size) { fileMissing = true; break; } } if (allFilesPresent) gotAnyMatchesWithAllFiles = true; if (!fileMissing) { // Count the number of matching files. Then, only keep those // entries which match a maximal amount of files. int curFilesMatched = 0; for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) curFilesMatched++; if (curFilesMatched > maxFilesMatched) { maxFilesMatched = curFilesMatched; for (uint j = 0; j < matched.size();) { if (matched[j]->flags & ADGF_KEEPMATCH) ++j; else matched.remove_at(j); } matched.push_back((const ADGameDescription *)g); } else if (curFilesMatched == maxFilesMatched) { matched.push_back((const ADGameDescription *)g); } } } // We didn't find a match if (matched.empty()) return NULL; return *matched.begin(); } int TinselMetaEngine::getMaximumSaveSlot() const { return 99; } void TinselMetaEngine::removeSaveState(const char *target, int slot) const { Tinsel::setNeedLoad(); Tinsel::getList(g_system->getSavefileManager(), target); g_system->getSavefileManager()->removeSavefile(Tinsel::ListEntry(slot, Tinsel::LE_NAME)); Tinsel::setNeedLoad(); Tinsel::getList(g_system->getSavefileManager(), target); } #if PLUGIN_ENABLED_DYNAMIC(TINSEL) REGISTER_PLUGIN_DYNAMIC(TINSEL, PLUGIN_TYPE_ENGINE, TinselMetaEngine); #else REGISTER_PLUGIN_STATIC(TINSEL, PLUGIN_TYPE_ENGINE, TinselMetaEngine); #endif namespace Tinsel { Common::Error TinselEngine::loadGameState(int slot) { // FIXME: Hopefully this is only used when loading games via // the launcher, since we do a hacky savegame slot to savelist // entry mapping here. // // You might wonder why is needed and here is the answer: // The save/load dialog of the GMM operates with the physical // savegame slots, while Tinsel internally uses entry numbers in // a savelist (which is sorted latest to first). Now to allow // proper loading of (especially Discworld2) saves we need to // get a savelist entry number instead of the physical slot. // // There are different possible solutions: // // One way to fix this would be to pass the filename instead of // the savelist entry number to RestoreGame, though it could make // problems how DW2 handles CD switches. Normally DW2 would pass // '-2' as slot when it changes CDs. // // Another way would be to convert all of Tinsel to use physical // slot numbers instead of savelist entry numbers for loading. // This would also allow '-2' as slot for CD changes without // any major hackery. int listSlot = -1; const int numStates = Tinsel::getList(); for (int i = 0; i < numStates; ++i) { const char *fileName = Tinsel::ListEntry(i, Tinsel::LE_NAME); const int saveSlot = atoi(fileName + strlen(fileName) - 3); if (saveSlot == slot) { listSlot = i; break; } } if (listSlot == -1) return Common::kUnknownError; // TODO: proper error code RestoreGame(listSlot); return Common::kNoError; // TODO: return success/failure } #if 0 Common::Error TinselEngine::saveGameState(int slot, const char *desc) { Common::String saveName = _vm->getSavegameFilename((int16)(slot + 1)); char saveDesc[SG_DESC_LEN]; Common::strlcpy(saveDesc, desc, SG_DESC_LEN); SaveGame((char *)saveName.c_str(), saveDesc); ProcessSRQueue(); // This shouldn't be needed, but for some reason it is... return Common::kNoError; // TODO: return success/failure } #endif } // End of namespace Tinsel pmccabe-v2.8/tests/test026.ref000066400000000000000000000055171400136053700162210ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test026 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 49 3 test026(49): Tinsel::TinselEngine::getGameID 1 1 1 53 3 test026(53): Tinsel::TinselEngine::getFeatures 1 1 1 57 3 test026(57): Tinsel::TinselEngine::getLanguage 1 1 1 61 3 test026(61): Tinsel::TinselEngine::getPlatform 1 1 1 65 3 test026(65): Tinsel::TinselEngine::getVersion 1 1 1 107 1 test026(107): TinselMetaEngine::TinselMetaEngine 1 1 1 109 3 test026(109): TinselMetaEngine::getName 1 1 1 113 3 test026(113): TinselMetaEngine::getOriginalCopyright 3 3 1 126 6 test026(126): TinselMetaEngine::hasFeature 1 1 1 133 8 test026(133): Tinsel::TinselEngine::hasFeature 3 3 22 146 30 test026(146): TinselMetaEngine::listSaves 2 2 4 177 7 test026(177): TinselMetaEngine::createInstance 38 38 109 197 155 test026(197): TinselMetaEngine::fallbackDetect 1 1 1 353 1 test026(353): TinselMetaEngine::getMaximumSaveSlot 1 1 5 355 8 test026(355): TinselMetaEngine::removeSaveState 4 4 14 372 42 test026(372): Tinsel::TinselEngine::loadGameState 61 61 182 n/a 425 Total RUN: ../pmccabe -X -vnt test026 CSL PCT NCSL PCT TOTAL FILENAME 155 36 270 64 425 test026 155 36 270 64 425 (total files: 1) RUN: ../pmccabe -x -vt test026 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 1 49 3 test026(49): Tinsel::TinselEngine::getGameID 1 1 1 53 3 test026(53): Tinsel::TinselEngine::getFeatures 1 1 1 57 3 test026(57): Tinsel::TinselEngine::getLanguage 1 1 1 61 3 test026(61): Tinsel::TinselEngine::getPlatform 1 1 1 65 3 test026(65): Tinsel::TinselEngine::getVersion 1 1 1 107 1 test026(107): TinselMetaEngine::TinselMetaEngine 1 1 1 109 3 test026(109): TinselMetaEngine::getName 1 1 1 113 3 test026(113): TinselMetaEngine::getOriginalCopyright 3 3 1 126 6 test026(126): TinselMetaEngine::hasFeature 2 2 1 133 8 test026(133): Tinsel::TinselEngine::hasFeature 3 3 22 146 30 test026(146): TinselMetaEngine::listSaves 2 2 4 177 7 test026(177): TinselMetaEngine::createInstance 38 38 109 197 155 test026(197): TinselMetaEngine::fallbackDetect 1 1 1 353 1 test026(353): TinselMetaEngine::getMaximumSaveSlot 1 1 5 355 8 test026(355): TinselMetaEngine::removeSaveState 4 4 14 372 42 test026(372): Tinsel::TinselEngine::loadGameState 1 1 6 416 8 test026(416): Tinsel::TinselEngine::saveGameState 63 63 189 n/a 425 Total pmccabe-v2.8/tests/test027000066400000000000000000000002321400136053700154340ustar00rootroot00000000000000namespace Foo { class Bar { public: Bar() {} ~Bar() {} enum class foobar { YES, NO, FILE_NOT_FOUND }; void hello(); }; } pmccabe-v2.8/tests/test027.ref000066400000000000000000000020651400136053700162150ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test027 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 7 1 test027(7): Foo::Bar::Bar 1 1 0 8 1 test027(8): Foo::Bar::~Bar 2 2 0 n/a 15 Total RUN: ../pmccabe -X -vnt test027 CSL PCT NCSL PCT TOTAL FILENAME 1 7 14 93 15 test027 1 7 14 93 15 (total files: 1) RUN: ../pmccabe -x -vt test027 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 0 7 1 test027(7): Foo::Bar::Bar 1 1 0 8 1 test027(8): Foo::Bar::~Bar 2 2 0 n/a 15 Total pmccabe-v2.8/tests/testlist.ref000066400000000000000000000576771400136053700167030ustar00rootroot00000000000000RUN: ../pmccabe -X -vt test000 test001 test002 test003 test004 test005 test006/Grapher.H test006/Handler.H test006/NodeArc.H test007 test008 test009 test010 test011 test012 test013 test014 test015 test016 test017 test018 test019 test020 test021 test022 test023 test024 test025 test026 test027 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 3 6 6 test000(6): Add::Add 1 1 2 13 5 test000(13): Add::~Add 1 1 1 19 4 test000(19): Add::print 4 8 18 24 35 test000(24): Add::eval 1 1 1 60 4 test000(60): Add::modified_attributes 1 1 0 2 3 test001(2): start 1 1 0 7 6 test001(12): some_class::~some_class 1 1 0 14 1 test001(14): destructor::~destructor 1 1 0 15 1 test001(15): destructor2::~destructor 1 1 4 17 4 test001(17): main 1 1 0 22 1 test001(22): xyzzy::operator() 1 1 0 27 1 test001(27): named_class::member_function 1 1 0 32 1 test001(32): unnamed::member_function 1 1 0 35 3 test001(36): xyzzy::operator+= 1 1 1 1 1 test002(1): class1::class2::class3::member 1 1 1 3 1 test002(3): class1::class2::operator+= 1 1 1 5 1 test002(5): class4::operator+= 1 1 1 6 1 test003(6): T1::operator_long() 1 1 1 15 4 test003(15): T1::operator_long() 1 1 1 20 4 test003(20): T2::operator_long() 1 1 1 8 4 test004(8): T1::unnamed::member 1 1 1 17 4 test004(17): T1::T11::T12::member 1 1 1 22 1 test005(22): TypedValue::HasValue 1 1 1 23 1 test005(23): TypedValue::HasValue 1 1 1 24 1 test005(24): TypedValue::ResetValue 1 1 2 25 1 test005(25): TypedValue::ResetValuePtr 2 2 3 27 2 test005(27): TypedValue::Value 2 2 3 29 2 test005(29): TypedValue::ValueRef 1 1 3 31 2 test005(31): TypedValue::Value 1 1 3 34 1 test005(34): TypedValue::TypedValue 1 1 3 37 2 test005(37): TypedValue::TypedValue 1 1 2 39 1 test005(39): TypedValue::TypedValue 1 1 0 41 1 test005(41): TypedValue::DestroyValue 1 1 1 44 2 test005(45): TypedValue::HasType 1 1 1 46 1 test005(46): TypedValue::Type 1 1 1 49 1 test005(49): TypedValue::TypePtr 1 1 1 50 1 test005(50): TypedValue::TypePtr 1 1 1 58 1 test005(58): TypedValue::Assign 2 2 3 63 4 test005(65): TypedValue::print_type 1 1 3 16 11 test006/Grapher.H(16): Grapher::Grapher 1 1 0 27 1 test006/Grapher.H(27): Grapher::~Grapher 1 1 1 29 1 test006/Grapher.H(29): Grapher::xegraph 2 2 3 68 8 test006/Handler.H(68): ActionHandler::returnControl 1 1 3 77 4 test006/Handler.H(77): ActionHandler::ActionHandler 1 1 1 83 1 test006/Handler.H(83): ActionHandler::target 1 1 1 84 1 test006/Handler.H(84): ActionHandler::target 2 2 2 85 1 test006/Handler.H(85): ActionHandler::targetted 1 1 2 89 4 test006/Handler.H(89): ActionHandler::init 1 1 3 94 6 test006/Handler.H(94): ActionHandler::takeCharge 1 1 2 101 4 test006/Handler.H(101): ActionHandler::abort 1 1 1 117 4 test006/Handler.H(117): MotionHandler::initializeData 1 1 1 122 4 test006/Handler.H(122): MotionHandler::updateData 1 1 3 127 5 test006/Handler.H(127): MotionHandler::startMotion 1 1 4 132 6 test006/Handler.H(132): MotionHandler::updateMotion 1 1 4 138 6 test006/Handler.H(138): MotionHandler::endMotion 1 1 0 145 1 test006/Handler.H(145): MotionHandler::drawGhost 1 1 0 146 1 test006/Handler.H(146): MotionHandler::doIt 1 1 1 148 4 test006/Handler.H(148): MotionHandler::MotionHandler 1 1 1 155 1 test006/Handler.H(155): MotionHandler::isInitialEvent 1 1 1 156 1 test006/Handler.H(156): MotionHandler::isOkInitialTarget 1 1 1 157 1 test006/Handler.H(157): MotionHandler::isOkFinalTarget 1 1 3 174 6 test006/Handler.H(174): ArcHandler::indicateInitialTarget 1 1 1 180 4 test006/Handler.H(180): ArcHandler::indicateNoTarget 1 1 1 184 4 test006/Handler.H(184): ArcHandler::indicateFinalTarget 1 1 1 188 3 test006/Handler.H(188): ArcHandler::indicatePreviousCursor 4 4 6 192 15 test006/Handler.H(192): ArcHandler::drawGhost 1 1 1 208 4 test006/Handler.H(208): ArcHandler::isInitialEvent 2 2 2 213 4 test006/Handler.H(213): ArcHandler::isOkInitialTarget 2 2 2 217 4 test006/Handler.H(217): ArcHandler::isOkFinalTarget 1 1 2 227 5 test006/Handler.H(227): ArcHandler::ArcHandler 1 1 1 232 4 test006/Handler.H(232): ArcHandler::~ArcHandler 1 1 6 250 10 test006/Handler.H(250): ArcMaker::initializeData 2 2 6 260 10 test006/Handler.H(260): ArcMaker::startMotion 10 10 23 271 37 test006/Handler.H(271): ArcMaker::updateMotion 4 4 6 309 11 test006/Handler.H(309): ArcMaker::endMotion 1 1 4 321 10 test006/Handler.H(321): ArcMaker::doIt 2 2 1 332 4 test006/Handler.H(332): ArcMaker::isOkInitialTarget 1 1 1 336 4 test006/Handler.H(336): ArcMaker::isOkFinalTarget 1 1 1 342 4 test006/Handler.H(342): ArcMaker::ArcMaker 2 2 1 356 4 test006/Handler.H(356): ArcChanger::isOkInitialTarget 2 2 1 360 4 test006/Handler.H(360): ArcChanger::isOkFinalTarget 1 1 8 365 12 test006/Handler.H(365): ArcChanger::initializeData 2 2 6 378 12 test006/Handler.H(378): ArcChanger::startMotion 6 6 18 391 30 test006/Handler.H(391): ArcChanger::updateMotion 3 3 6 422 11 test006/Handler.H(422): ArcChanger::endMotion 1 1 1 436 4 test006/Handler.H(436): ArcChanger::ArcChanger 2 2 2 451 8 test006/Handler.H(451): NodeMaker::drawGhost 1 1 1 459 4 test006/Handler.H(459): NodeMaker::isInitialEvent 2 2 2 464 4 test006/Handler.H(464): NodeMaker::isOkInitialTarget 1 1 2 469 5 test006/Handler.H(469): NodeMaker::initializeData 1 1 2 474 5 test006/Handler.H(474): NodeMaker::updateData 1 1 1 482 4 test006/Handler.H(482): NodeMaker::NodeMaker 1 1 1 515 3 test006/Handler.H(515): Selector::deselect 2 2 6 519 10 test006/Handler.H(519): Selector::updateData 2 2 1 530 5 test006/Handler.H(530): Selector::isInitialEvent 1 1 1 536 5 test006/Handler.H(536): Selector::isOkInitialTarget 1 1 4 543 7 test006/Handler.H(543): Selector::Selector 1 1 3 570 10 test006/Handler.H(570): SweepSelector::updateData 2 2 6 581 13 test006/Handler.H(581): SweepSelector::startMotion 2 2 5 595 7 test006/Handler.H(595): SweepSelector::updateMotion 2 2 7 603 10 test006/Handler.H(603): SweepSelector::endMotion 2 2 2 616 8 test006/Handler.H(616): SweepSelector::drawGhost 1 1 1 625 4 test006/Handler.H(625): SweepSelector::isInitialEvent 1 1 1 630 4 test006/Handler.H(630): SweepSelector::isOkInitialTarget 1 1 1 636 4 test006/Handler.H(636): SweepSelector::SweepSelector 1 1 1 658 4 test006/Handler.H(658): SubgraphSelector::isInitialEvent 2 2 1 663 4 test006/Handler.H(663): SubgraphSelector::isOkInitialTarget 1 1 1 669 4 test006/Handler.H(669): SubgraphSelector::SubgraphSelector 1 1 0 681 1 test006/Handler.H(681): ItemMover::startMove 1 1 0 682 1 test006/Handler.H(682): ItemMover::updateMove 1 1 0 683 1 test006/Handler.H(683): ItemMover::endMove 2 2 1 685 3 test006/Handler.H(685): ItemMover::isOkInitialTarget 1 1 1 689 4 test006/Handler.H(689): ItemMover::ItemMover 1 1 4 706 6 test006/Handler.H(706): NodeMover::startMove 2 2 8 712 11 test006/Handler.H(712): NodeMover::updateMove 1 1 1 723 3 test006/Handler.H(723): NodeMover::endMove 1 1 1 728 4 test006/Handler.H(728): NodeMover::NodeMover 3 3 1 740 4 test006/Handler.H(740): SelectionMover::isOkInitialTarget 1 1 1 746 4 test006/Handler.H(746): SelectionMover::SelectionMover 1 1 1 758 4 test006/Handler.H(758): MenuHandler::MenuHandler 1 1 1 31 1 test006/NodeArc.H(31): LabelledNode::~LabelledNode 1 1 1 33 1 test006/NodeArc.H(33): LabelledNode::label 1 1 1 37 1 test006/NodeArc.H(37): LabelledNode::shapeType 1 1 1 39 1 test006/NodeArc.H(39): LabelledNode::borderWidth 1 1 1 40 1 test006/NodeArc.H(40): LabelledNode::borderWidth 1 1 1 42 1 test006/NodeArc.H(42): LabelledNode::xeNode 1 1 1 43 1 test006/NodeArc.H(43): LabelledNode::xeNode 2 2 5 107 10 test006/NodeArc.H(107): LabelledArc::arcContains 2 2 7 118 13 test006/NodeArc.H(118): LabelledArc::labelContains 1 1 3 134 6 test006/NodeArc.H(134): LabelledArc::getLabelOrigin 2 2 5 141 10 test006/NodeArc.H(141): LabelledArc::arrowPoints 1 1 6 152 9 test006/NodeArc.H(152): LabelledArc::arrowBoundingBox 4 4 9 162 12 test006/NodeArc.H(162): LabelledArc::arcBoundingBox 2 2 5 179 9 test006/NodeArc.H(179): LabelledArc::drawArrow 1 1 1 200 1 test006/NodeArc.H(200): LabelledArc::owner 1 1 1 202 1 test006/NodeArc.H(202): LabelledArc::getLabel 1 1 1 205 1 test006/NodeArc.H(205): LabelledArc::getLabelColor 1 1 1 208 1 test006/NodeArc.H(208): LabelledArc::getLabelVisible 1 1 3 234 1 test006/NodeArc.H(234): SiblingList::SiblingList 1 1 1 235 1 test006/NodeArc.H(235): SiblingList::~SiblingList 1 1 1 237 1 test006/NodeArc.H(237): SiblingList::count 1 1 1 238 1 test006/NodeArc.H(238): SiblingList::max 3 3 8 244 11 test006/NodeArc.H(244): SiblingList::isSibling 5 5 15 279 28 test006/NodeArc.H(279): RankedArc::arrowPoints 2 2 2 308 3 test006/NodeArc.H(308): RankedArc::computeRank 2 2 2 312 1 test006/NodeArc.H(312): RankedArc::selfish 6 6 19 314 52 test006/NodeArc.H(314): RankedArc::arcContains 4 4 9 369 15 test006/NodeArc.H(369): RankedArc::getLabelOrigin 5 5 20 385 40 test006/NodeArc.H(385): RankedArc::arcBoundingBox 3 3 8 426 14 test006/NodeArc.H(426): RankedArc::drawArc 5 5 11 441 43 test006/NodeArc.H(441): RankedArc::drawRankedArc 5 5 15 485 36 test006/NodeArc.H(485): RankedArc::drawArrow 2 2 3 526 7 test006/NodeArc.H(526): RankedArc::~RankedArc 5 5 10 1 8 test007(1): a 5 5 10 9 8 test007(9): a 5 5 10 17 8 test007(17): a 5 5 10 25 8 test007(25): a 3 3 2 2 7 test008(2): fn1 2 2 2 10 7 test008(10): fn2 1 1 1 13 1 test009(13): function1/class1::amember/class2::bmember 2 2 4 9 10 test009(9): function1/class1::amember 1 1 2 4 20 test009(5): function1 1 1 1 2 5 test011(3): function1 1 1 1 8 5 test011(9): function2 1 1 1 14 5 test011(15): function3 1 1 2 1 6 test013(1): foo 2 2 1 2 6 test014(3): main 1 1 0 2 3 test015(2): Spreadsheetns::ACosFormula::ACosFormula 3 3 3 6 5 test015(6): Spreadsheetns::ACosFormula::ACosFormula 3 3 3 12 6 test015(12): Spreadsheetns::ACosFormula::getResult 1 1 0 21 1 test015(21): foo::bar::bar 1 1 0 25 1 test015(25): foo::foo1::bar::bar 1 1 0 28 2 test015(28): foo::fff 1 1 0 32 1 test015(32): bar::bar 1 1 0 36 1 test015(36): anonymous_namespace::bar::bar 1 1 1 5 1 test016(5): Foo::Foo 1 1 1 10 1 test016(10): Foo::after_potential_parsing_hang 1 1 0 5 1 test018(5): foo 4 4 4 14 24 test021(14): total_lack_of_modularity 1 1 0 3 11 test024(3): RescaleBlock_5x1555_To_4x1555 1 1 1 49 3 test026(49): Tinsel::TinselEngine::getGameID 1 1 1 53 3 test026(53): Tinsel::TinselEngine::getFeatures 1 1 1 57 3 test026(57): Tinsel::TinselEngine::getLanguage 1 1 1 61 3 test026(61): Tinsel::TinselEngine::getPlatform 1 1 1 65 3 test026(65): Tinsel::TinselEngine::getVersion 1 1 1 107 1 test026(107): TinselMetaEngine::TinselMetaEngine 1 1 1 109 3 test026(109): TinselMetaEngine::getName 1 1 1 113 3 test026(113): TinselMetaEngine::getOriginalCopyright 3 3 1 126 6 test026(126): TinselMetaEngine::hasFeature 1 1 1 133 8 test026(133): Tinsel::TinselEngine::hasFeature 3 3 22 146 30 test026(146): TinselMetaEngine::listSaves 2 2 4 177 7 test026(177): TinselMetaEngine::createInstance 38 38 109 197 155 test026(197): TinselMetaEngine::fallbackDetect 1 1 1 353 1 test026(353): TinselMetaEngine::getMaximumSaveSlot 1 1 5 355 8 test026(355): TinselMetaEngine::removeSaveState 4 4 14 372 42 test026(372): Tinsel::TinselEngine::loadGameState 1 1 0 7 1 test027(7): Foo::Bar::Bar 1 1 0 8 1 test027(8): Foo::Bar::~Bar 359 363 793 n/a 2375 Total RUN: ../pmccabe -X -vnt test000 test001 test002 test003 test004 test005 test006/Grapher.H test006/Handler.H test006/NodeArc.H test007 test008 test009 test010 test011 test012 test013 test014 test015 test016 test017 test018 test019 test020 test021 test022 test023 test024 test025 test026 test027 CSL PCT NCSL PCT TOTAL FILENAME 10 16 54 84 64 test000 9 24 28 76 37 test001 2 40 3 60 5 test002 6 25 18 75 24 test003 1 4 22 96 23 test004 32 31 71 69 103 test005 11 34 21 66 32 test006/Grapher.H 152 20 618 80 770 test006/Handler.H 161 30 378 70 539 test006/NodeArc.H 0 0 32 100 32 test007 2 12 14 88 16 test008 3 13 20 87 23 test009 1 14 6 86 7 test010 3 17 15 83 18 test011 0 0 1 100 1 test012 0 0 6 100 6 test013 1 14 6 86 7 test014 5 12 35 88 40 test015 4 33 8 67 12 test016 1 12 7 88 8 test017 2 40 3 60 5 test018 4 17 19 83 23 test019 0 0 21 100 21 test020 12 29 29 71 41 test021 1 17 5 83 6 test022 5 50 5 50 10 test023 8 62 5 38 13 test024 3 6 46 94 49 test025 155 36 270 64 425 test026 1 7 14 93 15 test027 595 25 1780 75 2375 (total files: 30) RUN: ../pmccabe -x -vt test000 test001 test002 test003 test004 test005 test006/Grapher.H test006/Handler.H test006/NodeArc.H test007 test008 test009 test010 test011 test012 test013 test014 test015 test016 test017 test018 test019 test020 test021 test022 test023 test024 test025 test026 test027 Modified McCabe Cyclomatic Complexity | Traditional McCabe Cyclomatic Complexity | | # Statements in function | | | First line of function | | | | # lines in function | | | | | filename(definition line number):function | | | | | | 1 1 3 6 6 test000(6): Add::Add 1 1 2 13 5 test000(13): Add::~Add 1 1 1 19 4 test000(19): Add::print 4 8 18 24 35 test000(24): Add::eval 1 1 1 60 4 test000(60): Add::modified_attributes 1 1 0 2 3 test001(2): start 1 1 0 7 6 test001(12): some_class::~some_class 1 1 0 14 1 test001(14): destructor::~destructor 1 1 0 15 1 test001(15): destructor2::~destructor 1 1 4 17 4 test001(17): main 1 1 0 22 1 test001(22): xyzzy::operator() 1 1 0 27 1 test001(27): named_class::member_function 1 1 0 32 1 test001(32): unnamed::member_function 1 1 0 35 3 test001(36): xyzzy::operator+= 1 1 1 1 1 test002(1): class1::class2::class3::member 1 1 1 3 1 test002(3): class1::class2::operator+= 1 1 1 5 1 test002(5): class4::operator+= 1 1 1 6 1 test003(6): T1::operator_long() 1 1 1 15 4 test003(15): T1::operator_long() 1 1 1 20 4 test003(20): T2::operator_long() 1 1 1 8 4 test004(8): T1::unnamed::member 1 1 1 17 4 test004(17): T1::T11::T12::member 1 1 1 22 1 test005(22): TypedValue::HasValue 1 1 1 23 1 test005(23): TypedValue::HasValue 1 1 1 24 1 test005(24): TypedValue::ResetValue 1 1 2 25 1 test005(25): TypedValue::ResetValuePtr 2 2 3 27 2 test005(27): TypedValue::Value 2 2 3 29 2 test005(29): TypedValue::ValueRef 1 1 3 31 2 test005(31): TypedValue::Value 1 1 3 34 1 test005(34): TypedValue::TypedValue 1 1 3 37 2 test005(37): TypedValue::TypedValue 1 1 2 39 1 test005(39): TypedValue::TypedValue 1 1 0 41 1 test005(41): TypedValue::DestroyValue 1 1 1 44 2 test005(45): TypedValue::HasType 1 1 1 46 1 test005(46): TypedValue::Type 1 1 1 49 1 test005(49): TypedValue::TypePtr 1 1 1 50 1 test005(50): TypedValue::TypePtr 1 1 1 58 1 test005(58): TypedValue::Assign 2 2 3 63 4 test005(65): TypedValue::print_type 1 1 3 16 11 test006/Grapher.H(16): Grapher::Grapher 1 1 0 27 1 test006/Grapher.H(27): Grapher::~Grapher 1 1 1 29 1 test006/Grapher.H(29): Grapher::xegraph 2 2 3 68 8 test006/Handler.H(68): ActionHandler::returnControl 1 1 3 77 4 test006/Handler.H(77): ActionHandler::ActionHandler 1 1 1 83 1 test006/Handler.H(83): ActionHandler::target 1 1 1 84 1 test006/Handler.H(84): ActionHandler::target 2 2 2 85 1 test006/Handler.H(85): ActionHandler::targetted 1 1 2 89 4 test006/Handler.H(89): ActionHandler::init 1 1 3 94 6 test006/Handler.H(94): ActionHandler::takeCharge 1 1 2 101 4 test006/Handler.H(101): ActionHandler::abort 1 1 1 117 4 test006/Handler.H(117): MotionHandler::initializeData 1 1 1 122 4 test006/Handler.H(122): MotionHandler::updateData 1 1 3 127 5 test006/Handler.H(127): MotionHandler::startMotion 1 1 4 132 6 test006/Handler.H(132): MotionHandler::updateMotion 1 1 4 138 6 test006/Handler.H(138): MotionHandler::endMotion 1 1 0 145 1 test006/Handler.H(145): MotionHandler::drawGhost 1 1 0 146 1 test006/Handler.H(146): MotionHandler::doIt 1 1 1 148 4 test006/Handler.H(148): MotionHandler::MotionHandler 1 1 1 155 1 test006/Handler.H(155): MotionHandler::isInitialEvent 1 1 1 156 1 test006/Handler.H(156): MotionHandler::isOkInitialTarget 1 1 1 157 1 test006/Handler.H(157): MotionHandler::isOkFinalTarget 1 1 3 174 6 test006/Handler.H(174): ArcHandler::indicateInitialTarget 1 1 1 180 4 test006/Handler.H(180): ArcHandler::indicateNoTarget 1 1 1 184 4 test006/Handler.H(184): ArcHandler::indicateFinalTarget 1 1 1 188 3 test006/Handler.H(188): ArcHandler::indicatePreviousCursor 4 4 6 192 15 test006/Handler.H(192): ArcHandler::drawGhost 1 1 1 208 4 test006/Handler.H(208): ArcHandler::isInitialEvent 2 2 2 213 4 test006/Handler.H(213): ArcHandler::isOkInitialTarget 2 2 2 217 4 test006/Handler.H(217): ArcHandler::isOkFinalTarget 1 1 2 227 5 test006/Handler.H(227): ArcHandler::ArcHandler 1 1 1 232 4 test006/Handler.H(232): ArcHandler::~ArcHandler 1 1 6 250 10 test006/Handler.H(250): ArcMaker::initializeData 2 2 6 260 10 test006/Handler.H(260): ArcMaker::startMotion 10 10 23 271 37 test006/Handler.H(271): ArcMaker::updateMotion 4 4 6 309 11 test006/Handler.H(309): ArcMaker::endMotion 1 1 4 321 10 test006/Handler.H(321): ArcMaker::doIt 2 2 1 332 4 test006/Handler.H(332): ArcMaker::isOkInitialTarget 1 1 1 336 4 test006/Handler.H(336): ArcMaker::isOkFinalTarget 1 1 1 342 4 test006/Handler.H(342): ArcMaker::ArcMaker 2 2 1 356 4 test006/Handler.H(356): ArcChanger::isOkInitialTarget 2 2 1 360 4 test006/Handler.H(360): ArcChanger::isOkFinalTarget 1 1 8 365 12 test006/Handler.H(365): ArcChanger::initializeData 2 2 6 378 12 test006/Handler.H(378): ArcChanger::startMotion 6 6 18 391 30 test006/Handler.H(391): ArcChanger::updateMotion 3 3 6 422 11 test006/Handler.H(422): ArcChanger::endMotion 1 1 1 436 4 test006/Handler.H(436): ArcChanger::ArcChanger 2 2 2 451 8 test006/Handler.H(451): NodeMaker::drawGhost 1 1 1 459 4 test006/Handler.H(459): NodeMaker::isInitialEvent 2 2 2 464 4 test006/Handler.H(464): NodeMaker::isOkInitialTarget 1 1 2 469 5 test006/Handler.H(469): NodeMaker::initializeData 1 1 2 474 5 test006/Handler.H(474): NodeMaker::updateData 1 1 1 482 4 test006/Handler.H(482): NodeMaker::NodeMaker 1 1 1 515 3 test006/Handler.H(515): Selector::deselect 2 2 6 519 10 test006/Handler.H(519): Selector::updateData 2 2 1 530 5 test006/Handler.H(530): Selector::isInitialEvent 1 1 1 536 5 test006/Handler.H(536): Selector::isOkInitialTarget 1 1 4 543 7 test006/Handler.H(543): Selector::Selector 1 1 3 570 10 test006/Handler.H(570): SweepSelector::updateData 2 2 7 581 13 test006/Handler.H(581): SweepSelector::startMotion 2 2 5 595 7 test006/Handler.H(595): SweepSelector::updateMotion 2 2 7 603 10 test006/Handler.H(603): SweepSelector::endMotion 2 2 2 616 8 test006/Handler.H(616): SweepSelector::drawGhost 1 1 1 625 4 test006/Handler.H(625): SweepSelector::isInitialEvent 1 1 1 630 4 test006/Handler.H(630): SweepSelector::isOkInitialTarget 1 1 1 636 4 test006/Handler.H(636): SweepSelector::SweepSelector 1 1 1 658 4 test006/Handler.H(658): SubgraphSelector::isInitialEvent 2 2 1 663 4 test006/Handler.H(663): SubgraphSelector::isOkInitialTarget 1 1 1 669 4 test006/Handler.H(669): SubgraphSelector::SubgraphSelector 1 1 0 681 1 test006/Handler.H(681): ItemMover::startMove 1 1 0 682 1 test006/Handler.H(682): ItemMover::updateMove 1 1 0 683 1 test006/Handler.H(683): ItemMover::endMove 2 2 1 685 3 test006/Handler.H(685): ItemMover::isOkInitialTarget 1 1 1 689 4 test006/Handler.H(689): ItemMover::ItemMover 1 1 4 706 6 test006/Handler.H(706): NodeMover::startMove 2 2 8 712 11 test006/Handler.H(712): NodeMover::updateMove 1 1 1 723 3 test006/Handler.H(723): NodeMover::endMove 1 1 1 728 4 test006/Handler.H(728): NodeMover::NodeMover 3 3 1 740 4 test006/Handler.H(740): SelectionMover::isOkInitialTarget 1 1 1 746 4 test006/Handler.H(746): SelectionMover::SelectionMover 1 1 1 758 4 test006/Handler.H(758): MenuHandler::MenuHandler 1 1 1 31 1 test006/NodeArc.H(31): LabelledNode::~LabelledNode 1 1 1 33 1 test006/NodeArc.H(33): LabelledNode::label 1 1 1 37 1 test006/NodeArc.H(37): LabelledNode::shapeType 1 1 1 39 1 test006/NodeArc.H(39): LabelledNode::borderWidth 1 1 1 40 1 test006/NodeArc.H(40): LabelledNode::borderWidth 1 1 1 42 1 test006/NodeArc.H(42): LabelledNode::xeNode 1 1 1 43 1 test006/NodeArc.H(43): LabelledNode::xeNode 2 2 5 107 10 test006/NodeArc.H(107): LabelledArc::arcContains 2 2 7 118 13 test006/NodeArc.H(118): LabelledArc::labelContains 1 1 3 134 6 test006/NodeArc.H(134): LabelledArc::getLabelOrigin 2 2 5 141 10 test006/NodeArc.H(141): LabelledArc::arrowPoints 1 1 6 152 9 test006/NodeArc.H(152): LabelledArc::arrowBoundingBox 4 4 9 162 12 test006/NodeArc.H(162): LabelledArc::arcBoundingBox 2 2 5 179 9 test006/NodeArc.H(179): LabelledArc::drawArrow 1 1 1 200 1 test006/NodeArc.H(200): LabelledArc::owner 1 1 1 202 1 test006/NodeArc.H(202): LabelledArc::getLabel 1 1 1 205 1 test006/NodeArc.H(205): LabelledArc::getLabelColor 1 1 1 208 1 test006/NodeArc.H(208): LabelledArc::getLabelVisible 1 1 3 234 1 test006/NodeArc.H(234): SiblingList::SiblingList 1 1 1 235 1 test006/NodeArc.H(235): SiblingList::~SiblingList 1 1 1 237 1 test006/NodeArc.H(237): SiblingList::count 1 1 1 238 1 test006/NodeArc.H(238): SiblingList::max 3 3 8 244 11 test006/NodeArc.H(244): SiblingList::isSibling 5 5 18 279 28 test006/NodeArc.H(279): RankedArc::arrowPoints 2 2 2 308 3 test006/NodeArc.H(308): RankedArc::computeRank 2 2 2 312 1 test006/NodeArc.H(312): RankedArc::selfish 8 8 28 314 52 test006/NodeArc.H(314): RankedArc::arcContains 4 4 9 369 15 test006/NodeArc.H(369): RankedArc::getLabelOrigin 6 6 27 385 40 test006/NodeArc.H(385): RankedArc::arcBoundingBox 3 3 8 426 14 test006/NodeArc.H(426): RankedArc::drawArc 10 10 27 441 43 test006/NodeArc.H(441): RankedArc::drawRankedArc 6 6 21 485 36 test006/NodeArc.H(485): RankedArc::drawArrow 2 2 3 526 7 test006/NodeArc.H(526): RankedArc::~RankedArc 5 5 10 1 8 test007(1): a 5 5 10 9 8 test007(9): a 5 5 10 17 8 test007(17): a 5 5 10 25 8 test007(25): a 3 3 2 2 7 test008(2): fn1 2 2 2 10 7 test008(10): fn2 1 1 1 13 1 test009(13): function1/class1::amember/class2::bmember 2 2 4 9 10 test009(9): function1/class1::amember 1 1 2 4 20 test009(5): function1 1 1 1 2 5 test011(3): function1 1 1 1 8 5 test011(9): function2 1 1 1 14 5 test011(15): function3 1 1 2 1 6 test013(1): foo 2 2 1 2 6 test014(3): main 1 1 0 2 3 test015(2): Spreadsheetns::ACosFormula::ACosFormula 3 3 3 6 5 test015(6): Spreadsheetns::ACosFormula::ACosFormula 3 3 3 12 6 test015(12): Spreadsheetns::ACosFormula::getResult 1 1 0 21 1 test015(21): foo::bar::bar 1 1 0 25 1 test015(25): foo::foo1::bar::bar 1 1 0 28 2 test015(28): foo::fff 1 1 0 32 1 test015(32): bar::bar 1 1 0 36 1 test015(36): anonymous_namespace::bar::bar 1 1 1 5 1 test016(5): Foo::Foo 1 1 1 10 1 test016(10): Foo::after_potential_parsing_hang 1 1 0 2 4 test018(5): foo 7 7 7 14 24 test021(14): XXX::total_lack_of_modularity 1 1 1 4 3 test023(4): checkGlError 1 1 6 3 11 test024(3): RescaleBlock_5x1555_To_4x1555 1 1 1 49 3 test026(49): Tinsel::TinselEngine::getGameID 1 1 1 53 3 test026(53): Tinsel::TinselEngine::getFeatures 1 1 1 57 3 test026(57): Tinsel::TinselEngine::getLanguage 1 1 1 61 3 test026(61): Tinsel::TinselEngine::getPlatform 1 1 1 65 3 test026(65): Tinsel::TinselEngine::getVersion 1 1 1 107 1 test026(107): TinselMetaEngine::TinselMetaEngine 1 1 1 109 3 test026(109): TinselMetaEngine::getName 1 1 1 113 3 test026(113): TinselMetaEngine::getOriginalCopyright 3 3 1 126 6 test026(126): TinselMetaEngine::hasFeature 2 2 1 133 8 test026(133): Tinsel::TinselEngine::hasFeature 3 3 22 146 30 test026(146): TinselMetaEngine::listSaves 2 2 4 177 7 test026(177): TinselMetaEngine::createInstance 38 38 109 197 155 test026(197): TinselMetaEngine::fallbackDetect 1 1 1 353 1 test026(353): TinselMetaEngine::getMaximumSaveSlot 1 1 5 355 8 test026(355): TinselMetaEngine::removeSaveState 4 4 14 372 42 test026(372): Tinsel::TinselEngine::loadGameState 1 1 6 416 8 test026(416): Tinsel::TinselEngine::saveGameState 1 1 0 7 1 test027(7): Foo::Bar::Bar 1 1 0 8 1 test027(8): Foo::Bar::~Bar 374 378 854 n/a 2375 Total "test018", line 3: too many )'s "test021", line 42: expected closing } for namespace, but got EOF pmccabe-v2.8/tests/testsuite000077500000000000000000000017021400136053700162630ustar00rootroot00000000000000#!/bin/sh PMCCABE=${PMCCABE:-../pmccabe} testlist=' test000 test001 test002 test003 test004 test005 test006/*.H test007 test008 test009 test010 test011 test012 test013 test014 test015 test016 test017 test018 test019 test020 test021 test022 test023 test024 test025 test026 test027' testlist=`echo $testlist` error=0 # record the command and output # save stderr separately to prevent buffering/interlace ordering problems run_pmccabe() { echo "RUN: $PMCCABE $@" $PMCCABE "$@" 2>.tmp cat .tmp rm .tmp } TEST1() { f=$1 shift ( run_pmccabe -X -vt $* run_pmccabe -X -vnt $* run_pmccabe -x -vt $* ) > $f.out if [ -f $f.ref -a -z "$REFERENCE" ] then if ! cmp $f.ref $f.out then error=2 diff $f.ref $f.out fi else echo "Creating new REFERENCE file $f.ref" mv $f.out $f.ref fi } TEST1 testlist $testlist for n in $testlist do TEST1 $n $n done exit $error pmccabe-v2.8/vifn000077500000000000000000000010041400136053700140250ustar00rootroot00000000000000#!/bin/sh if [ $# = 0 ] then echo "Usage: `basename $0` [filename/]functionname [...]" >&2 exit 2 fi exec 3<&0 while [ $# != 0 ] do fname=`dirname "$1"` fn=`basename "$1"` if [ $fname = "." ] then if [ ! -f pmccabe.out ] then pmccabe *.[CcHh] >pmccabe.out fi grep ": $fn$" pmccabe.out else pmccabe $fname | grep ": $fn" fi | sed 's/[()]/ /g' | while read c1 c2 statements l1 nl filename linenumber fnname do vi +$linenumber $filename <&3 done shift done pmccabe-v2.8/vifn.1000066400000000000000000000016661400136053700141770ustar00rootroot00000000000000.TH "vifn" 1 17Jan2021 .SH NAME vifn \- edit by function name rather than file name, uses vi .SH SYNOPSIS .B vifn [filename/]function-name [...] .SH DESCRIPTION .I vifn is a crude script which uses output from .IR pmccabe (1) to allow editing by function name rather than file name. When duplicate function names exist in more than one file, .I vifn cycles through each one. Use .B filename/ when multiple files contain identically-named functions and you know the one you want. .SH BUGS .I vifn uses the file "\fCpmccabe.out\fR" in the current directory, or creates it if not found by running .I pmccabe on files in the current directory. Maybe this isn't really a bug, but it could be better. .P .I vifn does not use the \fC$EDITOR\fR environment variable only because there are editors which misunderstand .IR vi 's .B +line convention for starting the editor positioned at a specific line. .SH AUTHOR Paul Bame .SH "SEE ALSO" .IR pmccabe (1)