diff --git a/.emacs.d/init.el b/.emacs.d/init.el index 6b42561..8ec2dfc 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -57,7 +57,8 @@ (add-to-list 'load-path "~/site-lisp") ;; Choose a cc-mode/c#-mode to use. (More on this below) -(add-to-list 'load-path "~/site-lisp/cc-mode/5.31.3") +(add-to-list 'load-path "~/site-lisp/cc-mode/5.32.3") +(add-to-list 'load-path "~/site-lisp/cc-mode/csharp-only") ;; Also ruby mode (add-to-list 'load-path "c:/ruby/lib") @@ -133,7 +134,7 @@ (progn (require 'color-theme) (require 'color-theme-solarized) - (color-theme-solarized-dark))) + (color-theme-solarized-light))) ;; Modeline format: (display-time-mode -1) @@ -324,7 +325,7 @@ ;; (autoload 'csharp-mode "cc-mode") ;; Here is another one that is not. -(autoload 'csharp-mode "csharp-mode-0.6.0" "Major mode for editing C# code." t) +(autoload 'csharp-mode "csharp-mode-0.8.6" "Major mode for editing C# code." t) (c-add-style "ms-csharp" '((c-basic-offset . 4) diff --git a/site-lisp/cc-mode/5.32.3/ANNOUNCEMENT b/site-lisp/cc-mode/5.32.3/ANNOUNCEMENT new file mode 100644 index 0000000..b0ba9da --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/ANNOUNCEMENT @@ -0,0 +1,21 @@ +Release Announcement +CC Mode Version 5.32 +Alan Mackenzie + +This message announces the availability of a new version of CC Mode, +an Emacs and XEmacs mode for editing C (ANSI and K&R), C++, +Objective-C, Java, CORBA's IDL, Pike and AWK code. + +A list of user visible changes is detailed in the NEWS file and in the +URL listed below. More information, including links to download the +source, are available on the CC Mode web page: + + + +Send email correspondence to + + bug-cc-mode@gnu.org + +For a list of changes please see + + diff --git a/site-lisp/cc-mode/5.32.3/COPYING b/site-lisp/cc-mode/5.32.3/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/site-lisp/cc-mode/5.32.3/ChangeLog b/site-lisp/cc-mode/5.32.3/ChangeLog new file mode 100644 index 0000000..6443651 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/ChangeLog @@ -0,0 +1,14608 @@ +2012-05-05 Alan Mackenzie + + * Patch release 5.32.3 + + * ChangeLog: Update for patch release 5.32.3. + + * cc-defs.el (c-version): Increment to 5.32.3. + + * *.el, cc-mode.texi: Add 2012 to copyright notices. + +2012-04-22 Alan Mackenzie + + Fix erroneous commit. + +2012-04-21 Alan Mackenzie + + Adding a ) can hide the resulting (..) from searches. Fix it. + + * cc-engine (c-append-lower-brace-pair-to-state-cache): Bound the + backward search to the position of the existing (. + +2012-04-15 Alan Mackenzie + + Ensure searching for keywords is case sensitive. + + * cc-cmds.el (c-electric-brace, c-electric-lt-gt) + (c-electric-paren c-beginning-of-defun, c-end-of-defun) + (c-defun-name, c-mark-function c-cpp-define-name) + (c-comment-indent, c-scan-conditionals c-indent-defun) + (c-context-line-break): bind case-fold-search to nil. + + * cc-mode.el (c-font-lock-fontify-region): bind case-fold-search + to nil. + +2012-04-11 Alan Mackenzie + + Make imenu work again for Objective C Mode. + * cc-menus.el (cc-imenu-objc-generic-expression): Correct the + *-index values, these having been disturbed by a previous change + in 2011-08. + +2012-04-08 Alan Mackenzie + + Correct two search limits in c-before-change-check_<>-operators. + * cc-engine.el (c-before-change-check-<>-operators): Make the + correction. + + * cc-mode.texi (c-offsets-alist): Correct a typo. + +2012-03-16 Alan Mackenzie + + Further optimise the handling of large macros. + + * cc-engine.el (c-crosses-statement-barrier-p): Use a limit to a + call of `c-literal-limits'. + (c-determine-+ve-limit): New function. + (c-at-macro-vsemi-p): Move `c-in-literal' to the bottom of an `and'. + (c-guess-basic-syntax): In macros, restrict a search limit to + 2000. In CASE 5B, restrict a search limit to 500. + (c-just-after-func-arglist-p): Obviouly wrong `or' -> `and'. + + * cc-mode.el (c-neutralize-syntax-in-and-mark-CPP): Restrict + macro bounds to +-500 from after-change's BEG END. + +2012-03-08 Alan Mackenzie + + * cc-cmds.el (c-mark-defun): Leave a mark, and extend region when + command is repeated. + +2012-03-02 Alan Mackenzie + + Depessimize the handling of very large macros. + + * cc-engine.el (c-macro-cache, c-macro-cache-start-pos): + (c-macro-cache-syntactic): New variables to implement a one + element macro cache. + (c-invalidate-macro-cache): New function. + (c-beginning-of-macro, c-end-of-macro, c-syntactic-end-of-macro): + Adapt to use the new cache. + (c-state-safe-place): Use better the cache of safe positions. + (c-state-semi-nonlit-pos-cache) + (c-state-semi-nonlit-pos-cache-limit): New variables for... + (c-state-semi-safe-place): New function. Here, in a macro is + "safe". + (c-invalidate-state-cache-1): New stuff for + c-state-semi-safe-place. + (c-in-literal, c-literal-limits, c-determine-limit-get-base): Use + c-state-semi-safe-place. + + * cc-langs.el (c-get-state-before-change-functions): Add + c-invalidate-macro-cache to the C, C++, Obj entries. + +2012-03-01 Alan Mackenzie + + Optimise macro handling with a 1 element cache of beginning and + end. Make the default of c-macro-names-with-semicolon nil. See + 2012-03-02 for details. + +2012-02-29 Alan Mackenzie + + Optimise c-state-safe-place. See 2012-03-02 for details. + +2012-02-19 Alan Mackenzie + + Create .hgignore. Delete the two old .cvsignore's. + +2012-02-19 Alan Mackenzie + + Modify the web pages for recent conversion to Mercurial. + + * hgaccess.php: New file. + * anoncvs.php: Mark old CVS repository as obsolete, change to + past tense. + * index.php: Direct the adventurous to hg rather than cvs. + * links.h: Add new links for hg pages. Move cvs pages to new + "obsolete" section. + +2012-02-19 Alan Mackenzie + + Remove old CVSROOT directory. + +2012-02-13 Alan Mackenzie + + Fix a loop in c-set-fl-decl-start. + * cc-engine.el (c-set-fl-decl-start): Add a check that + c-backward-syntactic-ws actually moves backwards. + +2012-02-12 Alan Mackenzie + + Fix infinite loop with long macros. + * cc-engine.el (c-state-safe-place): Handle macros properly. + +2012-02-07 Alan Mackenzie + + Fix spurious recognition of c-in-knr-argdecl. + + * cc-engine.el (c-in-knr-argdecl): Check for '=' in a putative K&R + region. + +2012-02-07 Alan Mackenzie + + Test for keyword @implementation in a #pragma. This used to + loop. + +2012-02-07 Alan Mackenzie + + * cc-engine.el (c-forward-objc-directive): Prevent looping in + "#pragma mark @implementation". + +2012-01-18 Alan Mackenzie + + Eliminate sluggishness and hangs in fontification of "semicolon + deserts". + + * cc-engine.el (c-state-nonlit-pos-interval): change value 10000 + -> 3000. + (c-state-safe-place): Reformulate so it doesn't stack up an + infinite number of wrong entries in c-state-nonlit-pos-cache. + (c-determine-limit-get-base, c-determine-limit): New functions to + determine backward search limits disregarding literals. + (c-find-decl-spots): Amend commenting. + (c-cheap-inside-bracelist-p): New function which detects "={". + + * cc-fonts.el (c-make-font-lock-BO-decl-search-function): Give a + limit to a backward search. + (c-font-lock-declarations): Fix an occurrence of point being + undefined. Check additionally for point being in a bracelist or + near a macro invocation without a semicolon so as to avoid a + fruitless time consuming search for a declarator. Give a more + precise search limit for declarators using the new + c-determine-limit. + +2012-01-17 Alan Mackenzie + + Correct a test to do with C-y: + * cc-mode.el (c-after-change): Correct a singular-plural + confusion. + +2012-01-13 Alan Mackenzie + + Fix filling for when filladapt mode is enabled. + + * cc-cmds.el (c-fill-paragraph): In the invocation of + c-mask-paragraph, pass in `fill-paragraph' rather than + `fill-region-as-paragraph'. (This is a reversion of a previous + change.) + * cc-mode.el (c-basic-common-init): Make + fill-paragraph-handle-comment buffer local and set it to nil. + +2012-01-11 Alan Mackenzie + + Fix Emacs bug #10463 - put `widen's around the critical spots. + + * cc-engine.el (c-in-literal, c-literal-limits): put a widen + around each invocation of c-state-pp-to-literal. Remove an unused + let variable. + +2012-01-08 Alan Mackenzie + + Optimise font locking in long enum definitions. + + * cc-fonts.el (c-font-lock-declarations): Add an extra arm to a + cond form to handle enums. + * cc-langs.el (c-enums-contain-decls): New lang variable. + * cc-mode.el (c-font-lock-fontify-region): Correct a typo. + +2011-12-24 Alan Mackenzie + + Introduce a mechanism to widen the region used in context font + locking. Use this to protect declarations from losing their + contexts. + + * cc-langs.el (c-before-font-lock-functions): replace + c-set-fl-decl-start with c-change-set-fl-decl-start (Renaming). + (c-before-context-fontification-functions): new defvar, a list of + functions to be run just before context (etc.) font locking. + + * cc-mode.el (c-extend-font-lock-region-for-macros): new, + functionality extracted from c-neutralize-syntax-in-and-mark-CPP. + (c-in-after-change-fontification): new variable. + (c-after-change): Set c-in-after-change-fontification. + (c-set-fl-decl-start): Rejig its interface, so it can be called + from both after-change and context fontifying. + (c-change-set-fl-decl-start, c-context-set-fl-decl-start): new + functions. + (c-standard-font-lock-fontify-region-function): new variable. + (c-font-lock-fontify-region): new function + +2011-12-22 Alan Mackenzie + + Fix unstable fontification inside templates. + + * cc-langs.el (c-before-font-lock-functions): newly created from + the singular version. The (c c++ objc) entry now additionally has + c-set-fl-decl-start. The other languages (apart from AWK) have + that as a single entry. + + * cc-fonts.el (c-font-lock-enclosing-decls): The functionality for + "local" declarations has been extracted to c-set-fl-decl-start. + + * cc-mode.el: (c-common-init, c-after-change): Changes due to + pluralisation of c-before-font-lock-functions. + (c-set-fl-decl-start): New function, extraced from + c-font-lock-enclosing-decls and enhanced. + (top level): Only advise the font-lock change functions when + font-lock-extend-after-change-region-function is not defined. + +2011-12-20 Alan Mackenzie + + Convert some British English spellings to American English. + +2011-12-13 Alan Mackenzie + + Large brace-block initialisation makes CC Mode slow: Fix. Tidy up + and accelerate c-in-literal, etc. by using the c-parse-state + routines. Limit backward searching in c-font-lock-enclosing.decl. + + * cc-engine.el (c-state-pp-to-literal): Return the pp-state and + literal type in addition to the limits. + (c-state-safe-place): New defun, extracted from + c-state-literal-at. + (c-state-literal-at): Use the above new defun. + (c-slow-in-literal, c-fast-in-literal): Removed. + (c-in-literal, c-literal-limits): Amended to use + c-state-pp-to-literal. + + * cc-fonts.el (c-font-lock-enclosing-decls): Check for being in a + literal. Add a limit for backward searching. + + * cc-mode.el (awk-mode): Don't alias c-in-literal to + c-slow-in-literal. + +2011-12-04 Alan Mackenzie + + Add the switch statement to AWK Mode. + + cc-awk (awk-font-lock-keywords): Add "switch", "case", "default" + to the keywords regexp. + + cc-langs (c-label-kwds): Let AWK take the same expression as the + rest. + (c-nonlabel-token-key): Allow string literals for AWK. Refactor + for the other modes. + +2011-10-22 Alan Mackenzie + + Fix bug #9560, sporadic wrong indentation; improve instrumentation of + c-parse-state. + * cc-engine.el (c-append-lower-brace-pair-to-state-cache): correct faulty + logical expression. + + (c-parse-state-state, c-record-parse-state-state) + c-replay-parse-state-state): New defvar/defuns. + (c-debug-parse-state): Use new functions. + +2011-10-12 Alan Mackenzie + + * Patch release 5.32.2 + + * ChangeLog: Update for patch release 5.32.2. + + * cc-defs.el (c-version): Increment to 5.32.2 + +2011-10-11 Alan Mackenzie + + Enhance cc-bytecomp-ignore-obsolete to cope with the missing + function `byte-compile-obsolete' in Emacs >= 24. + + * cc-bytecomp.el (top-level): Add variable cc-bytecomp-push-vars. + Set this and similar variables to nil each time the file is + loaded. + (cc-bytecomp-setup-environment, cc-bytecomp-restore-environment): + Add clauses to setup and restore "pushed" variables. + (cc-bytecomp-push): New macro to "push" a variable onto an + internal stack. + (cc-bytecomp-ignore-obsolete): Add a superfluous check to suppress + a compiler warning + (cc-bytecomp-ignore-obsolete): In Emacs >= 24, use + byte-compile-not-obsolete-funcs to mark a function as obsolete. + +2011-10-07 Alan Mackenzie + + Fontify Java @annotations with c-preprocessor-face-name instead of + c-annotation-face. Protect against a one line change + misfontifying an annotation as a variable declaration. Fix a + "minor" bug. + + (c-annotation-face): Remove + (c-basic-matchers-before): Move the stanza for Java @annotations + here from c-basic-matchers-after. Replace c-annotation-face by + c-preprocessor face name. + (c-font-lock-enclosing-decls): Check that + c-opt-block-decls-with-vars-key is non-nil before using it. + + annotations-1.face: recalculate this file. + +2011-09-15 Alan Mackenzie + + * cc-defs.el (top level): Add a test for the existence of + delete-dups. + * cc-fix.el (top level): (defun delete-dups) when necessary. + +2011-09-13 Alan Mackenzie + + * admin/index.php, admin/release.php: Update version to 5.32.1 + +2011-09-12 Alan Mackenzie + + * ChangeLog: Update for patch release 5.32.1. + + * cc-defs.el (c-version): Increment to 5.32.1 + +2011-09-12 Alan Mackenzie + + * Patch release 5.32.1 + + * cc-defs (c-version): Increment to 5.32.1 + +2011-09-11 Alan Mackenzie + + * cc-defs.el (c-emacs-features): add-local-hook-test: Put a + save-excursion round the buffer manipulation. Error detected by + XEmacs byte compiler. + +2011-09-04 Alan Mackenzie + + * cc-fonts.el: Reapply the change up to revision 5.232. + +2011-09-04 Alan Mackenzie + + * cc-menus.el: Reapply the change up to revision 5.87. + +2011-09-03 Alan Mackenzie + + * All .el files: Correct the copyright and license statements for + release 5.32. + + * cc-defs.el (c-next-single-property-change) + (c-search-backward-char-property): For XEmacs, only use + next/previous-single-char-property-change in versions >= + 2005-01-25 + +2011-09-03 Alan Mackenzie + + Restore to the state of Release_5_32. + +2011-08-28 Alan Mackenzie + + * cc-fonts.el: Fix - typing on a C++ inher-intro or inher-cont + line should preserve the fontification of the inherited class + names. Analogously for namespace names and Java import, extends, + etc. + + * cc-fonts.el (c-make-font-lock-BO-decl-search-function): New + function. + (c-basic-matchers-after - "Fontify the clauses after various + keywords"): Extract the three keyword lists for the 3 erroneous + constructs from the list of four, and use the new function above + in place of an old one. + +2011-08-27 Alan Mackenzie + + * cc-menus.el (cc-imenu-c++-generic-expression): Make it handle + function pointer parameters properly. + +2011-08-24 Alan Mackenzie + + Update the "recent changes" pointer to 5.32. + +2011-08-22 Alan Mackenzie + + * Release 5.32 + + Use `make-local-hook' only when it's needed. + + * cc-defs.el (c-emacs-features): Add 'add-hook-local into c-emacs-features + when make-local-hook is required. + + * cc-mode.el (c-basic-common-init, c-font-lock-init): Test c-emacs-features + for 'add-hook-local. + + * cc-styles.el (c-make-styles-buffer-local): Test c-emacs-features for + 'add-hook-local. + + + * cc-defs.el (c-search-forward-char-property): Streamline by using + c-next-single-property-change. + + * cc-engine.el: Correct typos. + +2011-08-20 Alan Mackenzie + + + Resolve invalid use of a regexp in regexp-opt. + + * cc-fonts.el (c-complex-decl-matchers): Add in special detection for a + java annotation. + + * cc-engine.el (c-forward-decl-or-cast-1): Add in special detection for a + java annotation. + + * cc-langs.el (c-prefix-spec-kwds-re): Remove the special handling for + java. + (c-modifier-kwds): Remove the regexp "@[A-za-z0-9]+". + + * cc-fonts.el: Tidy up font locking of a long CPP construct. + + * cc-fonts.el (c-guess-font-lock-context): eliminate this somewhat pompous + defun. + (c-font-lock-complex-decl-prepare): replace a call to the above with + inline code. + + + Fontify CPP expressions correctly when starting in the middle of such a + construct. Mainly for when jit-lock etc. starts a chunk here. + + * cc-fonts.el (c-font-lock-context): new buffer local variable. + (c-make-font-lock-search-form): new function, extracted from + c-make-font-lock-search-function. + (c-make-font-lock-search-function): Use the above function. + (c-make-font-lock-context-search-function): New function. + (c-cpp-matchers): Enhance the preprocessor expression case with the above + function + (c-font-lock-complex-decl-prepare): Test for being in a CPP form which + takes an expression. + + * cc-langs.el (c-cpp-expr-intro-re): New lang-variable. + +2011-08-16 Alan Mackenzie + + * cc-cmds.el (c-electric-lt-gt): Remove an unused dynamic variable. + + + Reduce the number of compilation warnings: + + * cc-awk.el (c-awk-get-NL-prop-cur-line): Replace `delete-backward-char' by + `delete-char'. + + * cc-cmds.el (c-electric-lt-gt, c-beginning-of-defun): Remove unused + dynamic variables. + + * cc-engine.el (top level): Add a cc-bytecomp-defun and a + cc-bytecomp-defvar. + (c-ssb-lit-begin, c-forward-<>-arglist-recur): + (c-just-after-func-arglist-p, c-looking-at-decl-block): + (c-append-to-state-cache): Remove unused dynamic variables. + + * cc-fonts.el (c-font-lock-enum-tail): Remove an unused dynamic variable. + + * cc-guess.el (top level): Add three cc-bytecomp-defvars. + + * cc-menus.el (cc-imenu-objc-function): Remove an unused dynamic variable. + + * cc-mode.el (top level): Add three cc-bytecomp-defvars. + + * tests/macro-27.cc, tests/macro-27.face, tests/macro-27.res: + Test "macros with semicolons". + +2011-08-15 Alan Mackenzie + + + Adapt recent changes to work with XEmacs. + + * cc-cmds.el (c-where-wrt-brace-construct): Replace a looking-at with + a call to c-looking-at-non-alphnumspace, because XEmacs doesn't have + \s!. + (c-defun-name): Adapt a regexp not to use \_>. + + * cc-defs.el (c-next-single-property-change): new macro. + (c-<-as-paren-syntax, c->-as-paren-syntax: Adapt for use as a simple + value (as well as for category properties). + (c-put-property-fun, c-put-char-property): wrap in eval-and-compile. + (c-use-category): new compile-time constant. + (c-search-forward-char-property): + (c-clear-char-property-with-value-function): + (c-clear-char-property-with-value-function, c-mark-<-as-paren): + (c-mark->-as-paren, c-unmark-<->-as-paren): small changes. + (c-sc-scan-lists-no-category+1+1, c-sc-scan-lists-no-category+1-1): + (c-sc-scan-lists-no-category-1-1, c-sc-scan-lists-no-category-1-1): + (c-sc-scan-lists, c-sc-parse-partial-sexp-no-category): + (c-sc-parse-partial-sexp): new macrofications of scan-lists and + parse-partial-sexp, for use in c-parse-state. + (c-looking-at-non-alphnumspace): new macro. + (c-emacs-features): Introduce new component category-properties. + + * cc-engine.el (several defuns): Replace next-single-property-change by + c-next-single-property-change. + (c-state-cache-non-literal-place): Correct, to avoid the inside of + macros. + (c-state-balance-parens-backwards): + (c-append-lower-brace-pair-to-state-cache, c-state-push-any-brace-pair): + (c-append-to-state-cache, c-remove-stale-state-cache): + (c-remove-stale-state-cache-backwards): Replace scan-lists by + c-sc-scan-lists and parse-partial-sexp by c-sc-parse-partial-sexp. + (c-invalidate-state-cache, c-parse-state): small changes. + (c-find-decl-spots): Enhance initialisation of cfd-prop-match to take + account of a possible c-decl-end c-type property on the last token before + the region. + (c-clear-<-pair-props, c-clear->-pair-props): use c-unmark-<->-as-paren. + (c-before-change-check-<>-operators): Search for syntax-table rather than + category property. + + * cc-fonts.el (c-skip-comments-and-strings): Use + c-next-char-propery-change. + (c-cpp-matchers): Use c-unmark-<->-as-paren. + (c-font-lock-invalid-string): Use characterp rather than integerp in + XEmacs, since characters are not integers. + + * cc-mode.el (c-neutralize-syntax-in-and-mark-CPP): Test for category + properties (i.e. GNU Emacs) before deleting them. + (c-before-change): replace next-single-property-change by + c-next-single-property-change. + (c-after-change): Make an Emacs dependent category property related + correction dependent on the existence of category properties. + +2011-07-26 Alan Mackenzie + + * tests/bitfield-2.c, tests/bitfield-2.face, tests/bitfield-2.res: + bitfield-2.c: New file to test awkward fontification of bitfields. + + + Fontify bitfield declarations properly. + + * cc-langs.el (c-has-bitfields): New lang variable. + (c-symbol-chars): Now exported as a lang variable. + (c-not-primitive-type-keywords): New lang variable. + + * cc-fonts.el (c-font-lock-declarations): Jump over the QT keyword "more" + to prevent "more slots: ...." being spuriously parsed as a bitfield + declaraion. + + * cc-engine.el (c-beginning-of-statement-1): Refactor and enhance to handle + bitfield declarations. + (c-punctuation-in): New function. + (c-forward-decl-or-cast-1): Enhance CASE 3 to handle bitfield + declarations properly. + +2011-07-22 Alan Mackenzie + + + Prevent cc-langs.elc being loaded at run time. + + * cc-mode.el: Remove two autoload forms which loaded cc-langs. + + * cc-langs.el (c-make-init-lang-vars-fun): Don't emit "(require 'cc-langs)". + Quote a form so it will evaluate at (cc-mode's) compilation time. + +2011-07-21 Alan Mackenzie + + + Fontify declarators properly when, e.g., a jit-lock chunk begins inside a + declaration. + + * cc-langs.el (c-symbol-chars): Correct a typo. + + * cc-fonts.el (c-font-lock-enclosing-decls): New function. + (c-complex-decl-matchers): Insert reference to + c-font-lock-enclosing-decls. + + * cc-engine.el (c-backward-single-comment, c-backward-comments): Bind + open-paren-in-column-0-is-defun-start to nil around calls to + (forward-comment -1). + +2011-07-15 Alan Mackenzie + + * cc-mode.texi, cc-styles.el, Makefile, cc-guess.el, cc-langs.el, cc-mode.el: + + * cc-guess.el: Update this and Make it an integral part of CC Mode. + + * cc-langs.el (c-mode-menu): Added "Style..." submenu. + + * cc-styles.el (cc-choose-style-for-mode): New function derived from + `c-basic-common-init'. + + * cc-mode.el (top-level): Require cc-guess. (c-basic-common-init): Use + `cc-choose-style-for-mode'. + + * cc-mode.texi (Guessing the Style): New page. (Styles): Add a short + introduction to above. + + Makefile: Change the position of cc-guess.el. + +2011-06-27 Alan Mackenzie + + * cc-engine.el, tests/templates-19.cc: + cc-engine (c-guess-continued-construct): Correct the handling of + template-args-cont, particularly for when font lock is disabled. Name + this case as "CASE G". + + templates-19.c: Reindent. + +2011-06-15 Alan Mackenzie + + * cc-fonts.el (c-font-lock-declarations): + 1: Whilst checking for declarators, disable + knr checking to speed up for normal files. 2: Refactor, replacing a + sequence of nested if forms by a cond form. + +2011-03-06 Alan Mackenzie + + * cc-engine.el (c-guess-basic-syntax): + Move CASE 19 to a different place, correctly to + process template-args-cont lines. + +2011-02-27 Alan Mackenzie + + * cc-engine.el (c-guess-continued-construct): In three places, replace + `lim' with 'containing-sexp'. + + * cc-engine.el (c-guess-continued-construct): + In three places, replace `paren-state' + with 'containing-sexp'. + + + Fix an infinite loop which happens when a template construct straddles a + jit-lock boundary. + + * cc-engine.el (c-forward-<>-arglist-recur): recast nested `if's as a + `cond' form. + + * cc-fonts.el (c-font-lock-declarations): Remove a harmful narrowing to + region being fontified. + +2011-02-20 Alan Mackenzie + + * cc-engine.el (c-state-literal-at): + Prevent positions in macros finding their way into + c-state-nonlit-pos-cache. Strengthen the comments. + (c-state-dump): New commented out diagnostic routine. + + * cc-cmds.el: Eliminate some infinite loops: + (c-forward-over-illiterls): On encountering a bare '#' step forward over + it. + (c-end-of-statement): Set macro-end correctly at the end of a loop. + +2010-12-28 Nathaniel Flath + + * cc-engine.el (c-guess-continued-construct): + used 'paren-state' instead of 'lim' to fix byte-compile warnings. + +2010-12-12 Alan Mackenzie + + * cc-engine.el (c-forward-type): + Before scanning a template arglist, check that the + current language supports this. + +2010-10-31 Alan Mackenzie + + * cc-cmds.el (c-mask-paragraph): Fix an off-by-1 error. + +2010-10-30 Alan Mackenzie + + * cc-fonts.el (c-font-lock-declarations): + Cache the result of the call to + c-beginning-of-decl-1 inside the internal lambda. This is for speed. + (c-font-lock-enum-tail): New function which fontifies the tail of an enum. + (c-basic-matchers-after): Insert a call to the above new function. + +2010-10-24 Nathaniel Flath + + * cc-engine.el: Patch to fix templates-19.cc test + +2010-10-10 Alan Mackenzie + + * cc-mode.el (c-before-change, c-after-change): + Move the setting of c-new-BEG and + c-new-END from c-before-change to c-after-change. + +2010-10-08 Alan Mackenzie + + + Together with the previous patch, enhance fontification of declarators to + take account of the presence/absence of "typedef". + + * cc-engine.el (c-forward-type): New &optional param "brace-block-too". + (c-forward-decl-or-cast-1): cdr of return value now indicates the + presence of either or both of a "struct"-like keyword and "typedef". + + * cc-fonts.el (c-complex-decl-matchers): Remove the heuristic fontification + of declarators which follow a "}". + + * cc-langs.el (c-typedef-kwds c-typedef-key): New lang variable for + "typedef". + (c-typedef-decl-key): New lang varaible built from c-typedef-decl-kwds. + + * cc-mode.el (c-advise-fl-for-region): Don't restrict to AWK Mode any more. + +2010-10-06 Alan Mackenzie + + * cc-fonts.el (c-font-lock-declarations): + Fontify declarators according to the + presence/absence of "typedef". + + * tests/class-21.face, tests/decls-33.c, tests/decls-33.face, tests/decls-8.cc, tests/decls-8.face, tests/templates-4.face, tests/typedef-1.face: + CC Mode now correctly fontifies declarators according to the + presence/absence of "typedef". Adapt the test files accordingly. + +2010-09-20 Nathaniel Flath + + * cc-engine.el: Moved case 19 out of case 7 + +2010-09-15 Alan Mackenzie + + * cc-engine.el (c-forward-<>-arglist-recur): Fix an infinite recursion. + + * cc-engine.el (c-forward-<>-arglist-recur): Correct the indentation. + +2010-08-06 Alan Mackenzie + + * cc-cmds.el (c-mask-paragraph, c-fill-paragraph): + Fix for the case that a C style + comment has its delimiters alone on their respective lines. + +2010-08-01 Alan Mackenzie + + * cc-align.el, cc-cmds.el, cc-defs.el, cc-engine.el, cc-mode.el, cc-mode.texi, cc-vars.el: + Eliminate some warning messages when Emacs 23 is used to compile them. + +2010-07-31 Alan Mackenzie + + * cc-cmds.el (c-mask-paragraph): Fix auto-fill bug. + +2010-07-21 Alan Mackenzie + + * tests/000tests.el, tests/annotations-1.face, tests/annotations-1.java, tests/annotations-1.res, tests/enum-6.face, tests/enum-6.java, tests/enum-6.res, tests/foreach.face, tests/foreach.java, tests/foreach.res, tests/generics-1.face, tests/generics-1.java, tests/java-varargs.face, tests/java-varargs.java, tests/java-varargs.res, cc-engine.el, cc-fix.el, cc-fonts.el, cc-langs.el, cc-menus.el, cc-mode.el, cc-mode.texi, cc-vars.el, cc-defs.el: + Integrate java-0-1 branch: Enhance Java Mode to handle Java 5.0 (Tiger) + and Java 6 (Mustang). Contributed by Nathanial Flath. + +2010-07-20 Alan Mackenzie + + * cc-defs.el, cc-engine.el, cc-fix.el, cc-fonts.el, cc-langs.el, cc-menus.el, cc-mode.el, cc-mode.texi, cc-vars.el, tests/000tests.el, tests/annotations-1.face, tests/annotations-1.java, tests/annotations-1.res, tests/enum-6.face, tests/enum-6.java, tests/enum-6.res, tests/foreach.face, tests/foreach.java, tests/foreach.res, tests/generics-1.face, tests/generics-1.java, tests/java-varargs.face, tests/java-varargs.java, tests/java-varargs.res: + Integrate java-0-1 branch: Enhance Java Mode to handle Java 5.0 (Tiger) + and Java 6 (Mustang). Contributed by Nathanial Flath. + +2010-07-18 Alan Mackenzie + + * tests/comments-6.c, cc-mode.el: + Enhance `c-file-style' in file/directory local variables. + + * cc-mode.el (c-count-cfss): New function. + (c-before-hack-hook): Call `c-set-style' differently according to whether + c-file-style was set in file or directory local variables. + + tests/comments-6.c. Enter Emacs-24 as a version in which to ignore this + test. + +2010-07-13 Nathaniel Flath + + * cc-mode.texi: Fixed chaotic braces in 'Java Symbols'. + +2010-06-30 Nathaniel Flath + + * cc-mode.texi: Added more detail on new syntactic constructs + +2010-06-20 Alan Mackenzie + + + Fix an indentation bug with templates. + + * cc-mode.el (c-common-init): Initialise c-new-BEG/END. + (c-neutralize-syntax-in-and-mark-CPP): c-new-BEG/END: Take account of + existing values. + + * cc-engine.el (c-clear-<-pair-props-if-match-after) + (c-clear->-pair-props-if-match-before): now return t when they've cleared + properties, nil otherwise. + (c-before-change-check-<>-operators): Set c-new-beg/end correctly by + taking account of the existing value. + + * cc-defs.el (c-clear-char-property-with-value-function): Fix this + to clear the property rather than overwriting it with nil. + + * cc-mode.el (c-before-hack-hook): + When the mode is set in file local variables, set it + first. + +2010-05-28 Alan Mackenzie + + * cc-engine.el, cc-langs.el, cc-mode.texi, cc-vars.el, cc-cmds.el: + Amend the handling of c-beginning/end-of-defun in nested declaration + scopes. + + * cc-vars.el (c-defun-tactic): Move here from cc-langs.el. Change it to a + defcustom. + + * cc-mode.texi (Movement Commands): Document `c-defun-tactic'. Document + the new handling of nested scopes for movement by defuns. + + * cc-langs.el (c-defun-tactic): Move this variable to cc-vars.el. + (c-nonlabel-token-2-key): New variable for change in cc-engine.el. + + * cc-engine.el (c-beginning-of-statement-1): Prevent "class foo : bar" + being spuriously recognized as a label. + + * cc-cmds.el (c-narrow-to-most-enclosing-decl-block): Add parameter + `inclusive' (to include enclosing braces in the region). + (c-widen-to-enclosing-decl-scope): New function. + (c-while-widening-to-decl-block): New macro. + (c-beginning-of-defun, c-end-of-defun): Change algorithm to keep going + outward for defun boundaries, and correspondingly change symbol + `respect-enclosure' to `go-outward'. + (c-declaration-limits): Change algorithm to report only the "innermost" + defun's boundaries. + +2010-05-25 Nathaniel Flath + + * cc-mode.texi: + Added descriptions of annotation-top-cont and annotation-var-cont into the manual. + +2010-05-22 Nathaniel Flath + + * cc-fonts.el, cc-mode.el: + Moved annotation highlighting from java-mode to c-basic-matchers-after. + +2010-05-21 Alan Mackenzie + + * cc-engine.el (c-parse-state-get-strategy): Replace parameter `here' with + `here-' and `here-+', which sandwich any pertinent CPP construct. + + (c-remove-stale-state-cache-backwards): Fix a bug which happens when + doing (c-parse-state) in a CPP construct: Exclude any "new" CPP construct + from taking part in the scanning. + +2010-05-21 Nathaniel Flath + + * cc-langs.el, tests/generics-1.face, cc-engine.el: + Fixed problem where Java Generics were not always fontified. + +2010-05-19 Nathaniel Flath + + * cc-langs.el, tests/generics-1.face, tests/generics-1.java, cc-engine.el: + Fixed unit tests for template expressions and declarations. Still a few broken ones in the new unit tests for Java generics. + +2010-05-18 Nathaniel Flath + + * cc-langs.el, tests/annotations-1.face, tests/annotations-1.java, tests/annotations-1.res, cc-engine.el: + Fixed the bugs in annotation highlighting; annotation unit tests are now passing. + + Also reindented c-forward-<>-arglist-recur and made a few changes that fixed some bugs in generic handline, but those unit tests are not entirely passing. + +2010-05-17 Alan Mackenzie + + * tests/annotations-1.face: + file annotations-1.face was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/annotations-1.java: + file annotations-1.java was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/annotations-1.res: + file annotations-1.res was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/enum-6.face: + file enum-6.face was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/enum-6.java: + file enum-6.java was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/enum-6.res: + file enum-6.res was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/foreach.face: + file foreach.face was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/foreach.java: + file foreach.java was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/foreach.res: + file foreach.res was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/generics-1.face: + file generics-1.face was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/generics-1.java: + file generics-1.java was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/java-varargs.face: + file java-varargs.face was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/java-varargs.java: + file java-varargs.java was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + + * tests/java-varargs.res: + file java-varargs.res was added on branch Branch_5_31 on 2010-07-20 20:41:14 +0000 + +2010-05-17 Nathaniel Flath + + * cc-engine.el, cc-fonts.el, cc-langs.el, cc-vars.el, tests/000tests.el, tests/annotations-1.face, tests/annotations-1.java, tests/annotations-1.res, tests/enum-6.face, tests/enum-6.java, tests/enum-6.res, tests/foreach.face, tests/foreach.java, tests/foreach.res, tests/generics-1.face, tests/generics-1.java, tests/java-varargs.face, tests/java-varargs.java, tests/java-varargs.res: + Added unit tests for new Java 1.5 constructs, as well as a few bug and formatting fixes. + + Most of the issues brought up by Alan's CR have been fixed, with the + exception of annotations being font-locked in java-mode. + Additionally, most of the broken tests were fixed, at the cost of the + a few of the new unit tests not passing. + + * tests/annotations-1.face, tests/annotations-1.java, tests/annotations-1.res, tests/enum-6.face, tests/enum-6.java, tests/enum-6.res, tests/foreach.face, tests/foreach.java, tests/foreach.res, tests/generics-1.face, tests/generics-1.java, tests/java-varargs.face, tests/java-varargs.java, tests/java-varargs.res: + New file. + +2010-04-29 Alan Mackenzie + + * cc-mode.el (c-extend-region-for-CPP): + Fix an off-by-one error (EO-macro position). + +2010-04-28 Nathaniel Flath + + * cc-engine.el: + Improved c-forward-annotation to handle annotations with arglists properly. + + * cc-vars.el, cc-engine.el: + Added two syntactic contexts to support annotations in java. + + The first, annotation-top-cont, represents a topmost continuation where the only items preceding the current line are annotations. An example is: + @Test + _ public void testFoo() {} + + The second is annotation-var-cont, representing a statement continuation where the only preceding items are annotations, such as: + class Test { + public static void main() { + @SuppressWarnings + _int i; + } + } + +2010-04-27 Nathaniel Flath + + * cc-engine.el: Fixed indentation. + + * cc-engine.el: + Added support for for:each loops and fixed a few bugs this uncovered in generic highlighting. + +2010-04-26 Alan Mackenzie + + * cc-align.el, cc-awk.el, cc-cmds.el, cc-defs.el, cc-engine.el, cc-fix.el, cc-langs.el, cc-lobotomy.el, cc-menus.el, cc-styles.el, cc-vars.el: + Replace leading spaces by characters throughout the source. + + * cc-awk.el, cc-cmds.el, cc-defs.el, cc-engine.el, cc-fix.el, cc-fonts.el, cc-langs.el, cc-lobotomy.el, cc-menus.el, cc-styles.el, cc-vars.el, cc-align.el: + Replace leading spaces by s, synched with java-0-1-merge-3. + + * cc-awk.el, cc-cmds.el, cc-defs.el, cc-engine.el, cc-fix.el, cc-langs.el, cc-lobotomy.el, cc-menus.el, cc-styles.el, cc-vars.el, cc-align.el: + Replace leading spaces by characters throughout source. + + * cc-mode.texi, cc-mode.el, cc-engine.el: + Merge from Branch_5_31, tag java-0-1-merge-2. + +2010-04-24 Nathaniel Flath + + * cc-engine.el, cc-fonts.el, cc-langs.el: + Added correct fontification for Java generics and varargs. + +2010-03-25 Alan Mackenzie + + * cc-mode.texi (Other Indentation): + State that functions on c-special-indent-hook are + called with no parameters and with point on the current line. + +2010-03-23 Nathaniel Flath + + * cc-fonts.el, cc-mode.el, cc-vars.el: + Renamed java-annotation-face to c-annotation-face and moved it to cc-fonts.el + +2010-03-22 Alan Mackenzie + + * cc-engine.el: *** empty log message *** + + * cc-engine.el (c-remove-stale-state-cache): Fix an off-by-one error. + +2010-03-12 Alan Mackenzie + + * cc-mode.el: *** empty log message *** + + * cc-mode.el: + Guard against the Emacs core spuriously calling before-change-functions + twice in succession. + (c-just-done-before-change): New flag + (c-before-change): Test and set the new flag before executing anything. + (c-after-change): Clear the flag. + +2010-03-11 Alan Mackenzie + + * cc-fonts.el, cc-langs.el, cc-mode.el, tests/inher-5.res, tests/inher-6.res, tests/templates-16.res, tests/templates-5.res, tests/templates-7.res, tests/templates-8.res, cc-cmds.el, cc-defs.el, cc-engine.el: + Merge from BRANCH_5_31, tag java-0-1-merge-1. + +2010-03-01 Alan Mackenzie + + * cc-engine.el: *** empty log message *** + + * cc-engine.el (c-remove-stale-state-cache): + Correct the previous patch. + + * cc-engine.el: *** empty log message *** + + * cc-engine.el (c-remove-stale-state-cache): + Take account of when `good-pos' is in the same + macro as `here'. + + * cc-engine.el, cc-mode.el: *** empty log message *** + + + + * cc-mode.el (c-common-init): In the funcall, replace the erroneous `beg', + `end' with (point-min), (point-max). + (c-after-change): After (e.g.) C-y, remove the 'syntax-table text props + that Emacs has converted from 'category text props. + + * cc-engine.el (c-clear-<-pair-props, c-clear->-pair-props): Clear the + 'category text property, not the 'syntax-table one. + +2010-02-19 Nathaniel Flath + + * cc-engine.el, cc-fonts.el, cc-langs.el, cc-mode.el, cc-vars.el: + Removed trailing whitespace from cc-vars and cc-engine, and fixed typo (xJava -> Java) + +2010-02-04 Alan Mackenzie + + * cc-engine.el, cc-mode.el: *** empty log message *** + + + + * cc-mode.el (c-common-init): Use c-get-state-before-change-functions in + place of c-get-state-before-change-function. Update some comments about + this. + + * cc-engine.el: Update some comments about + c-get-state-before-change-function. + + * cc-cmds.el, cc-defs.el, cc-engine.el, cc-langs.el, cc-mode.el: + + *** empty log message *** + + + Change strategy for marking < and > as template delimiters: mark them + strictly in matching pairs. + + * cc-mode.el (c-before-change): Use c-get-state-before-change-functions. + + * cc-langs.el (c-no-parens-syntax-table): New syntax table, used for + searching syntactically for matching s. + (c-get-state-before-change-functions): New language variable (note the + plural) which supersedes c-get-state-before-change-function. + + * cc-engine.el (c-clear-<-pair-props, c-clear->-pair-props) + (c-clear-<>-pair-props, c-clear-<-pair-props-if-match-after) + (c-clear->-pair-props-if-match-before) + (c-before-change-check-<>-operators): new functions. + (c-after-change-check-<>-operators): Use macro c-unmark-<->-as-paren. + + * cc-defs.el (c-search-backward-char-property): New macro. + + * cc-cmds.el (c-electric-lt-gt): Do not set text properties on < and > any + more. (These will be handled by font locking.) + +2010-01-25 Nathaniel Flath + + * cc-mode.el, cc-vars.el: Highlighting for Java annotation usage + +2010-01-21 Alan Mackenzie + + * cc-engine.el: *** empty log message *** + + * cc-engine.el: + Fix a situation where deletion of a cpp construct throws an error. + (c-invalidate-state-cache): Before invoking + c-with-all-but-one-cpps-commented-out, check that the special cpp + construct is still in the buffer. + (c-parse-state): Record the special cpp with markers, not numbers. + + * cc-defs.el: *** empty log message *** + + * cc-defs.el: + typing '#' in an empty C buffer throws "args out of range". + (c-set-cpp-delimiters, c-clear-cpp-delimiters): Check for EOB playing the + role of delimiter. + +2010-01-19 Nathaniel Flath + + * cc-langs.el: Highlight annotations as types + + * cc-mode.el, cc-langs.el: highlighting of @interface in java-mode + +2010-01-06 Nathaniel Flath + + * cc-menus.el: + Fixed issue with cc-imenu-java-generic-expression not handling array arguments properly + +2009-12-31 Nathaniel Flath + + * cc-langs.el: + Fix for enum indentation in Java. Aligns all enum options on the same column. + + * cc-langs.el: Added proper highlighting for java enums + +2009-12-10 Alan Mackenzie + + * tests/templates-19.cc, tests/templates-19.res: + Test template use in statements when the templates span line breaks. + + * tests/inher-5.res, tests/inher-6.res, tests/templates-16.res, tests/templates-5.res, tests/templates-7.res, tests/templates-8.res: + Amend for the second anchor point just added to template-args-cont. + + + Handle templates continued over line breaks in statements. Refactor + c-syntactic-skip-backward. Make text property `category' rear + non-sticky. + + * cc-mode.el (c-basic-common-init): make text property `category' rear + non-sticky. + + * cc-engine.el (c-ssb-lit-begin): New defsubst, extracted from .... + (c-syntactic-skip-backward): Refactor, extracting the above. + (c-guess-basic-syntax CASEs 5D.3, 5L): Add extra anchor point; + (c-guess-basic-syntax CASE 19): New CASE to handle template + construct continued over line boundary. + (c-guess-basic-syntax CASE 7): don't trigger on '<'. + +2009-12-03 Alan Mackenzie + + Enhance `c-parse-state' to run efficiently in "brace desserts". + cc-mode.el (c-basic-common-init): Call c-state-cache-init. + (c-neutralize-syntax-in-and-mark-CPP): Renamed from + c-extend-and-neutralize-syntax-in-CPP. Mark each CPP construct by + placing `category' properties value 'c-cpp-delimiter at its + boundaries. + + * cc-langs.el (c-before-font-lock-function): + c-extend-and-neutralize-syntax-in-CPP has been renamed + c-neutralize-syntax-in-and-mark-CPP. + + * cc-fonts.el (c-cpp-matchers): Mark template brackets with + `category' properties now, not `syntax-table' ones. + + * cc-engine.el (c-syntactic-end-of-macro): A new enhanced (but + slower) version of c-end-of-macro that won't land inside a literal + or on another awkward character. + (c-state-cache-too-far, c-state-cache-start) + (c-state-nonlit-pos-interval, c-state-nonlit-pos-cache) + (c-state-nonlit-pos-cache-limit, c-state-point-min) + (c-state-point-min-lit-type, c-state-point-min-lit-start) + (c-state-min-scan-pos, c-state-brace-pair-desert) + (c-state-old-cpp-beg, c-state-old-cpp-end): New constants and + buffer local variables. + (c-state-literal-at, c-state-lit-beg) + (c-state-cache-non-literal-place, c-state-get-min-scan-pos) + (c-state-mark-point-min-literal, c-state-cache-top-lparen) + (c-state-cache-top-paren, c-state-cache-after-top-paren) + (c-get-cache-scan-pos, c-get-fallback-scan-pos) + (c-state-balance-parens-backwards, c-parse-state-get-strategy) + (c-renarrow-state-cache) + (c-append-lower-brace-pair-to-state-cache) + (c-state-push-any-brace-pair, c-append-to-state-cache) + (c-remove-stale-state-cache) + (c-remove-stale-state-cache-backwards, c-state-cache-init) + (c-invalidate-state-cache-1, c-parse-state-1) + (c-invalidate-state-cache): New defuns/defmacros/defsubsts. + (c-parse-state): Enhanced and refactored. + (c-debug-parse-state): Amended to deal with all the new + variables. + + * cc-defs.el (c-<-as-paren-syntax, c-mark-<-as-paren) + (c->-as-paren-syntax, c-mark->-as-paren, c-unmark-<->-as-paren): + modify to use category text properties rather than syntax-table + ones. + (c-suppress-<->-as-parens, c-restore-<->-as-parens): new defsubsts + to switch off/on the syntactic paren property of C++ template + delimiters using the category property. + (c-with-<->-as-parens-suppressed): Macro to invoke code with + template delims suppressed. + (c-cpp-delimiter, c-set-cpp-delimiters, c-clear-cpp-delimiters): + New constant/macros which apply category properties to the start + and end of preprocessor constructs. + (c-comment-out-cpps, c-uncomment-out-cpps): defsubsts which + "comment out" the syntactic value of characters in preprocessor + constructs. + (c-with-cpps-commented-out) + (c-with-all-but-one-cpps-commented-out): Macros to invoke code + with characters in all or all but one preprocessor constructs + "commented out". + +2009-11-23 Nathaniel Flath + + * cc-menus.el: + Updating cc-imenu-java-generic-expression in order to match Java1.6 methods with generics and annotations. + +2009-09-25 Alan Mackenzie + + * cc-langs.el (c-nonlabel-token-key): Allow quoted character constants (as + case labels). + + * cc-engine.el (c-beginning-of-statement-1): Correct buggy bracketing. + +2009-09-24 Alan Mackenzie + + * cc-cmds.el (c-scan-conditionals): + A new function like c-forward-conditionals, but it + doesn't move point and doesn't set the mark. + (c-up-conditional, c-up-conditional-with-else, c-down-conditional) + (c-down-conditional-with-else, c-backward-conditional) + (c-forward-conditional): Refactor to use c-scan-conditionals. + + * cc-bytecomp.el (cc-bytecomp-ignore-obsolete): + In Emacs 23, byte-compile-warnings isn't + always a list any more. Use new function byte-compile-disable-warning + here. + +2009-08-26 Alan Mackenzie + + * admin/release.php: + Update and clarify the current status of the 5.31.n releases. + + * cc-defs.el (c-version): + increment the version number to 5.31.8.prerelease. + +2009-07-24 Alan Mackenzie + + * cc-mode.el, cc-mode.texi: + Whilst initialising a mode, make any explicit setting of a variable take + precedence over one done via c-file-style/c-file-offsets. + + * cc-mode.el (c-before-hack-hook, c-postprocess-file-styles): give + c-set-style a DONT-OVERRIDE parameter of t in each function. + + * cc-mode.texi (Config Basics, File Styles): Amend documentation. + +2009-06-29 Alan Mackenzie + + * cc-cmds.el (c-mask-paragraph): + Remove a spurious correction between the visible + width of TABs and their number of bytes, so that point is undisturbed + after typing a space, when there are tabs just before "*/". + +2009-06-10 Alan Mackenzie + + Introduce "font lock contexts", to enable (in particular) jit-lock to fontify + correctly when starting in the middle of a construct. Implement this for CPP + expressions. + + * cc-langs.el (c-cpp-expr-intro-re): New variable. + + * cc-fonts.el (c-guess-font-lock-context): New function. + (c-font-lock-context): New buffer local variable. + (c-make-font-lock-search-form): New function, extracted from + c-make-font-lock-search-function. + (c-make-font-lock-search-function): Use the above function. + (c-make-font-lock-context-search-function): New function. + (c-cpp-matchers): Enhance the preprocessor expression case as above. + (c-font-lock-complex-decl-prepare): Call c-guess-font-lock-context. + +2009-05-21 Alan Mackenzie + + + * cc-langs.el (c-before-font-lock-function): Change the name of an entry + to c-extend-and-neutralize-syntax-in-CPP. + + * cc-mode.el (c-basic-common-init): Set + font-lock-extend-after-change-region-function to + c-extend-after-change-region for Emacs 22 and later. + (c-before-hack-hook): Correct "hack-local-variables-alist" to + "file-local-variables-alist". + (c-extend-and-neutralize-syntax-in-CPP): Renamed from + c-neutralize-syntax-in-CPP; it now extends the font lock region by + setting c-new-BEG and c-new-END. + (c-font-lock-init): Remove initialization of obsolete variable + font-lock-lines-before. + (c-extend-after-change-region): New function. + (c-advise-fl-for-region): Generated code now extends f-l region for any + CC Mode, not just AWK Mode. + + * cc-fonts.el, cc-engine.el: + Undo the last change, which was ill thought out, apart from the macro + c-search-forward-char-property and some enhancements to comments. + +2009-05-18 Alan Mackenzie + + + * cc-fonts.el (c-font-lock-invalid-cpp-string-matcher): New function. + + (c-basic-matchers-before): New clause to fontify invalid strings in a CPP + construct. + + * cc-engine.el: Update some commenting. + + * cc-defs.el (c-search-forward-char-property): new macro. + +2009-04-30 Alan Mackenzie + + Enhancements for Objective-C: + + * cc-vars.el: (c-objc-method-arg-min-delta-to-bracket, + c-objc-method-arg-unfinished-offset, c-objc-method-parameter-offset): New + variables. + (c-offsets-alist): Use c-lineup-ObjC-method-call-colons in entry for + objc-method-call-cont. + + * cc-langs.el: (c-constant-kwds): New ObjC keywords "YES", "NO", + "NS_DURING", "NS_HANDLER", "NS_ENDHANDLER". + + * cc-align.el: (c-lineup-ObjC-method-call-colons): New function. + + * cc-menus.el: (cc-imenu-objc-function): Remove calls of + imenu-progress-message. + +2009-03-06 Alan Mackenzie + + * cc-defs.el, cc-engine.el, cc-fonts.el, cc-langs.el, cc-mode.texi, cc-vars.el: + Amend to indent and fontify macros "which include their own semicolon" + correctly, using the "virtual semicolon" mechanism. + + * cc-defs.el: Update "virtual semicolon" comments. + + * cc-engine.el (c-crosses-statement-barrier-p): Recoded to scan one line at + at time rather than having \n and \r explicitly in c-stmt-delim-chars + (for some modes, e.g. AWK). + (c-forward-label): Amend for virtual semicolons. + (c-at-macro-vsemi-p, c-macro-vsemi-status-unknown-p): New functions + + * cc-fonts.el (c-font-lock-declarations): Take account of the new C macros. + + * cc-langs.el (c-at-vsemi-p-fn, c-vsemi-status-unknown-p-fn): move to + earlier in the file. + (c-opt-cpp-symbol, c-line-comment-start-regexp): New language variables. + (c-opt-cpp-macro-define): Make into a full language variable. + (c-stmt-delim-chars, c-stmt-delim-chars-with-comma): Special value for + AWK Mode (including \n, \r) removed, no longer needed. + + * cc-mode.el (c-mode, c++-mode, objc-mode): Invoke + c-make-macro-with-semi-re. (Erroneously committed early, in previous + version, 5.259.) + + * cc-vars.el (c-macro-with-semi-re, c-macro-names-with-semicolon): New + variables. + (c-make-macro-with-semi-re): New function + + * cc-mode.texi (Indentation Commands): Mention "macros with semicolons". + (Other Special Indentations): Add an xref to "Macros with ;". + (Customizing Macros): Add stuff about syntax in macros. Add an xref to + "Macros with ;". + (Macros with ;): New page. + +2009-02-21 Alan Mackenzie + + * cc-engine.el, cc-langs.el: + Allow (compile time) expressions in case clauses. + + * tests/switch-16.c, tests/switch-16.res: New file. + + * tests/switch-16.c, tests/switch-16.res: + Test files for "case :". + +2009-02-13 Alan Mackenzie + + * cc-cmds.el (c-defun-name): Widen, so it works on a narrowed region. + +2009-02-08 Alan Mackenzie + + * cc-defs.el (c-emacs-features): + Check the working of beginning/end-of-defun-function + more rigorously before setting argumentative-bod-function. + +2009-01-05 Alan Mackenzie + + * cc-styles.el (c-setup-paragraph-variables): + Ensure paragraph-\(start\|separate\) match + blank lines. For AWK Mode. + +2008-11-07 Alan Mackenzie + + * tests/000tests.el (cc-test-extend-faces): + When two faces aren't distinct, display a + `message' rather than throwing an `error', a barely understood kludge to + allow interactive use of 000tests.el. + + (do-all-tests): reset buffer *cc-test-log* to read/write after calling + `compilation-mode'. + + * tests/top-4.res, tests/statement-15.res, tests/macro-8.res, tests/macro-7.res, tests/macro-3.res, tests/comments-4.res, tests/bracelist-11.res, tests/access-labels-qt-1.res: + Correct the syntactical analysis of subsequent macro continuation lines. + They are now never 'cpp-define-intro'. + +2008-11-03 Alan Mackenzie + + * cc-engine.el (c-forward-label): + Handle the new QT macros Q_SLOTS and Q_SIGNALS. + +2008-10-19 Alan Mackenzie + + * cc-langs.el (c-recognize-<>-arglists): + Enable this, crudely, for java. This will + enable certain constructs with generics to be recognized, although it + won't correctly handle the general use of generics. + +2008-10-17 Alan Mackenzie + + * cc-cmds.el (c-defun-name): + Make it work for "struct foo bar [] = { ...". + +2008-10-13 Alan Mackenzie + + * cc-cmds.el (c-indent-region): + Fix previous patch so that the function works on + one-line macros. + +2008-10-07 Alan Mackenzie + + * cc-mode.el (c-before-hack-hook): + New hook function for new hook (in Emacs 23) + (top level): Use this new hook if it's there, otherwise use + hack-local-variables-hook. + + * cc-mode.el (c-mode-base-map): + Don't bind C-m-[ae] to c-{beginning,end}-of-defun when + the current Emacs version passes a parameter to + {beginning,end}-of-defun-function. + + * cc-engine.el (c-literal-type, c-forward-decl-or-cast-1, c-at-toplevel-p): + Amend doc + strings. + (c-forward-decl-or-cast-1): Add in comments like "CASE 1", "CASE 2", ... + which will later (hopefully) be fleshed out with detailed comments. + + * cc-cmds.el (c-indent-region): + Fix so that indenting a macro followed by blank lines + doesn't backslash the following non-blank line into the macro. + + * cc-align.el (c-lineup-respect-col-0): New function. + + * cc-styles.el (c-style-alist "ellemtel"): + Move arglist-cont-nonempty into + c-hanging-braces-alist. + Change some `mapcar's into `mapc's. + +2008-10-05 Alan Mackenzie + + * cvstest.txt: Initial commision. + + * cvstest.txt: New file. + +2008-10-02 Alan Mackenzie + + * cc-fonts.el (c-font-lock-declarations): For "if (a<0 || b>99)", set + c-restricted-<>-arglists to t, so that the innards aren't treated as a + template bracket enclosure. Also refactor the code here. + +2008-08-12 Alan Mackenzie + + * cc-defs.el (c-emacs-features): + set `argumentative-bod-function' when the Emacs core + passes ARG through to `beginning-of-defun-function'. + +2008-06-28 Alan Mackenzie + + * cc-engine.el (c-beginning-of-statement-1): Improve the doc string. + + * cc-langs.el (c-defun-tactic): New language variable defining BO-defun. + (This was already being used, although not defined.) + + * cc-cmds.el (c-where-wrt-brace-construct): Fix problem with "labels" (e.g. + "private:") at the top level. + +2008-06-19 Alan Mackenzie + + * cc-engine.el (c-guess-basic-syntax CASE 5D.5): + Fix an infinite loop on invalid syntax. + +2008-05-24 Alan Mackenzie + + * cc-mode.el (c-postprocess-file-styles): + Throw an error if c-file-style is set to a + non-string. + (c-neutralize-syntax-in-CPP): Optimize for speed. + +2008-05-22 Alan Mackenzie + + * cc-engine.el (c-guess-basic-syntax, CASE 5B.1): + Fix off-by-1 error, comparing position + of ':' with BOL. + +2008-05-02 Alan Mackenzie + + * cc-mode.texi (Class Symbols): Correct a typo. + + * cc-fonts.el (c-font-lock-declarations): + In "if (Bool *b = f())", fontify "Bool" as a + type. + Also enhance the commenting significantly. + +2008-04-17 Alan Mackenzie + + + * cc-langs.el (c-type-decl-prefix-key): C++ bit: move + "\(const\|throw\|volatile\)\>" nearer the start of the regexp, so that + these keywords aren't wrongly matched as identifiers. + + * cc-fonts.el (c-font-lock-declarators): In (match-beginning 2), "2" -> + "3", corresponding to the change in c-type-decl-prefix-key. + (c-font-lock-maybe-decl-faces): Rearranged the header comments. + + * cc-engine.el (c-find-decl-spots): Rearranged the header comments. + (c-forward-decl-or-cast-1): (i) In (match-beginning 2), "2" -> "3", + corresponding to the change in c-type-decl-prefix-key. (ii) Remove a + check for a semicolon at the end of a function declaration: this causes + C++ constructor declarations to be fontified before the semicolon is + typed. + + * cc-defs.el (c-version): increment the version number to 5.31.6. + +2008-04-15 Alan Mackenzie + + * cc-langs.el (c-modified-constant): new language constant: matches, e.g. + "L'a'". + + * cc-engine.el (c-beginning-of-statement-1): modify to handle "case L'a':". + + * cc-fonts.el (c-font-lock-complex-decl-prepare): + Remove (most) c-type properties also + from the last token _before_ the (font-lock) region, not just those + actually inside it. + + Enhance some of the commenting. + +2008-04-12 Alan Mackenzie + + * admin/anoncvs.php, admin/compat.php, admin/index.php, admin/lists.php, admin/release.php: + Update to current admin state. + +2008-04-10 Alan Mackenzie + + * cc-mode.texi (c-offsets-alist): + Correct typos ("c-set-offsets" -> "c-set-offset", + twice). + +2008-04-06 Alan Mackenzie + + * cc-langs.el (c-before-font-lock-function): + Correct a typo in the doc string. + +2008-04-05 Alan Mackenzie + + + * cc-engine.el, cc-mode.texi: + + + * cc-cmds.el (c-defun-name, c-cpp-define-name): New commands, primarily to + support (X)Emacs's C-x 4 a (`add-change-log-entry-other-window') and + friends. + + * cc-langs.el (c-opt-cpp-macro-define-start): Add a regexp submatch to + match the #define's name. + + * cc-mode.el (c-neutralize-syntax-in-CPP): + Remove a superfluous right parenthesis. + + * cc-mode.texi, cc-engine.el: + + * cc-engine.el (c-in-knr-argdecl): In a suspected K&R region, scan at most + 20 brace/paren pairs. This prevents a drastic slowdown in files (e.g. + Emacs's lisp.h) where there are many consecutive declarations without a + brace block. + + * cc-mode.texi ("Limitations and Known Bugs") Document this restriction. + + * cc-vars.el (c-constant-symbol): + put `save-excursion' round this function. + +2008-03-01 Alan Mackenzie + + * cc-mode.el (c-neutralize-syntax-in-CPP): Fix coding bug. + + * cc-langs.el (c-before-font-lock-function): + Fix bug in doc-string, "c-old-LEN" -> + "c-old-END". + +2008-02-25 Alan Mackenzie + + * cc-mode.el (c-neutralize-syntax-in-CPP): + Fix a bug on typing "#" at EOB. + +2008-02-23 Alan Mackenzie + + Set of changes so that "obtrusive" syntactic elements in a C/C++/ObjC + preprocessor line (e.g. an unbalanced string quote or unmatched paren) don't + interact syntactically with stuff outside the CPP line. + + * cc-awk.el (c-awk-beyond-logical-line, c-awk-old-ByLL): Replace + c-awk-end-of-logical-line and c-awk-old-EoLL to solve an off-by-one bug. + + (c-awk-record-region-clear-NL): Replaces c-awk-before-change, with a bit + of refactoring. + + (c-awk-extend-and-syntax-tablify-region): Takes some of the functionality + of c-awk-advise-fl-for-awk-region, which has been refactored away. + + * cc-defs.el (c-clear-char-property-with-value-function) + (c-clear-char-property-with-value): New function and macro which remove + text-properties `equal' to a supplied value. + + * cc-engine.el: Comment about text properties amended. + + * cc-fonts.el (c-cpp-matchers): Make it put regexp parens around + "error\\|warning". + + * cc-langs.el (c-get-state-before-change-function) + (c-before-font-lock-function, c-anchored-cpp-prefix): New language + variables. + (c-cpp-message-directives): Handle "#warning" in C, C++ and ObjC. + + * cc-mode.el (c-basic-common-init): C and ObjC now use + syntax-table text properties. + (c-common-init): Call language specific before/after-change functions at + mode initialisation. + (c-new-BEG, c-new-END, c-old-BOM, c-old-EOM): New variables. + (c-extend-region-for-CPP, c-neutralize-CPP-line) + (c-neutralize-syntax-in-CPP): New functions. + (c-before-change, c-after-change): Call the new language specific change + functions defined in cc-langs.el. + (c-advise-fl-for-region): New macro. + (awk-mode): Remove AWK specific stuff which has been refactored into + language independent stuff. + +2008-02-02 Alan Mackenzie + + * cc-langs.el (c-specifier-key): + Exclude "template" from this regexp; to anchor the "{" of a + template function correctly on "template", not the following "<". + + * cc-engine.el (c-guess-basic-syntax, CASE 5A.5): + Anchor the "{" of a template function + correctly on "template", not the following "<". + + (c-guess-basic-syntax, CASE 5H): prevent a macro call inside a struct + being recognised as a K&R argument. + + * cc-align.el, cc-awk.el, cc-cmds.el, cc-defs.el, cc-styles.el: + Correct typos, remove WS, rephrase doc-strings/comments a little. + +2008-01-26 Alan Mackenzie + + * cc-defs.el (c-save-buffer-state): + Bind buffer-file-name and buffer-file-truename to + nil, to prevent primitives generating "buffer is read only" messages. + +2008-01-06 Alan Mackenzie + + * cc-vars.el (defcustom-c-stylevar): + New version by Thien-Thi Nguyen which gets rid of + ugly nested backquotes. + + * tests/000tests.el (do-all-tests, do-one-test): + bind 'enable-local-variables so as to get + round GNU Emacs's tighter restrictions on file local variables. + + * cc-awk.el: + awk-escaped-nls*: Use eval-and-compile to avoid compilation error. + +2007-11-02 Alan Mackenzie + + * admin/release.php: Explain about version 5.31.4. + +2007-09-22 Alan Mackenzie + + * admin/links.h: + At an extra link to directory "manual". Rename "Documentation" to + "Manual", clarifying with "(html)" and "(info/PS/DVI)". + +2007-08-25 Alan Mackenzie + + With two "namespace"s on the same line, the next line's syntactic context + (i) gets 2 "innamespace" elements, not 1 defun-block-intro + 1 + innamespace; + (ii) the anchor points are now those of the namespace constructs, not + just the line's indentation. + + * cc-langs.el (c-other-decl-block-key-in-symbols-alist): a new language + variable, an alist with elements like ("namespace" . innamespace). + + * cc-engine.el (c-brace-anchor-point): New function. (c-add-stmt-syntax): + Give accurate anchor points for "namespace", "extern" etc., rather than + BOI. Fix addition of spurious syntactic-symbol 'defun-block-intro, + replacing it with 'innamespace, etc. + +2007-08-01 Alan Mackenzie + + * cc-mode.texi: + "Mailing Lists and Bug Reports": correct "-no-site-file" to + "--no-site-file". + +2007-07-28 Alan Mackenzie + + * cc-langs.el, cc-mode.el: + Move macro call `c-make-emacs-variables-local' from + c-init-language-vars-for to c-make-init-lang-vars-fun, so that it works + for derived modes. + +2007-07-13 Alan Mackenzie + + * Makefile: + Rename target "html" to "html-raw". New "html" fixes up links to the + Emacs/Elisp manuals, pointing them into http://www.gnu.org. + + * 2www.gnu.org.sh: Add a #! line, and a directory parameter. + +2007-07-12 Alan Mackenzie + + * 2www.gnu.org.sh: + The manual has cross references to the Emacs and Elisp manuals. In the + HTML manual, these became broken links. This script directs those links + to the right places in http://www.gnu.org. (It also removes a link to a + manual which doesn't seem to exist online.) + +2007-07-11 Alan Mackenzie + + * tests/access-labels-qt-1.face, tests/class-1.face, tests/class-23.face, tests/class-4.face, tests/class-9.face, tests/interface-1.face, tests/switch-1.face, tests/switch-10.face, tests/switch-12.face, tests/switch-14.face, tests/switch-15.face, tests/switch-3.face, tests/templates-1.face, tests/templates-2.face, tests/templates-3.face, tests/templates-4.face, tests/templates-6.face, tests/union-2.face: + Update 18 files.face to reflect the change in cc-fonts.el + V5.205.2.4/5.209: Keywords which are terminated by a colon (e.g. + default:, public:) and the analogous Objective-C keywords are now + fontified with font-lock-keyword-face. + +2007-07-05 Alan Mackenzie + + * cc-defs.el (c-version): + Increase to 5.31.5. (5.31.4 was the version in Emacs 22.1.) + +2007-07-03 Alan Mackenzie + + * cc-vars.el: + Repair the customization routines which handle alists so that it is + possible to insert entries for those keys which are valid, yet aren't + currently in the alist. + + (c-constant-symbol): New defun which supersedes c-const-symbol. + (c-indent-comment-alist, c-hanging-braces-alist, c-hanging-colons-alist, + c-offsets-alist): Replace c-const-symbol by c-constant-symbol. + + Make the syntactic symbol arglist-cont-nonempty a legitimate key in + c-hanging-braces-alist. + + * cc-cmds (c-brace-newlines): Amend. + + * cc-styles.el (c-style-alist): Extend all standard styles to include the + new element. + + * cc-vars.el (c-hanging-braces-alist): Amend the default value, and the + customization form. + + * cc-mode.el: c-before-change: Replace a "1" with "(point-min)". + + * cc-cmds.el, cc-mode.el: cc-cmds.el (c-electric-slash): + + * cc-mode.el (c-remove-any-local-eval-or-mode-variables): + Replace wrong uses of `kill-...' (which added spurious entries to the + kill ring) by `delete-....'. + + * cc-cmds.el (c-in-function-trailer-p): + Fix this: when a function return type contains + "struct", "union", etc. c-end-of-defun goes too far forward. + + * cc-subword.el (c-capitalize-subword): + More closely mimic the behavior of `capitalize-word'. + Do not move point with a negative argument. Based on tiny change by Paul + Curry. + + * cc-subword.el (c-downcase-subword, c-upcase-subword): + Don't move point if ARG is + negative. Patch by Paul Curry. + + Changes to make `narrow-to-defun' and `mark-defun' work properly + in CC Mode: + + * cc-defs.el (c-beginning-of-defun-1): + + * cc-cmds.el (c-beginning-of-defun, c-end-of-defun): + Bind beginning/end-of-defun-function to nil around calls to + beginning/end-of-defun. + + * cc-langs.el (beginning-of-defun-function, + end-of-defun-function): New c-lang-setvar's. + + * cc-awk.el (c-awk-beginning-of-defun): Add "(or arg + (setq arg 1))" to enable non-interactive call. + + * cc-cmds.el (c-end-of-defun): + Tidy up, to eliminate byte-compiler warning "value + unused" in Emacs 22. + +2007-07-02 Alan Mackenzie + + * cc-cmds.el (c-electric-paren): + Fix space-before-funcall clean-up: only insert space + when on identifier, etc. Patch by David Hansen. + + Fix fontification of labels, and other things with ":". + + * cc-engine.el (c-forward-label): The function now + returns 'goto-target, 'qt-2kwds-colon, 'qt-1kwd-colon, as well as the + former t. + + * cc-fonts.el (c-font-lock-declarations): Interpret the + new return code from c-forward-label, fontifying tokens properly. Add + some general comments throughout the file. + + * cc-vars.el (c-special-indent-hook): Amend doc-string to mention + c-syntactic-indentation. + + * cc-cmds.el (c-forward-to-nth-EOF-}): Fix EOB bug. + + * cc-mode.el (c-make-emacs-variables-local): + Use `mapcar' rather than `mapcan' to + silence compiler warning in GNU Emacs 22. + + Remove stale tokens from `c-found-types' cache. + + * cc-engine.el: (c-partial-ws-p, c-unfind-type, c-trim-found-types): New + functions. + + * cc-mode.el: (c-unfind-enclosing-token, c-unfind-coalesced-tokens, + c-before-change): New functions. (c-maybe-stale-found-type): New + variable. + +2007-06-03 Alan Mackenzie + + * admin/lists.php: Update the address of the cc-mode-help mailing list. + +2007-03-16 Alan Mackenzie + + * cc-mode.texi: + + * cc-styles.el: cc-align.el, cc-styles.el: New line-up function, + c-lineup-gnu-DEFUN-intro-cont, for the DEFUN macro in the Emacs C + sources. Only used in "gnu" style. + + + * cc-align.el: Correct a logistical error in the previous patch. + + * cc-align.el: cc-align.el, cc-styles.el: New line-up function, + c-lineup-gnu-DEFUN-intro-cont, for the DEFUN macro in the Emacs C + sources. Only used in "gnu" style. + + * cc-compat.el, cc-langs.el, cc-menus.el, cc-styles.el, cc-vars.el, cc-align.el, cc-awk.el: + Update the copyright statements, correct some typos, remove silly WS, + improve a few comments. + +2007-02-24 Alan Mackenzie + + * cc-menus.el, cc-styles.el, cc-vars.el, cc-align.el, cc-awk.el, cc-compat.el, cc-langs.el: + Update the copyright statements, correct some typos, remove silly WS, + improve a few comments. + + * cc-mode.texi: Correct lots of typos. + ("Getting Started"): Change a sentence to the conditional. + ("Movement Commands"): Add missing (@code{c-beginning/end-of defun}). + ("Clean-ups"): Add an example for inserting a clean-up into + c-cleanup-list. + + * cc-mode.el (c-basic-comment-init): + Don't set open-paren-in-column-0-is-defun-start + to nil any more. Discussion in emacs-devel showed this was + counter-productive. + + * cc-fonts.el: Added comments to c-font-lock-complex-decl-prepare, + c-font-lock-<>-arglists, c-font-lock-declarations, c-font-lock-c++-new, + explaining that they get called as font-lock "FUNCTION"s; to + c-font-lock-declarations (a c-lang-defconst) explaining that it dumps + these functions to c-matchers-3. + + * cc-engine.el (c-beginning-of-current-token): + For no movement, return NIL, not 0. + (c-in-knr-argdecl): Fixed, so that it doesn't get confused by "[]" when + doing a C-M-a. + + * cc-defs.el (c-go-list-forward, c-go-list-backward): New macros. + + * cc-cmds.el (c-where-wrt-brace-construct): + correct the handline of K&R regions; C-M-a + was fouling up in them. + (c-indent-line): Change the notion of "whitespace" used for , so + that a ^L doesn't get swallowed. + (c-mask-paragraph): Correct the handling of unclosed C-style comments, + (for when auto-fill-mode is enabled). + (c-indent-new-comment-line): With M-j in an empty C-style comment, + correct the final position of point. + +2006-11-12 Alan Mackenzie + + Fix clean-up space-before-funcall so that it doesn't split the identifer + from the parentheses in "#define foo(..)". + + * cc-langs.el (c-opt-cpp-macro-define-id): new language variable. + + * cc-engine.el (c-forward-over-cpp-define-id): new function. + + * cc-cmds.el (c-electric-paren): Amend the function. + +2006-11-08 Alan Mackenzie + + * README: Tell XEmacs users they need the "advice" package. + + * tests/access-labels-qt-1.res, tests/bracelist-11.res, tests/comments-4.res, tests/macro-3.res, tests/macro-7.res, tests/macro-8.res, tests/statement-15.res, tests/top-4.res: + Correct the syntactical analysis of subsequent macro continuation lines. + They are now never 'cpp-define-intro'. + + * tests/macro-23.c, tests/macro-23.res: New file. + + * tests/macro-23.c, tests/macro-23.res: + New test case for plain statements as the continuation lines of a macro. + + * tests/macro-27.c, tests/macro-27.res: + A new test case for a wierd mixture of invalid syntax with CPP, labels, + and an escaped newline. + + * tests/macro-27.c, tests/macro-27.res: New file. + + * cc-engine.el: + (i) (c-guess-basic-syntax, case 5N): Check the format of c-state-cache is + valid for an optimisation before using it. + (ii) (c-guess-basic-syntax): New case 5Q "we are at a statement within a + macro". Other changes so that only the first continuation line in a + macro gets the symbol `cpp-define-intro', the others get `statement', or + whatever. + + * cc-mode.texi ("Limitations and Known Bugs"): + Document problems with eval-after-load + and a workaround. + +2006-07-20 Alan Mackenzie + + Introduce macro c-lang-setvar (sister to c-lang-defvar) to set standard + Emacs variables (like comment-start) to language dependent values, yet + without spuriously "defvar"ing them. + + * cc-langs.el (c-emacs-variable-inits): new variable. + (c-lang-setvar): new macro. + (c-make-init-lang-vars-fun): Use the initialization forms in + c-emacs-variable-inits in addition to those in c-lang-variable-inits. + (comment-start, comment-end, comment-start-skip): Change these from + c-lang-defvar's to c-lang-setvar's + + * cc-mode.el (c-make-emacs-variables-local): new macro, which calls + make-local-variable on the elements of c-emacs-variable-inits. + (c-init-language-vars-for): Call this macro. + +2006-07-19 Alan Mackenzie + + * cc-cmds.el, cc-mode.texi: + + * cc-mode.texi ("Filling and Breaking"): Amend the doc for + c-context-line-break. + + * cc-mode.texi, cc-cmds.el: + + * cc-cmds.el (c-context-line-break): When invoked within a string, preserve + whitespace. Add a backslash only when also in a macro. + + * cc-mode.texi ("Filling and Breaking"): Amend the doc for + c-context-line-breaak. + +2006-07-10 Alan Mackenzie + + * cc-defs.el: cc-defs.el. Correct typos. + + + * cc-awk.el, cc-fonts.el: Move awk-font-lock-keywords from cc-fonts.el back + to cc-awk.el to eradicate an eval-after-load, at the request of RMS. + +2006-07-06 Alan Mackenzie + + * cc-cmds.el (c-context-line-break): don't indent the new line after an + escaped EOL in a string. + +2006-07-03 Alan Mackenzie + + * tests/label-10.c, tests/label-10.res: + label-10.{c,res}: Recognise "foo:" as a label when it directly follows "else", + "do", .... + + * tests/label-10.c, tests/label-10.c~, tests/label-10.res: New file. + + * tests/label-10.c, tests/label-10.c~, tests/label-10.res: + label-10.{c,res}: Recognise "foo:" as a label when it directly follows "else", + "do", .... + + * cc-engine.el (c-forward-label): Recognise "foo:" as a label when it + directly follows "else", "do", .... + +2006-07-01 Alan Mackenzie + + * tests/templates-18.cc, tests/templates-18.res: New file. + + * tests/templates-18.cc, tests/templates-18.res: + templates-18.{cc,res}: tolerate empty angle brackets (as + seen in "explicit specialisations" of templates). + + + * cc-engine.el (c-looking-at-decl-block): tolerate empty angle brackets (as + seen in "explicit specialisations" of templates). + +2006-05-16 Alan Mackenzie + + * admin/anoncvs.php, admin/links.h: + Update the CVS server name to "cc-mode.cvs.sourceforge.net". + + * admin/anoncvs.php, admin/links.h: + Update the CVS server to "cc-mode.cvs.sourceforge.net". + +2006-05-14 Alan Mackenzie + + * admin/anoncvs.php: + Update the CVS host (following a SourceForge upgrade). + +2006-04-29 Alan Mackenzie + + * cc-mode.texi, cc-vars.el: + + * cc-vars.el (c-indentation-style): Mention c-file-style in the doc-string. + + * cc-mode.texi ("Choosing a Style"): Mention c-file-style. + + + * cc-cmds.el (c-mask-paragraph): Fix for C comments, when the comment ender + looks like "=========*/" and is alone on its line. + + + * cc-langs.el, cc-engine.el: Correct the spelling of + c-opt-op-identiTier-prefix, t -> f. Leave an alias for the old name. + + * cc-mode.texi, cc-mode.el: + + * cc-mode.el: Bind C-M-a and C-M-e to c-\(beginning\|end\)-of-defun by + default. + + * cc-mode.texi ("Movement Commands", "Sample .emacs File"): Document this. + + + * cc-align.el, cc-styles.el: New line-up function, + c-lineup-gnu-DEFUN-intro-cont, for the DEFUN macro in the Emacs C + sources. Only used in "gnu" style. + +2006-04-14 Alan Mackenzie + + * admin/release.php: + Correct a link from http://download.sourceforge.net/.... to + http://PRdownloadS.sourceforge.net/... + + * cc-cmds.el (c-electric-slash): + Extend the handling of clean-up comment-close-slash + also to work when there's a comment terminator on the line. + (c-beginning-of-defun, c-end-of-defun): Refactor and optimise these for + large arg - only take account of top level {..}, except for initial and + final adjustments. M-- C-M-[ae] now go to the right defuns when the + starting point is between defuns. They use the four new functions: + (c-in-function-trailer-p, c-where-wrt-brace-construct, + c-backward-to-nth-BOF-{, c-forward-to-nth-EOF-}): new functions to + support c-\(beginning\|end\)-of-defun. + + * cc-engine.el (c-forward-label): + Analyze ":" expressions more rigorously, to exclude + bit-field specifiers from being classed as labels. + (c-forward-label): When analyzing a ":" within a macro, be careful about + using c-forward-syntactic-ws at the macro beginning. + (c-beginning-of-decl-1): Whilst searching for "=" as evidence of a stmt + boundary, check for "operator=", etc. + +2006-04-13 Alan Mackenzie + + * tests/access-labels-qt-1.cc, tests/access-labels-qt-1.face, tests/access-labels-qt-1.res: + Jazz up the QT "slots:" declarations by inserting comments and macros + into them. + + * cc-mode.texi ("Other Commands"): + Move c-set-style (C-c .) here from "Choosing a + Style". + ("Styles"): Add @dfn{style}. + + * Makefile (docs: target): + Add a line to build cc-mode.XEMACS.info.tar.gz. + + * ChangeLog: Correct a typo. + +2006-02-19 Alan Mackenzie + + * cc-defs.el (c-emacs-features): Don't assume point-min==1. + + * NEWS, cc-cmds.el, cc-mode.el, cc-mode.texi: + Rename c-hungry-backspace to c-hungry-delete-backwards, at the request of + RMS. Leave the old name as an alias. + + * cc-awk.el: Correct a typo. + + * admin/changes-531.php: + Rename c-hungry-backspace to c-hungry-delete-backwards, at the request of + RMS. Leave the old name as an alias. + + * cc-mode.texi: + (i) Correct the definition of c-beginning-of-defun, to include the + function header within the defun. + (ii) Two minor amendments from Savannah. + + * cc-fix.el: + In the test for a broken (XEmacs) font-lock-compile-keywords, exclude GNU + Emacs, whose CVS version would now signal an error. + + * cc-fix.el, cc-guess.el, cc-lobotomy.el, cc-styles.el, cc-subword.el, cc-vars.el, cc-align.el, cc-awk.el, cc-bytecomp.el, cc-cmds.el, cc-compat.el, cc-defs.el, cc-engine.el, cc-fonts.el, cc-langs.el, cc-menus.el, cc-mode.el: + (i) Add 2006 to the copyright statement. + (ii) Correct a typo in cc-mode.el. + + * cc-mode.texi: (i) Add 2006 to the copyright. + (ii) Correct two typos. + + * cc-defs.el: Update the version string to "5.31.4". + +2006-02-18 Alan Mackenzie + + * admin/index.php, admin/release.php: Update for release 5.31.3. + + * ChangeLog: Fixed last minute bug in cc-mode.el. + + * cc-mode.el (c-postprocess-file-styles): + bind inhibit-read-only to t, around the call + to c-remove-any-local-eval-or-mode-variables, so that it works on a RO + file. + +2006-02-18 Alan Mackenzie + + * ChangeLog: Update for release 5.31.3. + +2006-02-18 Alan Mackenzie + + * Release 5.31.3 + +2006-02-18 Alan Mackenzie + + * cc-mode.el (c-postprocess-file-styles): bind inhibit-read-only + to t, around the call to + c-remove-any-local-eval-or-mode-variables, so that it works on a + RO file. + +2006-02-17 Alan Mackenzie + + * cc-defs.el (c-emacs-features): Don't assume point-min==1. + + * cc-awk.el: Correct a typo. + +2006-02-15 Alan Mackenzie + + * admin/changes-531.php, cc-mode.texi, NEWS, cc-cmds.el, + cc-mode.el: Rename c-hungry-backspace to + c-hungry-delete-backwards, at the request of RMS. Leave the old + name as an alias. + +2006-02-11 Alan Mackenzie + + * cc-mode.texi: + (i) Correct the definition of c-beginning-of-defun, to include the + function header within the defun. + (ii) Two minor amendments from Savannah. + + * cc-fix.el: In the test for a broken (XEmacs) + font-lock-compile-keywords, exclude GNU Emacs, whose CVS version + would now signal an error. + +2006-02-10 Alan Mackenzie + + * cc-fix.el, cc-guess.el, cc-lobotomy.el, cc-styles.el, + cc-subword.el, cc-vars.el, cc-langs.el, cc-menus.el, cc-mode.el, + cc-fonts.el, cc-bytecomp.el, cc-cmds.el, cc-compat.el, cc-defs.el, + cc-engine.el, cc-awk.el, cc-align.el: + (i) Add 2006 to the copyright statement. + (ii) Correct a typo in cc-mode.el. + + * cc-mode.texi: (i) Add 2006 to the copyright. + (ii) Correct two typos. + +2006-02-09 Alan Mackenzie + + * cc-defs.el: Update the version number to 5.31.3. + +2006-02-02 Alan Mackenzie + + * cc-cmds.el (c-electric-brace): Fix clean-up brace-else-brace + (error due to mbeg, mend being undefined). + +2006-02-01 Alan Mackenzie + + * cc-mode.el: File Local variables: Solve the problem where both + `mode' and c-file-offsets are specified: `mode' will overwrite + c-f-o's settings: + (c-remove-any-local-eval-or-mode-variables): new function. + (c-postprocess-file-styles): call the above new function, within + c-tentative-buffer-change, to splat `mode' and `eval' before the + second hack-local-variables. + +2006-01-31 Alan Mackenzie + + * cc-mode.el: + [Alternative patch to GNU Emacs: cc-engine.el V 1.45] + (c-after-change): Protect the match data with save-match-data. It + was getting corrupted by c-after-change-check-<>-operators. + + * cc-defs.el: [3 Patches from GNU Emacs: savannah V 1.3[678]: + (top level): Check for a buggy font-lock-compile-keywords ONLY in + XEmacs. GNU Emacs 22 now has a check which would throw an error + here. + (c-emacs-features): Use (point-min) and (point) rather than + hard-coded 1, in case the buffer is narrowed. + + * cc-awk.el (c-awk-after-change): Protect the match data with + save-match-data. It was being corrupted when Font Lock was not + enabled. + +2006-01-25 Alan Mackenzie + + * ChangeLog: Update for release 5.31.2. + +2006-01-25 Alan Mackenzie + + * Release 5.31.2 + +2006-01-22 Alan Mackenzie + + * cc-mode.texi (Comment Commands): State that C-u M-; kills any + existing comment. + (Electric Keys): Add a justification for electric indentation. + (Hungry WS Deletion): Clear up the names and complications of the + BACKSPACE and DELETE keys. + +2006-01-18 Alan Mackenzie + + * cc-mode.el (c-basic-common-init): Concatenate the minor mode + indicators directly onto mode-name, removing c-submode-indicators. + Sometimes, c-s-i got separated from the mode name on the mode + line. + + * cc-langs.el (c-mode-menu): Add menu items for Electric Mode and + Subword Mode. + + * cc-engine.el: Concatenate the minor mode indicators directly + onto mode-name, removing c-submode-indicators. Sometimes, c-s-i + got separated from the mode name on the mode line. + (c-beginning-of-statment-1): Distinguish real labels ("case 1:" or + "foo:") from non-labels ("public:"). + (c-forward-objc-directive): Replace c-forward-token-2 with crude + coding; c-f-t-2 doesn't move over a token at EOB. + + * cc-defs.el (c-version): Update version number to 5.31.2 + + * cc-cmds.el (c-update-modeline): Concatenate the minor mode + indicators directly onto mode-name, removing c-submode-indicators. + Sometimes, c-s-i got separated from the mode name on the mode + line. + (c-electric-brace, c-electric-semi&comma, c-electric-colon): + Correct doc-strings: "/ln" -> "/la". + +2006-01-17 Martin Stjernholm + + * cc-langs.el (c-make-init-lang-vars-fun): Improved the error + message when there's an evaluation error to show whether it's + loaded from source or not. + (c-filter-ops): Made it available at runtime too to work when + `c-make-init-lang-vars-fun' needs to evaluate from source. + +2005-12-06 Alan Mackenzie + + * Release 5.31.1 + +2005-12-06 Alan Mackenzie + + * NEWS: Correct the spelling of Masatake YAMATO's name (with + apologies to him). + +2005-12-06 Alan Mackenzie + + * cc-defs.el (c-version): <- 5.31.1 + + * cc-defs.el: Restore the (correct) (c-external-require 'cl). + +2005-11-30 Alan Mackenzie + + * Release 5.31. + +2005-11-30 Alan Mackenzie + + * cc-mode.texi: Spelling and minor typographical changes. + +2005-11-29 Alan Mackenzie + + * cc-align.el, cc-awk.el: Spelling corrections. + + * cc-cmds.el (c-electric-paren): Only call the + `blink-paren-function' for a CLOSE parenthesis. + + * cc-defs.el: Change "(cc-external-require 'cl)" to + "(eval-when-compile (require 'cl))". (The change came from + savannah - I don't understand it.) + + * cc-engine.el: Add an autoload to c-guess-basic-syntax (From + savannah.) + + * cc-langs.el: Add "(cc-external-require 'cl)". + + * cc-mode.el (c-font-lock-init): "Add (font-lock-lines-before + . 1)". + + * cc-subword.el: Add a dummy `c-subword-mode' for Emacsen which + lack `define-minor-mode'. (Currently Emacs <21. We might do this + function properly in the future). + +2005-11-28 Alan Mackenzie + + * cc-cmds.el, cc-defs.el, cc-styles.el, cc-vars.el: New macros + c-sentence-end and c-default-value-sentence end, to cope with + Emacs 22's new function `sentence-end'. + +2005-11-26 Martin Stjernholm + + * cc-cmds.el (c-show-syntactic-information): Solved the compat + issue using `c-put-overlay' and `c-delete-overlay'. + + * cc-defs.el (c-put-overlay, c-delete-overlay): New compat macros + to handle overlays/extents. + +2005-11-25 Alan Mackenzie + + * cc-fix.el: Add definitions of the macros push and pop (for GNU + Emacs 20.4) + + * cc-defs.el: + (i) Load cc-fix.elc for `push' and `pop' (for GNU Emacs 20.4) + + * cc-cmds.el (c-show-syntactic-information): change the + highlighting mechanism so it will work in XEmacs too. + + Remove several unused dynamic bindings. + + * cc-defs.el: Insert c-int-to-char. + + * cc-langs.el (c-nonsymbol-token-char-list): Insert a call to the + new macro c-int-to-char. This solves XEmacs's regarding + characters as different from integers. + +2005-11-25 Martin Stjernholm + + * cc-fonts.el (c-make-syntactic-matcher): New internal helper. + + (c-cpp-matchers, c-basic-matchers-before): Use the `eval' + construct to make the indirect face lookup work in XEmacs. + + (c-cpp-matchers): Append the negation char face to the existing + fontification, so that the cpp face doesn't disappear. Use + `c-make-syntactic-matcher' to avoid negation chars in comments and + strings. + +2005-11-24 Martin Stjernholm + + * cc-fonts.el (c-negation-char-face-name): New variable to map to + `font-lock-negation-char-face' in emacsen where it exists. + +2005-11-23 Alan Mackenzie + + * cc-mode.el: Bind c-subword-mode to C-c C-w. + + * cc-mode.texi: + (i) Document the binding C-c C-w, in "Minor Modes" and in "Subword + Movement". + (ii) Mark c-\(forward\|backward\)-into-nomenclature as superseded + by c-subword-mode. + (iii) "Config Basics": change the troublesome "@itemize @w" to + "@itemize @asis". + (iv) Eliminate the "@defvr {LIST}" construct in "Adding Styles". + Bring descriptions of subsidiary matters into the definition of + the style description by shifting an "@end". + +2005-11-22 Alan Mackenzie + + * cc-mode.texi, cc-subword.el, cc-cmds.el, cc-mode.el: Rename + "c-subword-move-mode" as "c-subword-mode". + + * cc-mode.texi, cc-subword.el: cc-subword.el: In + c-forward-subword-internal, check that the regexp doesn't match a + null string. This can happen, e.g., in Info Mode, where ' has the + syntax of a word constituent. + + cc-mode.texi: + (i) "Subword Movement": Say that subword-move-mode is available in + non-CC Modes. + (ii) "Config Basics": Add a recommendation to beginners to use the + top-level setq mechanism. + (iii) "Config Basics": Deobfuscate the description of top-level + setq's. + + * cc-mode.texi: + (i) Add a description of the various build commands + (e.g. makeinfo), as supplied by Robert Chassell. + (ii) Move description of `comment-region' from "Other Commands" to + "Comment Commands". + (iii) Remove C-c C-y (which used to be bound to + c-toggle-hungry-state). + (iv) Added a @footnote about the change of the binding C-c C-d. + (v) Reinstated the description of `c-toggle-auto-hungry-state'. + + * cc-mode.el: Remove the binding C-c C-y for c-toggle-hungry-state + + * cc-cmds.el: Reinsert c-toggle-auto-hungry-state (but with no + binding). + +2005-11-21 Alan Mackenzie + + * cc-mode.el: Added tty suitable bindings for C-c and C-c + C-. (To the c-hungry- delete functions). + +2005-11-21 Martin Stjernholm + + * cc-mode.el: Added autoload directive for `c-subword-move-mode' + for use in older emacsen. + +2005-11-20 Alan Mackenzie + + * cc-mode.el: + (i) Insert a binding for C-c C-backspace into + c-bind-special-erase-keys which works in TTYs. + (ii) Make sure that when file styles are used, any explicitly + given style variables take priority over those in the style. Do + this by calling `hack-local-variables' a second time. + + * cc-vars.el: Add language specific customization widgets for AWK + to c-doc-comment-style, c-require-final-newline and + c-default-style. Add a defcustom for awk-mode-hook. Give + c-syntactic-element and c-syntactic-context doc-strings by + directly setting their `variable-documentation' propery. This + allows Emacs 22.1 to read these with C-h v. + + * cc-awk.el: Apply a tidy-up patch (from Stefan Monnier). + +2005-11-20 Martin Stjernholm + + * cc-mode.texi: Mention gtkdoc. + + * cc-mode.texi: The concept index also contains the keys. Make + that more obvious so that the keys are found more easily. + + * cc-mode.texi: Updated the Hungry WS Deletion section on the + details about the C-c C- bindings etc. + + * cc-mode.texi: Added a section about the subword minor mode. + + * cc-fonts.el, cc-vars.el (gtkdoc-font-lock-doc-comments, + gtkdoc-font-lock-doc-protection, gtkdoc-font-lock-keywords): + GtkDoc patterns contributed by Masatake YAMATO. + + (c-doc-comment-style): Made GtkDoc default in C mode. + +2005-11-19 Martin Stjernholm + + * cc-mode.el: Fixed key bindings for C-c C- and C-c + C-. + + (c-bind-special-erase-keys): New function for use on + `normal-erase-is-backspace-hook' to bind C-c C- correctly. + + * cc-cmds.el (c-hungry-delete): New function to fix key + behavior in XEmacs according to `delete-forward-p'. + C.f. `c-electric-delete'. + +2005-11-18 Alan Mackenzie + + * cc-mode.texi: DVI stuff: Remove the quotes from "GNU Emacs + Manual" and friends. Complete several cross references with their + fifth parameter (the name of the printed manual). + + "Indentation Commands": Tidy up `c-indent-command', putting the + variables `c-tab-always-indent' and `c-insert-tab-function' inside + its description. Inserted some "printed manual names" into cross + references where they were missing. Move description of + `indent-for-comment' into ... + + "Comment Command": A new @section under "Commands"; it contains + the description of `indent-for-comment'; this was taken out of + "Indentation Commands". Add GNU Emacs's new name `comment-dwim' + for this function. + + "Sample .emacs File": Change "@example" to "@verbatim" so that the + text isn't indented. Reorder the Lisp forms. + +2005-11-08 Alan Mackenzie + + * cc-mode.texi: "Configuration Basics": Add a note that ".emacs" + means "whatever initialization file you fancy". Also, another + note that the mode hooks are good places to put personal + preferences. + + "Performance Issues": Remove the recommendation to put defun + braces at column 0, replacing it with a historical remark. + + "Limitations and Known Bugs": State that C++ templates aren't yet + handled fully. + +2005-11-06 Alan Mackenzie + + * cc-mode.texi: Renamed @chapter "Getting Connected" to "Getting + Started" and @chapter "Config Strategies" to "Config Basics". + + "Getting Started": Added "quick fix" configurations for four of + the most common requests (c-basic-offset, c-set-style, + c-electric-mode, should indent NL). + + "FAQ": Permuted the questions a little. Added "How can I change + the indent level from 4 spaces to 2 spaces?". Added several cross + references. + +2005-11-05 Alan Mackenzie + + * cc-mode.el: Move c-toggle-hungry-state from "C-c C-d" to "C-c C-y". Give + c-hungry-backspace and c-hungry-delete-forward permanent key bindings. + + * cc-mode.texi: Document the new state of affairs: Nodes changed: "Minor + Modes", "Hungry WS Deletion", "Sample .emacs File" + + * cc-mode.texi: + "Style Variables": New @section explaining what style variables are and + how to set them. + "Permanent Customization": Removed this @section, since its contents have + been moved elsewhere. + "c-offsets-alist": New @section + + Removed much commented out material, including @examples in the Line-Up + sections. + + "Config Strategies": (i) Added a summary of style variables; (ii) + Corrected the priority of settings made by "File Local Variables"; + (iii) Clarified and corrected how top-level `setq's interact with + styles; (iv) Added a terse but accurate description of the "user" + style. + "Style Variables": Took over most of the stuff from "Styles", its + parent. Added a @pxref to each item in the list of style variables. + "Built-in Styles": Corrected the description of the "user" style. Other + styles DO NOT inherit from it - they inherit from the factory defaults + in c-fallback-style. + "Adding Styles": Clarification of inheritance from c-fallback-style. + + "Hanging Braces": Replace a tedious flowchart of what CC Mode does, with + a description of how to go about configuring the thing. + "Custom Braces": Move description of c-syntactic-context to near the + top of the node, and note the other three circumstances it gets bound + (together with @xrefs). + "Hanging Semicolons and Commas": Note that c-syntactic-context is bound. + + "Indentation Engine Basics": Clarify first stage of indentation process. + "Syntactic Symbols" (and sub-nodes): Note the syntactic symbols which + don't have and anchor point, or have additional info in a syntactic + element. + + "Customizing Indentation": Stuff about c-offsets-alist has been moved to + its own new @section. + "Line-Up Functions": Add a mention of the calling convention together + with a pointer to "Custom Line-Up". + "Other Indentation": Clarify the whole @section. State that File local + variables take precedence over all else, even settings in hooks. + +2005-11-04 Alan Mackenzie + + * cc-cmds.el (c-mask-paragraph): Remove the "(if t ..." construct + which was experimentally inserted into V 5.314 (2005-08-18) to + minimise the patch size by not changing the indentation level. + +2005-11-03 Alan Mackenzie + + * cc-cmds.el (c-electric-semi&comma): Bind c-syntactic-context for + calls to "criteria functions", for consistency with other calls to + user functions. + +2005-10-31 Alan Mackenzie + + * cc-cmds.el (c-indent-command): expunge use of + `current-prefix-arg', since this might be the prefix arg to a + command which calls c-indent-command as a function. Change the + interactive spec from "p" to "P". + +2005-10-04 Alan Mackenzie + + * cc-mode.texi: + "Minor Modes": Document the command c-toggle-syntactic-indentation. + "Analysis": Formalise the description of + c-show-syntactic-information to a quasi-@defun form. Describe the new + feature of highlighting anchor positions. + Make sure there's a blank line at the top of each node. + + * cc-mode.texi: "Indentation Engine Basics": + (i) Rearrange the paragraphs more logically; + (ii) make @dfn's out of "syntactic symbol", "anchor position" and + "offset(s)". + (iii) Make an @enumeration out of the two-step indentation process. + (iv) Add a paragraph motivating c-syntactic-indentation, complete with a + reference to "Config Strategies". + +2005-10-02 Alan Mackenzie + + * cc-mode.texi: "Custom Line-Up": + (i) Increase the concision of the page. + (ii) Comment out the example. (Maybe this should go into its own + @subsection.) + (iii) Specify precisely the conventions for a line-up function, in + particular, that point may not be moved. + (iv) Add in the suggestion that c-special-indent-hook may sometimes be a + better idea than line-up functions. + There are minor consequential changes on other pages. + +2005-09-18 Alan Mackenzie + + * cc-mode.texi: + (i) Partition the over-large @section "Line-Up Functions". + (ii) Expand the description of c-special-indent-hook. + (iii) Add cross references between "Other Indentation" and "Custom + Line-up", emphasizing that c-special-indent-hook functions and line-up + functions are alternatives. + +2005-09-17 Alan Mackenzie + + * cc-styles.el: Amend the doc-string of c-set-style, in reponse to + a report from Joseph Kiniry that it was difficult + to understand. + +2005-09-11 Martin Stjernholm + + * cc-engine.el (c-on-identifier): Fixed bug when at the first char + of an identifier. + + * cc-engine.el (c-on-identifier): Handle the "operator +" syntax + in C++. + +2005-09-09 Alan Mackenzie + + * cc-mode.texi ("Syntactic Analysis"): Minor amendments. + ("Syntactic Symbols"): Partition this monster into a section with + thirteen subsections, each of which (more or less) illustrates a coherent + grouping of symbols. + Replace the spurious references to substatement-block-intro with + statement-block-intro. + Add @ssindex entries for those symbols missing them. + +2005-09-08 Alan Mackenzie + + * cc-mode.texi: Some general tidying up and clarification. Also: + (Hooks): mention c-special-indent-hook + (FAQ): Commented out the question about M-[ae] going into blocks. + +2005-08-29 Alan Mackenzie + + * cc-mode.texi: + 55 Changes, great and small. Most of them are minor linguistic + improvements, clarifications, adding xrefs, bug fixes, or the like, but + there are also several more notable changes: + (i) "Config Strategies": State which setting takes precedence when + conflicting settings are made (e.g. both in a style and in a hook). + (ii) "Config Strategies": Add a bit about "File Styles". + (iii) "File Styles": Fleshed out this chapter quite a bit. + (iv) "Mode Initialization": Removed this embryonic node (which was far + from complete or useful) and all references to it. + +2005-08-18 Alan Mackenzie + + * cc-cmds.el (c-mask-paragraph): correct, so that auto-fill + doesn't split a c-comment's last word from a hanging "*/" when a + space is typed between them after fill-column. + + cc-defs.el: New macro c-delete-and-extract-region. + +2005-06-24 Alan Mackenzie + + * cc-styles.el (c-set-style, c-setup-paragraph-variables): Abort + the command if we're not in a CC Mode buffer. + +2005-06-13 Alan Mackenzie + + * cc-align.el (c-lineup-C-comments): Correct indentation with + blank comment-prefix, and a blank line as the comment's second + line. + +2005-05-22 Martin Stjernholm + + * cc-fonts.el (c-cpp-matchers, c-basic-matchers-before): + Incorporated the patterns added in the Emacs development branch + for the new Emacs 22 face `font-lock-negation-char-face'. + + * cc-fonts.el (c-invalid-face-name): Use "red1" instead of "red" + since it stands out better in xterms and DOS terminals. + + * cc-engine.el (c-literal-faces): Added + `font-lock-comment-delimiter-face' which is new in Emacs 22. + + * cc-fonts.el (c-font-lock-declarators): Fixed bug where the point + could go past the limit in decoration level 2, thereby causing + errors during interactive fontification. + +2005-05-08 Alan Mackenzie + + * cc-mode.texi: + Add documention for the new electric minor mode and finish that for clean-up + comment-close-slash. Tidy up the structure a bit, make some minor linguistic + improvements. In detail: + + Change "Clean-ups" from being a section of "Custom auto-newlines) to being its + own section, since it documents some stuff which is independent of + auto-nelines. + Change "Auto-newlines" and "Hungry WS Deletion" from being subsections of + "Minor Modes" to their own sections, since they're to important to hide. + Move "Electric Keys" alongside them, since it now bears the same + relationship to "Minor Modes" as "Auto-newlines" and "Hungry WS .." do. + "Indentation Commands": Add a convenience description of standard (X)Emacs + C-j. + "Minor Modes": + (i) Document the new "electric minor mode" with toggle C-c C-l, and the + coupling between it and c-toggle-auto-newline. + (ii) Remove the description of the defunct `c-toggle-auto-hungry-state'. + (iii) Update the description of the modeline flags. + (iv) Recast the node considerably in the process. + "Electric Keys and Keywords": + (i) Add a note that electric minor mode needs to be enabled for (most of) + the stuff here to work. + (ii) Mention the new clean-up comment-close-slash. + (iii) Note the electric actions which don't need electric minor mode to be + enabled. + "Sample .emacs File": Replace c-toggle-auto-hungry-state with + c-toggle-\(auto-newline\|hungry-state\). + "FAQ": Add an entry "How do I stop my code jumping all over the place when I + type?". + +2005-05-07 Alan Mackenzie + + * cc-cmds.el: Correct previous patch to c-toggle-auto-newline. + + * cc-mode.texi: Document the new clean-up `comment-close-slash'. + + * cc-cmds.el: Make C-c C-a (`c-toggle-auto-newline') forcibly + enable c-electric-flag. + +2005-05-06 Alan Mackenzie + + * cc-vars.el, cc-cmds.el: New clean-up `comment-close-slash' on + c-electric-slash: if enabled, typing `/' just after the + comment-prefix of a C-style comment will close that comment. + +2005-05-05 Alan Mackenzie + + * cc-mode.texi: Sync with Lute Kamstra's patch from emacs-devel to + prevent a superfluous cc-mode.ss index file being built with + texi2dvi. + +2005-05-01 Martin Stjernholm + + * cc-fonts.el (c-basic-matchers-before, c-complex-decl-matchers): + Fixed the "not-arrow-prefix" regexp used in Pike. + + * cc-langs.el (c-other-op-syntax-tokens): Only C++ has digraphs. + +2005-04-29 Alan Mackenzie + + * cc-mode.texi: Resolve some CVS conflict markers. + + * cc-mode.texi: Custom Filling and Breaking: State that + c-comment-prefix regexp can be an association list. + +2005-04-11 Martin Stjernholm + + * cc-fonts.el, cc-langs.el, cc-engine.el + (c-cpp-message-directives, c-cpp-include-directives, + c-opt-cpp-macro-define, c-opt-cpp-macro-define-start, + c-cpp-expr-directives): Introduced new language constants to + control cpp syntax in a cleaner way. + + (c-cpp-expr-functions): Renamed from c-cpp-defined-fns. + + (c-cpp-matchers, c-forward-to-cpp-define-body): Use them. + +2005-04-10 Martin Stjernholm + + * cc-mode.el (c-make-inherited-keymap): Fixed cc-bytecomp bug when + the file is evaluated interactively. + + * cc-langs.el, cc-fonts.el (c-string-escaped-newlines, + c-multiline-string-start-char): New language constants and + variables to specify how newlines in string literals work. + + (c-font-lock-invalid-string): Use them. + + * cc-mode.texi: Removed hint that the one-liner-defun cleanup only + would be useful/relevant in AWK mode. + + * cc-cmds.el (c-try-one-liner): Robustness fix if an unbalanced + close brace is entered. Optimization by avoiding going back over + arbitrarily large blocks. Removed hints that this function only + would be relevant/useful in AWK. + + (c-electric-brace): Indent syntactically after the cleanups since + lineup functions might do it differently then. + + * cc-engine.el, cc-langs.el (c-opt-op-identifier-prefix): New + language constant and variable. + + (c-just-after-func-arglist-p, c-after-special-operator-id, + c-search-decl-header-end, c-inside-bracelist-p): Use it. + +2005-02-14 Kevin Ryde : + + * cc-align.el (c-lineup-argcont): Ignore conses for {} pairs from + c-parse-state, to avoid a lisp error (on bad code). + +2005-04-09 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Handle operator + declarations somewhat better in C++. + + * cc-align.el, cc-engine.el (c-after-special-operator-id): New + helper to handle C++ operator identifiers. + + (c-lineup-topmost-intro-cont, c-just-after-func-arglist-p, + c-guess-basic-syntax): Handle C++ operator identifiers in + declarations. + + * cc-langs.el (c-assignment-operators): Added the trigraph version + of ^= too. + + * cc-langs.el (c-assignment-operators): Added the trigraph version + of |= in C++. + +2005-04-08 Alan Mackenzie + + * cc-mode.texi: "Advanced Customizations": Finally remove the + vestiges of this chapter. Resolve three other minor FIXMEs. + +2005-04-03 Martin Stjernholm + + * cc-fonts.el (c-font-lock-declarators): Handle + `c-decl-hangon-kwds' after the identifier name. + + * cc-engine.el (c-guess-basic-syntax): When deciding whether an + arglist is "nonempty", ignore a comment after the open paren if it + isn't followed by a non-comment token on the same line. + + * cc-engine.el (c-guess-basic-syntax): Case 4: Enable heuristics + below the point to cope with classes inside special brace lists in + Pike. + +2005-04-03 Alan Mackenzie + + * cc-mode.texi: Correct a typo in the sourceforge CVS URL. + + * cc-mode.texi: Add a statement that the manual is GPL'd. Add a + pointer to the manual's source at sourceforge. + +2005-04-01 Alan Mackenzie + + * cc-cmds.el: Amend c-point-syntax to handle macros. + +2005-03-29 Martin Stjernholm + + * cc-guess.el (cc-guess-install): + New function to install an already guessed style + in another buffer. + +2005-02-14 Kevin Ryde + + * cc-mode.texi (File Styles): Cross reference emacs file local + variables, correction to grammatical typo. + +2005-03-20 Martin Stjernholm + + * cc-guess.el: Improvement contributed by Masatake YAMATO: + Frequency is now taken into account to make a better guess. + + (cc-guess-region): Inverted the RESET argument to make it more + convenient. The guessed style is also merged into + `c-offsets-alist' right away. + + (cc-guess, cc-guess-view-style): New functions. + +2005-03-19 Martin Stjernholm + + * cc-defs.el (c-tentative-buffer-changes): No longer sets + `inhibit-read-only' - `c-save-buffer-state' should be used anyway + if the change always is undone. + +2005-03-12 Alan Mackenzie + + Implement togglable electricity: + + * cc-defs.el: Enhance c-save-buffer-state's doc-string, saying + when it should be used. + + * cc-engine.el: Add the new buffer-local variable, + c-electric-flag. + + * cc-langs.el: Change the name of c-toggle-auto-state to + c-toggle-auto-newline. + + * cc-mode.el: Rename c-toggle-auto-state to c-toggle-auto-newline. + Remove the binding for c-toggle-auto-hungry-state. Add the + binding C-c C-l for the new c-toggle-electric-state. + + * cc-vars.el: Make c-syntactic-indentation buffer local. + + * cc-cmds.el: Add `c-bytecomp-defun's for + c-\(forward\|backward\)-subword. + (c-update-modeline): Add the new modeline flag `l' for + `c-electric-flag'. Make the auto-newline flag `a' dependent on + `l'. + (c-toggle-auto-state): Rename it to `c-toggle-auto-newline'. Make + the old name an alias of the new name. + (c-toggle-auto-hungry-state): Removed. + (c-toggle-electric-state): New function. + c-electric-\(pound\|brace\|slash\|star\|semi&comma\|colon\|lt-gt\|paren\|continued-statement\): + Adapt these functions to do electric things only when + c-electric-flag is non-nil. + (c-point-syntax, c-brace-newlines, c-try-oneliner): Extract these + new functions from c-electric-brace. + (c-point-syntax): Add a check for "virtual semicolons" in AWK + mode, so that the tentative extra newline doesn't change the + syntax of the following brace. + (c-electric-brace): restructure by extracting the above functions. + Tidy up the coding somewhat. + (c-electric-semi&comma, c-electric-colon, c-electric-paren): + restructure a bit. + + * cc-mode.texi: + "Electric Keys": Amend description of `<' and `>': they are also electric when + they are template brackets. + "Other Commands": Add an entry for the standard Emacs command `comment-region' + which has CC Mode binding C-c C-c. + "Custom Filling and Breaking": Purge the description of + `c-comment-prefix-regexp' of confusing gobbledygook. + +2005-03-02 Alan Mackenzie + + * cc-mode.texi: + "Filling and Breaking": Add a cross reference to "Custom Filling and + Breaking". + Several minor amendments. + +2005-02-01 Alan Mackenzie + + * cc-mode.texi: + Merge the changes made on branch texi-0-1 back to HEAD. + +2005-01-31 Alan Mackenzie + + * cc-mode.texi: + "Overview": Get rid of reference to "AWK" section; + "Sample .emacs FILE": Put key bindings into c-initialization-hook; + Move the c-add-style call from out of the c-mode-hook. + +2004-12-19 Alan Mackenzie + + * cc-mode.texi: + In the GNU/XEmacs conditional things, replace "X" by "XEMACS" for clarity. + Rename the chapter "Indentation Engine" to "Indentation Engine Basics". + "Indentation Commands": Add stuff about macros (taken from the old "Macro + Handling" chapter). + "Other Commands": Move the description of "c-backslash-region" into here. + Rename "Macro Handling" to "Custom Macros", having moved the stuff other than + customization to other chapters. + + * cc-vars.el: Remove the erroneous (doubly inserted) patch from + yesterday. + +2004-12-18 Martin Stjernholm + + * cc-cmds.el (c-show-syntactic-information): Show the anchor + position(s) using faces. Thanks to Masatake YAMATO for the idea. + + * cc-mode.el, cc-cmds.el, cc-defs.el, cc-engine.el + (c-submode-indicators): Changed name from `c-auto-hungry-string' + since it's now used to track another submode. + + (c-update-modeline): Converted to function and extended to check + `c-subword-move-mode'. + + (c-forward-into-nomenclature, c-backward-into-nomenclature): + Converted to compat aliases for `c-forward-subword' and + `c-backward-subword'. + + * cc-subword.el: New functions and minor mode to handle + SillyCapsedStyleIndentifiers, contributed by Masatake YAMATO: + + (c-forward-subword, c-backward-subword, c-mark-subword, + c-kill-subword, c-backward-kill-subword, c-transpose-subwords, + c-capitalize-subword, c-downcase-subword, c-upcase-subword): + Functions corresponding to the standard word handling functions. + + (c-subword-move-mode): Minor mode that replaces all the standard + word handling functions with their subword equivalences. + +2004-12-17 Alan Mackenzie + + * cc-vars.el (c-cleanup-list): Insert a customization entry for + one-liner-defun. + +2004-12-12 Alan Mackenzie + + * cc-defs.el: Give c-tentative-buffer-changes its own name in its + def-edebug-spec. + + * cc-cmds.el (c-electric-brace): Make the one-liner-defun clean-up + work with empty-defun-braces. o-l-d now compacts space before a + comment, if this will make things fit on one line. + +2004-12-05 Alan Mackenzie + + * cc-mode.texi: + "AWK Mode Defuns": Removed this subsection, transferring its contents to + "Movement Commands" + "Movement Commands": Condensed the separate descriptions of + complementary -backward-* and -forward-* commands into joint + descriptions. + +2004-12-04 Alan Mackenzie + + * cc-mode.texi: + "Introduction": Integrated Alan more tightly into CC-Mode. ;-) + "Overview": New chapter describing the structure of the manual. + "Other Commands": Added a description of c-macro-expand. + "Built-in Styles": Added a description of the new "awk" style. + "Custom Braces" and "Hanging Semicolons and Commas": Specify the meaning of + point in action functions, and that is must be preserved. + "Clean-ups": Document the new clean-up one-liner-defun and associated + variable c-max-one-liner-length. + "Customizing Indentation" is now its own chapter rather than being a section + of "Indentation Engine". + "AWK Mode: Removed the entire chapter, moving the two remaining useful + sections to "Font Locking" and "Movement Commands". + Added/Moved lots of index entries. + +2004-11-29 Alan Mackenzie + + * cc-mode.el: Add a fourth parameter `t' to the awk-mode autoload, + so that it is interactive, hence can be found by M-x awk-mode + whilst cc-mode is yet to be loaded. Reported by Glenn Morris + . + +2004-11-28 Alan Mackenzie + + Introduce an "awk" style, mainly for auto-newline and clean-ups. + + * cc-align.el: new function c-snug-1line-defun-close + + * cc-cmds.el: In c-electric-brace, add code for new clean-up + one-liner-defun. + + * cc-styles.el: Add the new "awk" style. + + * cc-vars.el: Add description of one-liner-defun to + c-cleanup-list's doc-string. New user options, + c-max-one-liner-length. In c-default-style, set the default style + for AWK to "awk". + +2004-11-28 Martin Stjernholm + + * cc-mode.el, cc-styles.el (c-run-mode-hooks): New helper macro to + make use of `run-mode-hooks' which has been added in Emacs 21.1. + + (c-mode, c++-mode, objc-mode, java-mode, idl-mode, pike-mode, + awk-mode): Use it. + + (make-local-hook): Suppress warning about obsoleteness which has + been added in Emacs 21.1. + +2004-11-07 Martin Stjernholm + + * cc-engine.el (c-forward-label): Fixed fontification of macros + inside labels. + +2004-11-04 Alan Mackenzie + + * cc-mode.texi: + (i) Some general tidying up, remove @ignore sections, etc. + (ii) Firm up the mechanism for generating @xrefs to the Emacs/Xemacs + manual and the Elisp/Lispref manual. There are now four macros, + @emacsman{}, @lispref{}, @emacsmantitle{}, @lispreftitle{} which + generate the filenames and titles (for the printed versions) of the + manuals pertinent to Emacs or XEmacs, depending on whether the makeinfo + variable `X' is defined or not. The titles were taken from the + @settitle lines in the source files of the four manuals. In the + process, the title "The Emacs Editor" has been amended to "GNU Emacs + Manual". + +2004-10-16 Alan Mackenzie + + * cc-mode.texi: Much general tidying up of the wording. + "Auto-newlines" + (i) Add a note that c-electric-* only do their stuff when last on + line. + (ii) State that a `before' auto-newline is never added if the `{' + etc. is "already on a newline". + (iii) Replace the statement of where auto-newlines go by default (it + was wrong and oversimplified) by a statement that the style system + does the configuration most of the time. + "Custom Auto-newlines" + (i) Make the page what it says it is, removing the stuff which is now + in "Commands". + (ii) Add a @dfn{} for "hang", and "hanging on the left/right". + (iii) + "Hanging Braces" + (i) Insert an @enumerated section describing the algorithm. + (ii) Insert a more robust description of c-hanging-braces-alist. + (iii) + "Hanging Colons" + (i) Update this page to mirror "Hanging Braces". + (ii) State that the default action (if no alist entry) is to add no + newlines. + "Custom Semis and Commas" + (i) Add clarification that criteria functions don't themselves add + newlines. + (ii) State that NLs never get added _before_ a `;' or `,'. + (iii) + "Clean-ups" + (i) Give an actual definition of "Clean-up" for the @dfn{}. ;-) + + Moved the @section "Custom Brace and Colon Hanging" away from "Advanced + Customizations" to underneath "Hanging Braces", removing the spurious + "and Colons" from its name. + Moved the contents of the @section "Customizing Semicolons and Commas" + away from "Advanced Customizations" and inserted them into "Hanging + Semicolons and Commas" (which previously had only a pointer into the + CSaC node). + "Advanced Customization" is now almost content free. + + Add Experimental macros for "Emacs"/"XEmacs" and "Elisp"/"Lispref", in + the hope they might enable a better XEmacs version of the manual. + +2004-10-07 Martin Stjernholm + + * cc-cmds.el, cc-engine.el, cc-align.el + (c-append-backslashes-forward, c-delete-backslashes-forward, + c-find-decl-spots, c-semi&comma-no-newlines-before-nonblanks): + Compensate for return value from `forward-line' when it has moved + but not to a different line due to eob. + +2004-10-01 Martin Stjernholm + + * cc-engine.el (c-looking-at-bos): Obsoleted in favor of + `c-at-statement-start-p' and `c-at-expression-start-p'. + + * cc-defs.el (c-tnt-chng-record-state): Don't signal an error if + the mark isn't set. + + * cc-engine.el (c-guess-basic-syntax): Fixed anchoring in + `objc-method-intro' and `objc-method-args-cont'. + + * cc-engine.el (c-guess-continued-construct, + c-guess-basic-syntax): Use `c-forward-decl-or-cast-1' to more + accurately detect functions inside functions. + +2004-09-30 Alan Mackenzie + + * cc-mode.texi: + Reorder the chapters a bit on the principle "Most basic earliest": + Move "Font locking" with contents to just after "Commands". + Move "Indentation Engine" with contents to just after "Custom Filling and + Breaking". + Move "Custom Filling and Line Breaking" to before "Custom Auto-Newlines". + +2004-09-26 Alan Mackenzie + + * cc-mode.texi: + Add a "Mode Initialization" section (as yet, content free) to + "Configuration Strategies". + Move "Minor Modes" into the "Commands" chapter. Remove the + configuration instructions from its submode "Auto-newlines". Outline + the default configuration for auto-newlines here. + Rename the old "Auto-newline insertion" to "Customizing Auto-newline + Mode" and make it a @chapter in its own right, containing four + sections. The content of this @chapter is yet to be adapted. + Amend the descriptions in "Minor Modes" of the key sequences, using + @table rather than an unbroken textual paragraph. + Amend "Electric Keys", so that there is explicit reference to + "Clean-ups" in the right places. All electric actions are now + collected together in this section. + Condense the description of '*' and '/' in Electric keys. + In "Clean-ups" insert "@tie{}" where a critical space was getting lost + in line wrap. + Tidy up a lot of wording. + Introduce an experimental facility which will build either a GNU Emacs + or an XEmacs specific info file. + +2004-09-26 Martin Stjernholm + + * cc-engine.el (c-at-expression-start-p): New function like + `c-at-statement-start-p' that additionally recognizes commas and + expression parentheses as delimiters. + +2004-09-24 Alan Mackenzie + + * cc-awk.el: Add character classes (e.g. "[:alpha:]") into AWK + Mode's regexps. + +2004-09-19 Alan Mackenzie + + * cc-mode.texi: Move the page "Hungry WS Deletion" into the + "Commands" chapter, and revise this node for (hopefull) increased + clarity. + +2004-09-18 Alan Mackenzie + + * cc-mode.texi: Reduce the length of many node names, (following + suggestion on emacs-devel). Tidy up some of the wording. + +2004-09-17 Alan Mackenzie + + * cc-mode.texi: Added ACM to the list of authors. + Renamed "Other Electric Commands" to "Electric Keys and Keywords" + In "Electric Keys and Keywords", added descriptions of {, }, :, ;, ,,, + and tidied up the wording a bit. + Tidied up the wording and presentation of "Configuration Strategies". + In "Customizing Filling and Line Breaking", expanded the description of + c-comment-prefix-regexp. + +2004-08-20 Alan Mackenzie + + * cc-mode.texi: + Moved the "Commands" chapter to near the start of the file. + Moved "Other Electric Commands" into the "Commands" chapter. + Split "Text Filling and Line Breaking" into the "Filling and Line + Breaking Commands" (a section under "Commands"), and "Customizing Filling + and Line Breaking". + +2004-08-18 Alan Mackenzie + + * cc-mode.texi: Update the master menu for the file. + + * cc-mode.texi: + This change is the first stage in the restructuring of cc-mode.texi. + Added new chapter, "Configuration Strategies", and converted "Hooks" and + "Styles" (together with the latter's sub-nodes) into sections of this new + chapter. + Converted "Syntactic Symbols" and "Customizing Indentation" (together with + the latter's sub-nodes "Interactive C.." and "Permanent C..") into sections of + "Indentation Engine". "Customizing Indentation" has acquired "Line-Up + Functions", "Custom Line-up Functions" and "Other Special Indentations" as + sub-nodes, but has lost "Hooks" and "Styles"). + "Advanced Customization", formerly a sub-node of "Customizing Indentation" + is now a chapter in its own right. It has lost "Custom Line-Up Functions" and + "Other Indentations". + +2004-06-29 Martin Stjernholm + + * cc-engine.el (c-looking-at-inexpr-block): Added flag to avoid + heuristics that doesn't work for unclosed blocks. + + (c-at-statement-start-p): New function. + +2004-06-19 Martin Stjernholm + + * cc-mode.texi: Added an FAQ item about the + open-paren-in-column-zero issue. + +2004-05-25 Martin Stjernholm + + * cc-defs.el, cc-vars.el (c-emacs-features): Moved from cc-vars to + cc-defs for dependency reasons. Fixed the POSIX char class test + to check that it works in `skip-chars-(forward|backward)' too. + + * cc-align.el (c-lineup-arglist): Fixed bug when the first + argument starts with a special brace list. + +2004-05-23 Martin Stjernholm + + * cc-engine.el (c-forward-type): Fixed promotion bug when + `c-opt-type-concat-key' is used + (i.e. in Pike). + + * cc-engine.el (c-looking-at-special-brace-list): Fixed bug when + the inner char pair doesn't have paren syntax, i.e. "(< >)". + +2004-04-28 Alan Mackenzie + + Amend doc(-strings) to say that doesn't insert WS into a CPP + line. + + * cc-cmds.el, cc-vars.el (c-indent-command, c-tab-always-indent): + Amend doc strings. + + * cc-mode.texi (@node Indentation Commands): Amend documentation + of c-tab-always-indent. + +2004-04-20 Martin Stjernholm + + * cc-align.el (c-lineup-multi-inher): Made it syntactic whitespace + safe. + +2004-04-19 Martin Stjernholm + + * cc-engine.el, cc-fonts.el: Fixes in handling of Objective-C + directives, e.g. directives spanning lines should work reasonably + well now. + + (c-put-c-type-property, c-clear-c-type-property): New helpers. + + (c-forward-objc-directive): New function to move over any ObjC + directive. + + (c-just-after-func-arglist-p, c-guess-basic-syntax, + c-basic-matchers-before): Use it. + + (c-font-lock-objc-iip-decl): Removed. + + * cc-engine.el (c-guess-basic-syntax): Some improvement in the + template arglist recognition. + +2004-04-17 Martin Stjernholm + + * cc-styles.el (c-style-alist): Fixed several inconsistencies in + the Whitesmith style. + + * cc-mode.texi: Documented c-lineup-after-whitesmith-blocks. Some + other fixes. + + * cc-align.el (c-lineup-after-whitesmith-blocks): New lineup + function to get lines after Whitesmith style blocks correctly + indented. + + (c-lineup-whitesmith-in-block): Backed out the compensation for + opening parens since it's done using `add' lists in the style + definition instead. Don't use the anchor position since it varies + too much between the syntactic symbols. :P + + * cc-vars.el (c-valid-offset): Updated. + + * cc-mode.texi: Updated the doc for offset specifications on + `c-offsets-alist'. + + * cc-engine.el (c-evaluate-offset): Extended to handle lists where + the offsets are combined according to several different methods: + `first', `min', `max', and `add'. Report offset evaluation errors + with `c-benign-error' so that some kind of reindentation still is + done. + + * cc-engine.el (c-guess-basic-syntax): Anchor `arglist-intro' the + same way as `arglist-cont-nonempty' and `arglist-close'. + + * cc-engine.el (c-guess-basic-syntax): Fixed similar situations + for `arglist-cont-nonempty' and `arglist-close'. + +2004-04-16 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Fixed anchor position for + `arglist-intro' when there are two arglist open parens on the same + line and there's nothing in front of the first. + + * cc-mode.texi: Updated the parts dealing with line-up functions. + Fixed some terminology to use the same words everywhere. + + * cc-langs.el (c-opt-identifier-concat-key-depth): New constant. + + * cc-fonts.el (c-basic-matchers-before): Fixed font locking of + qualified names in Java, which previously could fontify common + indexing expressions in many cases. The standard Java naming + conventions are used to tell them apart. + +2004-04-12 Martin Stjernholm + + * cc-defs.el: Use `cc-bytecomp-fboundp' and cc-bytecomp-boundp' in + a number of places. + +2004-04-09 Martin Stjernholm + + * cc-align.el (c-lineup-whitesmith-in-block): Fixed inconsistency + wrt opening parens on the first line inside a paren block. + + * cc-defs.el (c-langs-are-parametric): Made it known at compile + time to avoid warnings. + + * cc-defs.el (c-langs-are-parametric): Must be known at compile + time for the sake of `c-major-mode-is'. + + (c-mode-is-new-awk-p): Made it a macro to delay expansion of + `c-major-mode-is' in the event that this is used inside a + `c-lang-defconst'. + +2004-04-04 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Fixed a macro related + issue. + +2004-04-03 Alan Mackenzie + + * cc-engine.el, cc-cmds.el, cc-awk.el: Remove (nearly all of) the + cruft associated with AWK Mode's former concept of "virtual + semicolons". + + * cc-styles.el, cc-vars.el, cc-engine.el, cc-cmds.el, cc-awk.el: + 1. Add character classes (e.g. "[:alpha:]") into AWK Mode's regexps. + 2. Adapt c-beginning-of-statement, c-end-of-statement (together with + subfunctions) to use the new notion of "virtual semicolon" in place of the + old awkward special handling for AWK. There remains much cruft in + cc-awk.el, cc-cmds.el and cc-engine.el to clear out. + + * cc-awk.el: Change the terminology of regexps: A char list is now [asdf], + a char class [:alpha:]. Include code for char classes. + Set c-awk-NL-prop on lines ending in open strings. (Bug fix.) + + * cc-cmds.el: + (c-ascertain-adjacent-literal): In the backwards direction, now + recognises AWK regexp delimiters as string delimiters. + (c-after-statement-terminator-p): Adapt for virtual semicolons; + check more rigorously for "end of macro". + (c-back-over-illiterals, c-forward-over-illiterals): Adapt for + virtual semicolons; + (c-beginning-of-statement): Adapt for virtual semicolons; Separate + out the code for forward movement into ... + (c-end-of-statement): Now contains the code for forward movement, + adapted for virtual semicolons. + + * cc-engine.el: + (c-ws*-string-limit-regexp): new regexp. + (c-forward-single-comment, c-backward-single-comment): Comment out + the (now redundant) "special" AWK stuff. + + * cc-styles.el, cc-vars.el: Change the settings of + c-string-par-start, c-string-par-separate to be more like Text + Mode than Fundamental Mode. + +2004-03-27 Alan Mackenzie + + * cc-engine.el, cc-styles.el: + Add in two checks for user errors, thus eliminating cryptic and unhelpful + Emacs error messages. (1) Check the arg to `c-set-style' is a string. + (2) Check that settings to `c-offsets-alist' are not spuriously quoted. + +2004-03-26 Alan Mackenzie + + * cc-mode.texi: Synchronise with the 5.31 latest version, 5.197, + in particular enhancing the documentation of `c-add-style'. + +2004-03-26 Martin Stjernholm + + * cc-mode.texi: Enhanced the style doc somewhat more. + +2004-03-25 Martin Stjernholm + + * cc-defs.el (c-major-mode-is): Fixed expansion inside + `c-lang-defconst' so that it works better with fallback languages. + + * cc-defs.el (c-add-language): Fixed a typo that caused it to fail + to record the base mode. + +2004-03-23 Martin Stjernholm + + * cc-fonts.el (c-font-lock-declarations): Always narrow to the + fontified region so that fontification doesn't occur outside it + (could happen e.g. when fontifying a line with an unfinished + declaration). + +2004-03-18 Martin Stjernholm + + * cc-engine.el (c-syntactic-re-search-forward): Fixed bug so that + it doesn't go past the closing paren when PAREN-LEVEL is used. + Reordered the syntax checks to get more efficient skipping in some + situations. + +2004-03-18 Alan Mackenzie + + * cc-awk.el, cc-defs.el, cc-engine.el, cc-langs.el, cc-mode.el: + Amend the concept of "virtual semicolons" (in the indentation engine) for + languages like AWK, such that they are now conceptually attached to end of the + last token of a statement, not the end of the line. (In AWK Mode, however, + the pertinent text property is still physically set on the EOL.) Remove the + specific tests for awk-mode, thus facilitating the introduction of other + language modes where EOLs can end statements. (Note: The funtionality in + cc-cmds.el, specifically c-beginning/end-of-statement has yet to be amended.) + + * cc-awk.el: Regexps for analysing AWK code have been moved to near the start + of the file. ^L now separate sections of the file. + New defconsts: c-awk-non-eol-esc-pair-re, + c-awk-blank-or-comment-line-re, c-awk-one-line-possibly-open-string-re, + c-awk-regexp-one-line-possibly-open-char-class-re, + c-awk-one-line-possibly-open-regexp-re, c-awk-one-line-non-syn-ws*-re. + New functions: c-awk-at-vsemi-p, c-awk-vsemi-status-unknown-p. + * cc-defs.el: New macros c-at-vsemi-p, c-vsemi-status-unknown-p. + + * cc-langs.el: Added `#' into AWK Mode's value of c-stmt-delim-chars. New + c-lang-defvars: c-at-vsemi-p-fn, c-vsemi-status-unknown-p-fn (in a new + page). + + * cc-engine.el: In c-beginning-of-statement-1, c-crosses-statement-barrier-p, + c-guess-basic-syntax, replace numerous awkward forms like + (if (c-major-mode-is 'awk-mode) (c-awk-prev-line-incomplete-p)) with + (c-at-vsemi-p). Fix a few typos. In c-guess-basic-syntax, new variable + before-ws-ip, the place just after char-before-ip appears. + + * cc-mode.el: Fix what's almost a semantic ambiguity in a comment. + +2004-03-02 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Cleaned up using + `c-tentative-buffer-changes'. + + * cc-defs.el (c-region-is-active-p): Simplified and converted to + macro to choose between Emacs and XEmacs at compile time. + + (c-set-region-active): New set counterpart to + `c-region-is-active-p'. + + (c-tentative-buffer-changes): New macro to handle temporary buffer + changes in a convenient way. + + (c-tnt-chng-record-state, c-tnt-chng-cleanup): Internal helpers + for `c-tentative-buffer-changes'. + + * cc-cmds.el (c-electric-brace): Don't trip up on a line + continuation which might precede the newly inserted '{'. + +2004-03-01 Martin Stjernholm + + * cc-engine.el (c-syntactic-re-search-forward): Fixed cases where + it could loop indefinitely. + +2004-02-22 Martin Stjernholm + + * cc-engine.el (c-looking-at-inexpr-block): Tightened up the + checks for paren sexps between the point and the keyword, to avoid + some false alarms. + + * cc-engine.el, cc-langs.el (c-looking-at-inexpr-block): Fixed a + situation where an error could be thrown for unbalanced parens. + Changed to make use of c-keyword-member' to avoid some repeated + regexp matches. + + (c-opt-lambda-key, c-opt-inexpr-block-key, + c-opt-inexpr-class-key): These language variable are no longer + necessary. + + (c-block-stmt-kwds): New language constant used by + c-looking-at-inexpr-block'. + + (c-guess-basic-syntax): Removed an optional check that looked at + the existence of the now removed language variables. + + * cc-engine.el (c-fdoc-shift-type-backward, + c-forward-decl-or-cast-1): Fixed invalid recognition of C++ style + object instantiation expressions as declarations in some contexts. + This bug only affected languages where the declarator can't be + enclosed in parentheses. + +2004-02-21 Alan Mackenzie + + * cc-mode.texi (c-block-comment-prefix): State that it's default + setting, "* " gets overridden by the default style, gnu. + +2004-02-19 Martin Stjernholm + + * cc-styles.el (c-style-alist): Fixed the GNU style to insert + newlines before and after substatement braces. + +2004-02-16 Martin Stjernholm + + * cc-engine.el: Improved the heuristics for recognizing function + declaration headers and the handling of C++ style member init + lists. + + (c-just-after-func-arglist-p): Rewritten to use + `c-forward-decl-or-cast-1'. Now behaves a bit differently too. + + (c-beginning-of-member-init-list): Removed since it isn't used + anymore. + + (c-guess-basic-syntax): Case 5B adapted for the new + `c-just-after-func-arglist-p'. Cases 5B.1 and 5B.3 merged. Cases + 5D.1 and 5D.2 removed since they aren't trigged anymore (case 5B.1 + covers all cases now). + + * cc-defs.el (c-point): Added 'bosws and 'eosws. + +2004-02-15 Alan Mackenzie + + * cc-styles.el, cc-vars.el: Correct silly bug in previous commit. + + * cc-cmds.el, cc-styles.el, cc-vars.el: + New variables c-string-par-start/separate c-sentence-end-with-esc-eol, + initialised in c-setup-paragraph-variables, used in string scanning + subroutines of c-beginning-of-statement. + +2004-02-06 Alan Mackenzie + + * cc-cmds.el (c-electric-brace): don't delete a comment which + precedes the newly inserted `{'. + +2003-12-08 Martin Stjernholm + + * cc-fonts.el (c-font-lock-declarators): Handle array size specs + correctly. Only fontify identifiers in front of '(' with as + functions - don't accept any paren char. Tightened up initializer + skipping to stop before function and class blocks. + +2003-12-07 Martin Stjernholm + + * cc-engine.el, cc-langs.el: Rewrote the recognition function for + declaration level blocks. It should now cope with templates + better and also be a lot more comprehensible. + + (c-looking-at-decl-block): The new function. + + (c-search-uplist-for-classkey): The old one. It's now a wrapper + for compatibility. + + (c-add-class-syntax, c-guess-continued-construct, + c-guess-basic-syntax): Adapted for `c-looking-at-decl-block'. + + (c-decl-block-key): Changed to tell apart ambiguous and + unambiguous keywords. Pike specials are now handled directly in + the code instead. + + (c-block-prefix-disallowed-chars, c-block-prefix-charset): New + language constants and variables to make the backward skip in + `c-looking-at-decl-block' as tight as possible. + + (c-nonsymbol-token-char-list): New language constant. + + * cc-engine.el (c-backward-<>-arglist): New function to find + balanced template arglists backwards. + + * cc-defs.el (c-make-bare-char-alt): New helper for making char + classes for `c-syntactic-skip-backward'. + + * cc-engine.el (c-guess-basic-syntax): Simplified case 16D - can't + be a class-close at that point. + + * cc-engine.el (c-guess-basic-syntax, c-add-class-syntax): Don't + narrow out the enclosing declaration level. This makes everything + a lot easier, and it was actually only four small places that + needed it to work. Some places that previously did `widen' are + removed now, which has the effect that `c-guess-basic-syntax' + never will look at things outside the current narrowment now. The + anchor position for `topmost-intro' is affected by this, but it + was so bogus it was basically useless before, and now it's equally + bogus but in a slightly different way. + + (c-narrow-out-enclosing-class): Gone. + + (c-most-enclosing-brace, c-least-enclosing-brace): Don't filter to + the narrowed region. + + (c-least-enclosing-brace): Removed silly optional argument. + + * cc-engine.el (c-beginning-of-decl-1): Fixed bug where the point + could be left directly after an open paren when finding the + beginning of the first decl in the block. + + * cc-engine.el (c-parse-state): Don't use the syntax table when + filtering out legitimate open parens to be recorded. This could + cause cache inconsistencies when e.g. `c++-template-syntax-table' + was temporarily in use. + + * cc-engine.el (c-beginning-of-decl-1): Fixed bug where the point + could be left directly after an open paren when finding the + beginning of the first decl in the block. + +2003-12-06 Martin Stjernholm + + * cc-engine.el, cc-fonts.el (c-forward-keyword-clause): Specify + which submatch to use. + + * cc-langs.el (c-symbol-start): Include '@' in ObjC. + + (c-decl-start-re): No no longer any need for special treatment of + ObjC due to the above. + + (c-other-block-decl-kwds): Handle "extern" in ObjC too since it + presumably follows C in that regard. + + * cc-langs.el (c-identifier-ops, c-after-id-concat-ops): New + language constants to specify operator tokens inside identifiers + in a more high level way. + + (c-opt-identifier-prefix-key): New internal language constant. + + (c-opt-identifier-concat-key, c-opt-after-id-concat-key, + c-identifier-start, c-identifier-key): Now completely calculated + from other constants. + + (c-identifier-last-sym-match): Decommissioned since it's no longer + used. + + (c-operators): Use `c-identifier-ops'. Documented + `postfix-if-paren'. + + * cc-engine.el (c-forward-name): Removed the optimization when + c-identifier-key is equal to c-symbol-key since it doesn't work in + byte compiled files. Don't record empty regions as identifiers. + + * cc-langs.el (c-filter-ops): New helper function to simplify + access to `c-operators' and its likes. + + (c-operator-list, c-all-op-syntax-tokens, + c-nonsymbol-token-regexp, c-<>-multichar-token-regexp, + c-<-op-cont-regexp, c->-op-cont-regexp, c-expr-kwds, + c-primary-expr-regexp, c-cast-parens): Use it. + + * cc-defs.el (c-lang-const): Fixes to allow use without an + explicit language in functions. + + * cc-defs.el (c-make-keywords-re): Added an appendable variant of + adornment. + +2003-12-05 Martin Stjernholm + + * cc-langs.el (c-any-class-key): Removed unused language variable. + + (c-type-decl-prefix-key): Removed some now unnecessary cruft from + the Pike value. + + * cc-engine.el (c-on-identifier, c-simple-skip-symbol-backward): + Small fix for handling "-" correctly in `skip-chars-backward'. + Affected the operator lfun syntax in Pike. + + (c-forward-label): Small fix for handling "-" correctly in + `c-syntactic-skip-backward'. + + * cc-engine.el (c-on-identifier, c-simple-skip-symbol-backward): + Small fix for handling "-" correctly in `skip-chars-backward'. + Affected the operator lfun syntax in Pike. + +2003-12-04 Martin Stjernholm + + * cc-langs.el (c-make-init-lang-vars-fun): Disabled the diagnostic + message about precompiled language vars not being used. + + * cc-langs.el (c-paren-nontype-kwds): The GCC keyword + "__attribute__" is followed by a parenthesis. + + (c-type-start-kwds, c-prefix-spec-kwds, c-prefix-spec-kwds-re, + c-specifier-key, c-not-decl-init-keywords): Some cleanup using new + language constants `c-type-start-kwds' and `c-prefix-spec-kwds'. + +2003-11-30 Martin Stjernholm + + * cc-engine.el (c-invalidate-sws-region-after): Fixed bug that + could cause an error from `after-change-functions' when the + changed region is at bob. + + * cc-fonts.el, cc-langs.el, cc-engine.el: Internal cleanups to + properly detect the declared identifiers in various declarations. + + (c-decl-start-kwds): New language constant to recognize + declarations that can start anywhere. Used for class declarations + in Pike. + + (c-specifier-key, c-not-decl-init-keywords, + c-decl-prefix-or-start-re, c-find-decl-prefix-search, + c-find-decl-spots): Implement `c-decl-start-kwds'. + + (c-other-decl-kwds, c-postfix-decl-spec-kwds, c-decl-hangon-kwds, + c-decl-hangon-key, c-forward-decl-or-cast-1): Separated the + handling of the compiler specific extension keywords into a new + language constant `c-decl-hangon-kwds' that defines keyword + clauses to be ignored in declarations. + + (c-forward-id-comma-list, c-forward-keyword-clause): Don't skip + past unrecognized tokens when handling `c-colon-type-list-kwds'. + Necessary to stop at the declared identifier in e.g. IDL valuetype + declarations. + + (c-typedef-decl-kwds, c-typeless-decl-kwds, c-type-list-kwds, + c-prefix-spec-kwds-re, c-postfix-spec-kwds, + c-after-suffixed-type-decl-key, c-opt-postfix-decl-spec-key, + c-forward-decl-or-cast-1): Recognize the declared identifier in + class and enum declarations as such and not as part of the type. + + (c-forward-decl-or-cast-1, c-forward-label): Relaxed the + interpretation of PRECEDING-TOKEN-END when there's no preceding + token. + + (c-forward-decl-or-cast-1): Don't disregard sure signs of + declarations when there's some syntax error later on. + + (c-complex-decl-matchers): Did away with a reference to + `c-specifier-key'. + +2003-11-23 Martin Stjernholm + + * cc-engine.el (c-maybe-labelp): Provide no default value - this + variable is always dynamically bound. + +2003-11-22 Martin Stjernholm + + * cc-engine.el, cc-fonts.el, cc-langs.el, cc-menus.el, cc-mode.el, + cc-styles.el, cc-vars.el, cc-align.el, cc-awk.el, cc-cmds.el, + cc-defs.el: Changed the policy for marking up functions that might + do hidden buffer changes: All such internal functions are now + marked instead of those that don't. + + (c-beginning-of-macro, c-end-of-macro, c-(forward|backward)-comments, + c-(forward|backward)-single-comment, c-parse-state, c-on-identifier, + c-(fast-|slow-|)in-literal, c-literal-limits, c-collect-line-comments, + c-literal-type): Allow these functions to make hidden buffer changes, + so that they are free to use text property caching later on. + + (c-electric-backspace, c-electric-delete-forward, c-electric-pound, + c-electric-brace, c-electric-slash, c-electric-star, + c-electric-semi&comma, c-electric-colon, c-electric-lt-gt, + c-electric-paren, c-electric-continued-statement, c-indent-command, + c-indent-region, c-mask-paragraph, c-indent-new-comment-line, + c-context-line-break): Added `c-save-buffer-state' calls to comply + with the changed semantics of the functions above. + + * cc-engine.el (c-beginning-of-statement-1): + Fixed a bug when macros occur in obscure + places. Optimized the sexp movement a bit. + +2003-11-21 Alan Mackenzie + + * cc-awk.el, cc-cmds.el, cc-engine.el, cc-mode.el, cc-mode.texi: + Enhancements for c-beginning-of-statement to work in AWK Mode: + cc-awk.el: + Supersede c-awk-NL-prop value `;' (completed statement) with `}' (statement + completed by closing brace or semicolon) and `$' (statement completed by + EOL). + New functions: c-awk-virtual-semicolon-ends-prev-line-p, + c-awk-virtual-semicolon-ends-line-p, c-awk-skip-semantic-ws-forward, + c-awk-skip-semantic-ws-backward, c-awk-at-statement-end-p. + cc-cmds.el: + Simplify the structure of functions c-forward-over-illiterals, + c-back-over-illiterals. + Enhance these two functions and c-beginning-of-statement to handle AWK Mode. + cc-engine.el: + Enhance c-forward-single-comment, c-backward-single-comment for AWK mode. + Attempt to clarify their doc-strings. + cc-mode.el: + Put M-a and M-e into awk-mode-map. + cc-mode.texi: + Document that M-a and M-e now work in AWK mode. Fix minor typos. + +2003-11-21 Martin Stjernholm + + * cc-engine.el, cc-fonts.el, cc-langs.el: Cleaned up the label + handling. Labels are now recognized in a uniform and more robust + way, regardless of context. Text properties are put on all labels + to recognize the following declarations better. Multiword labels + are handled both in indentation and fontification for the benefit + of language extensions like Qt. For consistency, keywords in + labels are now fontified with the label face instead. That also + applies to "case" and "default". + + (c-beginning-of-statement-1): Fixed some bugs in the label + handling. Disregard `c-nonlabel-token-key' in labels that begin + with `c-label-kwds'. + + (c-find-decl-spots): Support that the callback adds more + `c-decl-end' spots to find. + + (c-forward-decl-or-cast-1): Don't treat a list of plain + identifiers followed by a colon as a declaration. + + (c-forward-label): New function to recognize labels. + + (c-guess-basic-syntax): Replaced uses of `c-label-key' with + `c-forward-label'. Moved the label recognition cases (14 and 15) + earlier since they aren't so context sensitive now. Handle labels + on the top level gracefully. Moved access label recognition to + the generic label case (CASE 15) - removed CASE 5E. + + (c-font-lock-declarations): Added recognition of labels in the + same round since we need to handle labels in parallell with other + declarations to recognize both accurately. It should also improve + speed. + + (c-simple-decl-matchers, c-basic-matchers-after): Moved + `c-font-lock-labels' so that it only is used on decoration level 2 + since `c-font-lock-declarations' handles it otherwise. + + (c-complex-decl-matchers): Removed the simplistic recognition of + access labels. + + (c-decl-prefix-re): Removed the kludges that was necessary to cope + with labels earlier. + + (c-decl-start-re): New language variable to make + `c-font-lock-declarations' stop for the special protection labels + in Objective-C that start with '@'. + + (c-label-key): Removed since it's no longer used. + + (c-recognize-colon-labels, c-label-prefix-re): New language + constants to support recognition of generic colon-terminated + labels. + + (c-type-decl-end-used): `c-decl-end' is now used whenever there + are colon terminated labels. + + * cc-align.el (c-lineup-arglist): Fixed bug when the first + argument starts with a special brace list. + +2003-11-19 Martin Stjernholm + + * cc-engine.el, cc-fonts.el (c-forward-decl-or-cast-1, + c-font-lock-declarations): Broke out the declaration and cast + recognition from `c-font-lock-declarations' to a new function, so + that it can be used in the indentation engine. + +2003-11-16 Martin Stjernholm + + * cc-engine.el (c-guess-continued-construct, + c-guess-basic-syntax): Check a little more carefully if it's an + function declaration when an unknown construct followed by a block + is found inside a statement context. This avoids macros followed + by blocks to be taken as function declarations. + + (c-guess-continued-construct): Changed the analysis of a statement + continuation with a brace open to `substatement-block', for + consistency with recognized statements. + + (c-add-stmt-syntax): Don't continue to the surrounding sexp if the + start is in a position so that `c-beginning-of-statement-1' jumped + to the beginning of the same statement. + + * cc-engine.el (c-guess-continued-construct, + c-guess-basic-syntax): Check a little more carefully if it's an + function declaration when an unknown construct followed by a block + is found inside a statement context. This avoids macros followed + by blocks to be taken as function declarations. + + (c-guess-continued-construct): Changed the analysis of a statement + continuation with a brace open to `substatement-block', for + consistency with recognized statements. + +2003-11-15 Martin Stjernholm + + * cc-fonts.el, cc-cmds.el, cc-engine.el + (c-forward-<>-arglist-recur): Don't accept binary operators in the + arglist if we're in a function call context, i.e. if + `c-restricted-<>-arglists' is set. That avoids template + recognition in cases like "if (a < b || c > d)". + + (c-restricted-<>-arglists): New more appropriate name for + `c-disallow-comma-in-<>-arglists'. + + Accessing functions updated for the variable name change. + +2003-11-07 Martin Stjernholm + + * cc-engine.el (c-find-decl-spots): Fixed bug in backing up to the + start of the literal. Fixed bug with the point on the wrong side + of the search limit that could happen when the start position is + inside a literal. + + * cc-engine.el (c-parse-state, c-invalidate-state-cache): Modified + the use of `c-state-cache-end' so that it's kept a little bit back + to increase the hit rate. + + (c-parse-state): Changed the macro handling and fixed some + glitches. Macro context is checked more often than necessary now, + but otoh less garbage conses are generated. + + * cc-engine.el (c-parse-state, c-invalidate-state-cache): Cache + the last position where `c-state-cache' applies. This can speed + up refontification quite a bit in blocks where there are many + non-brace parens before the point. + + (c-state-cache-end): New variable for this. + + (c-guess-basic-syntax, c-debug-parse-state): Adapted for the new + cache variable. + +2003-11-06 Martin Stjernholm + + * cc-engine.el (c-find-decl-spots): Take more care to get close + initial continue positions when the start position is inside a + literal or macro. Do not call the callback for spots before the + start position (which can happen e.g. for `c-decl-end' spots + inside comments). Optimize better in special cases when the + region is a single line inside a literal or macro (typically when + the current line is refontified). + +2003-11-04 Martin Stjernholm + + * cc-engine.el (c-syntactic-re-search-forward): Fix bug where the + match data could get clobbered if NOT-INSIDE-TOKEN is used. + +2003-11-02 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Simplified calls to + `c-add-stmt-syntax' - there's no need to explicitly whack off + entries from the paren state. + + * cc-engine.el (c-add-stmt-syntax): Narrowed down the special case + for "else if" clauses. + +2003-11-01 Martin Stjernholm + + * cc-engine.el (c-looking-at-inexpr-block, c-add-stmt-syntax): Use + `c-recognize-paren-inexpr-blocks'. + + * cc-langs.el (c-recognize-paren-inexpr-blocks): New language + variable to recognize the gcc extension with statement blocks + inside expressions. + + * cc-engine.el (c-add-stmt-syntax): Restructured to make it + somewhat more comprehensible. The argument AT-BLOCK-START is no + longer used and hence removed. + + (c-guess-continued-construct, c-guess-basic-syntax): Updated calls + to `c-add-stmt-syntax'. + + * cc-engine.el (c-beginning-of-statement-1): Don't allow parens in + labels. + + (c-backward-to-decl-anchor): Use `c-beginning-of-statement-1' + instead of duplicating parts of it. This fixes bogus label + recognition. + + * cc-engine.el (c-backward-to-decl-anchor): Use + `c-beginning-of-statement-1' instead of duplicating parts of it. + This fixes bogus label recognition. + + * cc-mode.texi: Extended the doc on c-label-minimum-indentation a + little. + + * cc-align.el (c-gnu-impose-minimum): Reverted to the old method + of checking the context in which to apply the minimum indentation, + so that it isn't enforced in e.g. namespace blocks. + + * cc-vars.el (c-inside-block-syms): New constant used by + `c-gnu-impose-minimum'. It's defined close to `c-offsets-alist' + to somewhat reduce the risk of becoming stale. + + * cc-cmds.el, cc-engine.el (c-shift-line-indentation): Moved from + cc-cmds to cc-engine to allow use from cc-align. + +2003-10-29 Martin Stjernholm + + * cc-engine.el (c-beginning-of-inheritance-list): Cope with fully + qualified identifiers containing "::". +q +2003-10-26 Martin Stjernholm + + * cc-engine.el (c-add-type, c-check-type, c-forward-name, + c-forward-type): Improved storage of template types in + `c-found-types' so that they can be recognized better. + + (c-syntactic-content): Added option to skip past nested parens. + + * cc-engine.el (c-forward-name): Set `c-last-identifier-range' all + the time. It's less work that way. Handle that there might not + be an identifier to store in `c-last-identifier-range'. + + (c-forward-type): Handle that `c-last-identifier-range' might be + nil from `c-forward-name'. + + * cc-defs.el: (c-safe-scan-lists, + c-(go-)?(up|down)-list-(forward|backward)): Added limit arguments. + + * cc-defs.el (c-save-buffer-state): Use `unwind-protect' to work + even if the form fails. + + * cc-defs.el (c-make-keywords-re): Added kludge for bug in + `regexp-opt' in Emacs 20 and XEmacs when strings contain newlines. + + * cc-engine.el (c-parse-state): Speedup when moving far down in a + large file in one go. + + (c-get-fallback-start-pos): New helper function for + `c-parse-state'. + +2003-10-25 Martin Stjernholm + + * cc-vars.el (c-emacs-features): Use a space in front of the name + of the temporary buffer. That also avoids dumping problems in + XEmacs due to undo info being left around after the buffer is + killed. + + * cc-mode.texi: Document c-lineup-assignments and c-lineup-math. + + * cc-align.el (c-lineup-assignments): New lineup function which is + like `c-lineup-math' but returns nil instead of `c-basic-offset' + when it doesn't match. + + (c-lineup-math): Changed to use `c-lineup-assignments'. + +2003-10-20 Alan Mackenzie + + * cc-cmds.el: Fix some bugs in subfunctions of + c-beginning-of-statement. New subfunctions + c-in-comment-line-prefix-p, c-narrow-to-comment-innards. + +2003-10-14 Martin Stjernholm + + * cc-fonts.el, cc-langs.el: Use `c-simple-ws' instead of hardcoded + char classes whereever possible. Changed a couple of places to + use skip by syntax instead of skip by char class. + + * cc-langs.el (c-unterminated-block-comment-regexp): Fixed a bug + in the regexp that caused extreme backtracking. + +2003-10-13 Martin Stjernholm + + * cc-engine.el (c-in-knr-argdecl): Look closer at the function + arglist to see if it's a K&R style declaration. + + (c-guess-basic-syntax): CASE 5B.2: Check with `c-in-knr-argdecl' + before returning knr-argdecl-intro. + +2003-10-12 Martin Stjernholm + + * cc-langs.el (c-block-comment-starter, c-block-comment-ender): + New language constants to specify in a single place how block + comments look. + + (c-comment-start-regexp, c-block-comment-start-regexp, + comment-start, comment-end, comment-start-skip, + c-syntactic-ws-start, c-syntactic-ws-end, c-nonwhite-syntactic-ws, + c-syntactic-ws, c-nonempty-syntactic-ws, + c-single-line-syntactic-ws, c-syntactic-eol): Now built from + `c-line-comment-starter', `c-block-comment-starter' and + `c-block-comment-ender'. + + (c-block-comment-regexp, c-unterminated-block-comment-regexp): New + language constants to break up things a bit. + + (c-simple-ws): New language constant for simple whitespace. + + * cc-defs.el (c-concat-separated): New convenience function. + + * cc-defs.el (c-make-keywords-re): Added kludge for bug in + `regexp-opt' in Emacs 20 and XEmacs when strings contain newlines. + Allow and ignore nil elements in the list. + +2003-10-06 Alan Mackenzie + + * cc-cmds.el: Comment out a (n almost certainly superfluous) + check, (eq here (point-max)) in c-beginning-of-statement. + +2003-10-02 Alan Mackenzie + + * cc-cmds.el: Tidy up the comments in c-beginning-of-statement and + subfunctions. + +2003-10-01 Alan Mackenzie + + * cc-awk.el: Replace calls to put-text-property to the more + flexible c-put-char-property and c-clear-char-properties. Add the + author's email address. + +2003-09-30 Alan Mackenzie + + * cc-langs.el: New variable, c-block-comment-start-regexp. + +2003-09-29 Alan Mackenzie + + * cc-cmds.el: 1. Fix stupid error in previous commit. 2. Fix bug + with M-e, when point is inside the closing "*/" of a block + comment. + + * cc-cmds.el: Tidy c-beginning-of-sentence (and subfunctions) so + that it works at BOB and EOB. + + * cc-cmds.el: Correct small inaccuracy in previous check-in. + + * cc-cmds.el, cc-vars.el: More updating of + c-beginning-of-statement, including new variable + c-block-comment-start-regexp. + +2003-09-24 Martin Stjernholm + + * cc-engine.el (c-parse-state): Fixed bug that could cause errors + when the state cache contains info on parts that have been + narrowed out. + +2003-09-22 Martin Stjernholm + + * cc-mode.texi, cc-vars.el (c-comment-prefix-regexp): Document + that `c-setup-paragraph-variables' has to be used when this + variable is changed; it doesn't work to reinitialize the mode + since that typically clobbers the variable. + + * cc-styles.el (c-setup-paragraph-variables): Made it interactive. + +2003-09-21 Martin Stjernholm + + * cc-langs.el (c-known-type-key): Optimize simple symbols from + `*-font-lock-extra-types' so that there's no need to use + `regexp-opt' on those lists. + + * cc-fonts.el (c-font-lock-declarations): Fixed recognition of + constructors and destructors for classes whose names are matched + by `*-font-lock-extra-types'. + + * cc-langs.el (c-type-list-kwds): If "operator" is followed by an + identifier in C++ then it's a type. + + * cc-langs.el (c-type-decl-suffix-key): Fix when + `c-type-modifier-kwds' is empty. + +2003-09-19 Martin Stjernholm + + * cc-fonts.el (c-font-lock-invalid-string): Fix when there are + several strings on the same line. + + * cc-engine.el (c-literal-limits): Removed the compatibility + function for older emacsen. `c-literal-limits-fast' has now taken + the place of this function. + + * cc-vars.el (c-emacs-features): Removed compatibility with older + emacsen: We now require 'pps-extended-state. + +2003-09-17 Martin Stjernholm + + * cc-fonts.el (c-font-lock-invalid-string): Fixed eob problem that + primarily affected XEmacs. Don't use faces to find unterminated + strings since Emacs and XEmacs fontify strings differently - this + function should now work better in XEmacs. + +2003-09-15 Alan Mackenzie + + * cc-cmds.el: New function c-beginning-of-sentence, which obviates + the need to hack sentence-end. This now handles escaped newlines + in strings correctly. Correct minor bugs in c-move-over-sentence + and in c-beginning-of-statement. + +2003-09-13 Alan Mackenzie + + * cc-cmds.el (c-beginning-of-statement (and subfunctions)): Adapt + c-\(back\|forward\)-over-illiterals such that movement over macros + and code are rigorously separated from eachother. Correct a few + incidental bugs. + +2003-09-08 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Fixed a bug in the + `expand-abbrev' workaround which caused braces to disbehave inside + macros. + + * cc-engine.el (c-forward-keyword-clause): Fixed error handling. + This bug could cause interactive font locking to bail out. + +2003-08-31 Martin Stjernholm + + * cc-engine.el (c-just-after-func-arglist-p): Handle paren-style + types in Pike. Also fixed some cases of insufficient handling of + unbalanced parens. + +2003-08-29 Alan Mackenzie + + * cc-cmds.el: Restructure c-beginning-of-statement: Improve its + doc-string. Improve the handling of certain specific cases. + +2003-08-26 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Work around for a misfeature in + `expand-abbrev' which caused electric keywords like "else" to + disappear if an open brace was typed directly afterwards. + +2003-08-24 Martin Stjernholm + + * cc-engine.el, cc-fonts.el, cc-langs.el (c-guess-basic-syntax): + Changed the way class-level labels are recognized; they can now + contain essentially any symbols. + + (c-opt-extra-label-key): New language variable to cope with the + special protection label syntax in Objective-C. + + (c-opt-access-key): Removed; this is now handled better by + `c-nonlabel-token-key' and `c-opt-extra-label-key'. + + (c-complex-decl-matchers): Update to handle that + `c-opt-access-key' no longer exists. + + * cc-engine.el (c-guess-basic-syntax): Make use of the improved + label recognition in `c-beginning-of-statement-1'. + + * cc-engine.el (c-beginning-of-member-init-list): Recognize + bitfields better. + + * cc-engine.el (c-beginning-of-inheritance-list): Removed some + cruft and fixed a bug that could cause it to go to a position + further down. + + * cc-langs.el, cc-engine.el (c-beginning-of-statement-1): Improved + detection of labels in declaration contexts. + + (c-beginning-of-decl-1): Use it. + + (c-nonlabel-token-key): New language constant and variable needed + by `c-beginning-of-statement-1'. + + * cc-engine.el (c-guess-basic-syntax): Fixed bug that manifested + itself due to the correction in `c-forward-sexp'. + + * cc-defs.el (c-forward-sexp, c-backward-sexp): Made these behave + as documented when used at the buffer limits. + + * cc-mode.el, cc-engine.el, cc-langs.el (c-type-decl-end-used): + Made this a language variable. + + * cc-mode.el (c-after-change): Widen the buffer to work correctly + when `combine-after-change-calls' is used together with temporary + narrowings. + +2003-08-23 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Report labels + correctly when the start point is immediately after the colon. + +2003-08-22 Martin Stjernholm + + * cc-vars.el (c-extra-types-widget): The doc string is mandatory + in `define-widget'. + + * cc-align.el, cc-langs.el (c-lineup-math): Don't align the + operators "!=", "<=" and ">=" as assignment operators. + + (c-assignment-operators): New language constant that only contains + the assignment operators. + + (c-assignment-op-regexp): New language variable used by + `c-lineup-math'. + +2003-08-21 Martin Stjernholm + + * cc-defs.el (c-parse-sexp-lookup-properties): Removed since it + isn't used anymore. + + * cc-cmds.el (c-electric-lt-gt): Detect and mark angle bracket + arglists such as template parens in C++. + + * cc-engine.el (c-syntactic-skip-backward): Fixed a bug in the + last check-in. Some optimization. + + * cc-engine.el (c-syntactic-skip-backward): Fixed bug where it + could stop at the same level in a preceding sexp when PAREN-LEVEL + is set. + + * cc-mode.el (c-basic-common-init): Turn on syntax-table text + property lookup only when it's needed. + + * cc-langs.el, cc-engine.el, cc-fonts.el, cc-mode.el: Changed the + policy for paren marked angle brackets to be more persistent; once + marked they remain marked even when they're found to be unbalanced + in the searched region. This should keep the paren syntax around + even when individual lines are refontified in multiline template + arglists. + + (c-parse-and-markup-<>-arglists): New dynamically bound variable + to control markup so that incorrect angle bracket arglists aren't + marked in contexts where the correct value for + `c-disallow-comma-in-<>-arglists' isn't known. + + (c-forward-<>-arglist, c-forward-<>-arglist-recur): The reparse + argument has become `c-parse-and-markup-<>-arglists'. + + (c-remove-<>-arglist-properties): Removed - no longer used. + + (c-after-change-check-<>-operators): New function used on + `after-change-functions' to avoid that "<" and ">" characters that + are part of longer operators have paren syntax. + + (c-<>-multichar-token-regexp): New language variable used by + `c-after-change-check-<>-operators'. + + (c-after-change): Call `c-after-change-check-<>-operators'. + + (c-font-lock-<>-arglists): Use the context properties set by + `c-font-lock-declarations' to set + `c-disallow-comma-in-<>-arglists' correctly to avoid doing invalid + markup. + + (c-font-lock-declarations): Removed code that undoes the invalid + markup done by `c-font-lock-<>-arglists'. + + (c-complex-decl-matchers): `c-font-lock-<>-arglists' now runs + after `c-font-lock-declarations'. + +2003-08-08 Martin Stjernholm + + * cc-engine.el (c-syntactic-skip-backward): Added paren-level + feature. + + (c-guess-basic-syntax): Improved the anchor position for + `template-args-cont' in nested template arglists. There's still + much to be desired in this area, though. + +2003-08-07 Martin Stjernholm + + * cc-engine.el (c-just-after-func-arglist-p): Safeguard against + unbalanced sexps. + +2003-08-03 Martin Stjernholm + + * cc-mode.el (c-init-language-vars-for): Add argument MODE. + Renamed from c-init-c-language-vars'. + (c-initialize-cc-mode): Change accordingly. + (c-common-init): Ditto. + (c-mode): Ditto. + (c++-mode): Use function. + (objc-mode): Ditto. + (java-mode): Ditto. + (idl-mode): Ditto. + (pike-mode): Ditto. + (awk-mode): Ditto. + +2003-08-01 Martin Stjernholm + + * cc-engine.el (c-end-of-current-token): Return whether or not the + point moved. + + (c-search-decl-header-end): Don't trip up on operator identifiers + in C++ and operators like == in all languages. + + * cc-engine.el (c-backward-to-decl-anchor): Detect leading labels + correctly. + +2003-07-21 Alan Mackenzie + + * cc-cmds.el, cc-engine.el, cc-langs.el, cc-mode.texi, cc-vars.el: + Make the "Text Filling and Line Breaking" commands work for AWK + buffers. + +2003-07-20 Martin Stjernholm + + * cc-mode.texi: Some updates due to the dropping of the support + for older emacsen. + + * cc-defs.el, cc-engine.el (c-mode-is-new-awk-p): Removed; + (c-major-mode-is 'awk-mode) can be used instead now. + + * cc-mode.el: Always set up AWK mode since emacsen where it + doesn't work no longer are supported. + + * cc-mode.el, cc-styles.el, cc-vars.el, cc-defs.el, cc-engine.el, + cc-fonts.el, cc-langs.el, cc-cmds.el: CC Mode now requires support + for the syntax-table' text property, which rules out Emacs 19 and + XEmacs < 21.4. Removed various compatibility cruft associated + with those versions. + + * cc-defs.el, cc-fix.el: CC Mode now requires support for the + `syntax-table' text property, which rules out Emacs 19 and XEmacs + < 21.4. Removed various compatibility cruft associated with those + versions. + + * cc-vars.el (c-emacs-features): CC Mode now requires support for + the `syntax-table' text property. + +2003-07-16 Martin Stjernholm + + * cc-fonts.el (c-nonbreakable-space-face): Remove the variable and + use an extra quoted face name instead. All the emacsen flavors + handle that correctly. + + * cc-defs.el (c-langelem-sym, c-langelem-pos, c-langelem-2nd-pos): + Added accessor functions for syntactic elements. + +2003-07-09 Martin Stjernholm + + * cc-engine.el (c-literal-faces): Declare as a variable since it + might be modified. + + * cc-langs.el: (c++-make-template-syntax-table, + c-syntactic-ws-start, c-syntactic-ws-end): Gave more consistent + names to these language constants. + +2003-07-08 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Do not do hidden buffer + changes; there's third party code that calls this function + directly. + +2003-07-07 Martin Stjernholm + + * cc-fonts.el (javadoc-font-lock-keywords, + autodoc-font-lock-keywords): Don't byte compile on font lock + initialization when running from byte compiled files. + +2003-07-06 Alan Mackenzie + + * cc-engine.el: Fix AWK mode indentation when previous statement + ends with auto-increment "++". + +2003-07-05 Martin Stjernholm + + * cc-langs.el, cc-styles.el (c-style-alist, c-lang-variable-inits, + c-lang-variable-inits-tail): The values of these are changed, so + declare them as variables and not constants. + +2003-07-05 Martin Stjernholm + + * cc-langs.el, cc-styles.el (c-style-alist, c-lang-variable-inits, + c-lang-variable-inits-tail): The values of these are changed, so + declare them as variables and not constants. + + * cc-mode.el: Fixed some autoload problems: Try to ensure that the + entry for ".c" extension comes before the one for ".C" on + `auto-mode-alist', to behave better on case insensitive OS:es. + Fixed incorrect entries that were added to + `interpreter-mode-alist'. Moved the autoload directives for AWK + to the top level since they aren't recognized anywhere else. Do + not use the new AWK mode doc in the autoload form for the old AWK + mode. + +2003-07-03 Martin Stjernholm + + * cc-fonts.el (c-font-lock-complex-decl-prepare, + c-font-lock-declarators, c-font-lock-declarations, + c-complex-decl-matchers, c-basic-matchers-after): Use a text + property to mark the items in in declarator lists to handle + refontification inside multiline declarations better. + +2003-07-02 Martin Stjernholm + + * cc-fonts.el (c-font-lock-declarations): Recognize a construct + like "a * b = c;" as a declaration. + + * cc-menus.el (cc-imenu-init): Do not set + `imenu-create-index-function' if the second argument is left out. + This bug broke the imenu support in C, C++ and Java modes. + +2003-06-19 Martin Stjernholm + + * Release 5.30. + + * cc-engine.el, cc-align.el (c-add-stmt-syntax, c-lineup-arglist, + c-lineup-arglist-close-under-paren): Fixes to cope with special + brace lists in Pike. + +2003-06-19 Alan Mackenzie + + * cc-mode.el: awk-mode: Call c-awk-after-change to ensure + syntax-table props at loading. + + * cc-fonts.el: Put (cc-require-when-compile 'cc-awk) to eliminate + compile-time errors. + +2003-06-18 Alan Mackenzie + + * cc-awk.el, cc-engine.el: Added code to analyze AWK top-level + forms properly (c-guess-basic-syntax CASE 5P), + c-awk-backward-syntactic-ws. + +2003-06-17 Martin Stjernholm + + * cc-fix.el: cc-mode-19.el has been renamed to cc-fix.el since it + now contains compatibility stuff for later versions than (X)Emacs + 19. + +2003-06-17 Martin Stjernholm + + * cc-langs.el (c-paren-nontype-kwds): New language constant. + + (c-other-decl-kwds, c-postfix-decl-spec-kwds): Added compiler + specific declspec keywords: __attribute__ for gcc and __declspec + for msvc. + + * cc-fonts.el (c-font-lock-declarations, c-complex-decl-matchers): + Support specifiers in a couple more contexts to cope with msvc + '__declspec'. + + * cc-engine.el (c-forward-keyword-clause): Support + `c-paren-nontype-kwds'. + +2003-06-16 Martin Stjernholm + + * cc-langs.el (c-primary-expr-regexp): Don't match a bare period + as a float. + +2003-06-16 Martin Stjernholm + + * cc-bytecomp.el (cc-bytecomp-setup-environment): Do not cover + functions that have been bound. + + (cc-external-require): New macro to use for requiring external + packages, to handle the environment correctly. + + * cc-defs.el, cc-fix.el, cc-fonts.el, cc-mode.el: Replaced + external require's with `cc-external-require'. + +2003-06-15 Martin Stjernholm + + * cc-engine.el (c-beginning-of-member-init-list, + c-guess-basic-syntax): Fixes in handling of bitfields. + +2003-06-13 Martin Stjernholm + + * cc-langs.el (comment-end): Put a space in front of the comment + ender in C, as it was before the move from cc-mode.el. + +2003-06-11 Alan Mackenzie + + * cc-fonts.el: Do not load cc-awk.elc or awk-font-lock-keywords + unless there is an AWK Mode buffer. + +2003-06-10 Alan Mackenzie + + * cc-awk.el: New file that implements AWK support, superseding the + old separate derived mode in awk-mode.el. + + * cc-vars.el, cc-mode-19.el, cc-langs.el, cc-mode.el, cc-defs.el, + cc-engine.el, cc-fonts.el: Changes for the new AWK support. + +2003-06-05 Martin Stjernholm + + * cc-engine.el, cc-langs.el (c-decl-block-key, + c-search-uplist-for-classkey): Check that the modifier is followed + by "{" in Pike before considering it to start a class-like block. + +2003-05-30 Martin Stjernholm + + * cc-mode.el (c-initialize-cc-mode): Added some compatibility to + make this function behave somewhat more as documented for derived + modes. It's still not enough to make the old AWK mode behave + reasonably, but it's been like this a long time now so fixing it + more might cause trouble elsewhere. :P + +2003-05-29 Martin Stjernholm + + * cc-fonts.el (c-remove-font-lock-face): New macro to remove a + font lock face properly (especially in XEmacs). + + * cc-bytecomp.el (cc-bytecomp-obsolete-fun): Added the same kludge + as in `cc-bytecomp-obsolete-var' to avoid a confused compiler + warning. + + * cc-engine.el (c-forward-type): Fixed a bug in the handling of + concatenated types when the component types are known. + + * cc-fonts.el (c-constant-face-name): Added face name variable to + avoid the use of `font-lock-constant-face' for constants in + emacsen that doesn't have it. + +2003-05-25 Martin Stjernholm + + * cc-styles.el, cc-vars.el, cc-cmds.el: Fixes for the syntactic + symbols for module and composition blocks. + +2003-05-17 Martin Stjernholm + + * cc-mode.el (c-basic-common-init): Use + `open-paren-in-column-0-is-defun-start' if it exists and works. + + * cc-vars.el (c-emacs-features): Added `col-0-paren' to detect + when `open-paren-in-column-0-is-defun-start' exists and actually + works. + +2003-05-07 Martin Stjernholm + + * cc-align.el (c-lineup-argcont, c-lineup-gcc-asm-reg): Don't + quote nil in docstrings. + +2003-04-14 Martin Stjernholm + + * cc-vars.el, cc-langs.el (c-primitive-type-kwds, + c-font-lock-extra-types): "complex" and "imaginary" aren't + keywords in C99, only macros that expand to the keywords + "_Complex" and "_Imaginary", so make the former a bit less + hardcoded by putting it on `c-font-lock-extra-types' instead. + There are also "bool" and "_Bool" that work the same way. + + (c-constant-kwds): "false" and "true" are standard constant macros + in C99. + +2003-04-09 Martin Stjernholm + + * cc-menus.el, cc-langs.el, cc-engine.el, cc-fonts.el, cc-cmds.el: + Fixed various regexps to use POSIX char classes when that is + supported. + + * cc-defs.el (c-alpha, c-alnum, c-digit, c-upper, c-lower): New + constants to make it easier to create regexps that use POSIX char + classes in emacsen that support them. + +2003-04-07 Martin Stjernholm + + * cc-vars.el (c-emacs-features): Detect in the regexp engine + understands POSIX char classes. + +2003-04-05 Martin Stjernholm + + * cc-mode.el (c-after-change): Added kludge for bug where this + function sometimes gets positions outside the buffer range. + +2003-03-30 Martin Stjernholm + + * cc-engine.el (c-beginning-of-member-init-list): Better handling + of paretheses in unexpected places. + + * cc-engine.el (c-forward-<>-arglist-recur): Fixed a regexp match + order problem that could cause empty template args on the form + "<>" to be missed. + +2003-03-23 Martin Stjernholm + + * cc-engine.el (c-parse-state): Added kludge to avoid an infinite + loop when Emacs' open-paren-in-column-zero rule kicks in and + causes the sexp functions to misbehave. + +2003-03-06 Martin Stjernholm + + * cc-engine.el (c-beginning-of-member-init-list): Fixed bug when + C++-like code is encountered in non-C++ mode. + +2003-03-02 Martin Stjernholm + + * cc-defs.el (c-make-keywords-re): Added option to specify the + language to look up `c-nonsymbol-key' in. + +2003-02-24 Martin Stjernholm + + * cc-cmds.el, cc-engine.el (c-auto-newline-analysis): New + dynamically bound variable to turn off the + topmost-intro-cont/statement-cont kludge for brace lists during + the analysis for the auto newline feature. This fixes some cases + where the setting for `brace-list-open' on + `c-hanging-braces-alist' didn't have any effect. + +2003-02-23 Martin Stjernholm + + * cc-langs.el (c-literal-start-regexp): Yet another language + variable. + + * cc-fonts.el (c-font-lock-doc-comments, + c-find-invalid-doc-markup, javadoc-font-lock-keywords): Fixed + fontification of the markup in Javadoc comments. + + * cc-engine.el: Fixes in face handling to cope with doc comments. + + (c-find-decl-spots): More failsafe skipping of comments and + strings that only have been partially fontified. + + * cc-defs.el (c-got-face-at): New subst to test faces at positions + easier. + + * cc-defs.el (c-safe-scan-lists): New wrapper macro to avoid the + warnings with too many args to `scan-lists' in Emacs. + +2003-02-22 Martin Stjernholm + + * cc-engine.el (c-syntactic-skip-backward): New function to make + syntactic searches in the backward direction easier. + + (c-beginning-of-statement-1): Optimized skipping over large paren + sexps somewhat. + + (c-safe-position): Removed the odd macro handling which was + centered around the point instead of the passed position. + +2003-02-16 Martin Stjernholm + + * cc-engine.el (c-in-knr-argdecl): Do not trip up on + initialization expressions. + + * cc-align.el (c-lineup-arglist, c-lineup-close-paren, + c-lineup-arglist-close-under-paren): Tuned the "macro block" + heuristics to work better in nested arglist situations. + +2003-02-10 Martin Stjernholm + + * cc-styles.el (c-set-offset): Don't find a default syntactic + element through syntactic analysis if called outside a CC Mode + buffer. + +2003-02-09 Martin Stjernholm + + * cc-mode.el (c-basic-common-init): Install `c-fill-paragraph' on + `fill-paragraph-function'. Although it's not the normal way to + call it in a CC Mode buffer it makes a direct call to + `fill-paragraph' work better. + +2003-01-28 Martin Stjernholm + + * cc-vars.el, cc-mode.el (c-require-final-newline): Made this + variable an alist to specify a value for each language. The + default value causes `require-final-newline' to be set to t only + in languages where the standard requires a final newline. + +2003-01-25 Martin Stjernholm + + * cc-mode.el, cc-vars.el (c-require-final-newline): Added a + variable to make the initialization of `require-final-newline' + more configurable. + + * cc-vars.el (c-mode-common-hook): Do not change the format string + to "CC Mode Common Hook" since that causes confusion (although it + is a more accurate name). + +2003-01-20 Martin Stjernholm + + * cc-fonts.el (javadoc-font-lock-keywords, + autodoc-font-lock-keywords): Support for Javadoc and Pike Autodoc + doc comments. + + * cc-vars.el (c-doc-comment-style): New variable to control the + fontification of documentation comments on top of the normal mode + font lock. + +2003-01-14 Martin Stjernholm + + * cc-langs.el, cc-fonts.el (c-primary-expr-regexp, + c-font-lock-declarations): Avoid false recognition of parens as + casts when they are followed by an operator that is both prefix + and infix. + +2003-01-07 Martin Stjernholm + + * cc-cmds.el (c-guess-fill-prefix): Tuned the heuristics of when + to use `c-block-comment-prefix' for an unclosed block comment. + +2002-12-22 Martin Stjernholm + + * cc-engine.el, cc-langs.el (c-nonsymbol-sexp-kwds, + c-forward-keyword-clause): Handle keywords like "extern" that can + be followed by e.g. a string literal. + + * cc-defs.el (c-make-keywords-re): Make a regexp correctly with + one submatch when adorn is set and the list is empty. + +2002-12-14 Martin Stjernholm + + * cc-fonts.el (c-font-lock-declarations): Fixed a search that + could go far past the relevant region and cause slowness. Do not + limit the declaration detection to the fontified region since that + can cause misfontification in multiline declarations. + + * cc-engine.el (c-find-decl-spots): Added limit argument to handle + declarations spanning the fontification limit better. + +2002-12-10 Martin Stjernholm + + * cc-engine.el (c-in-literal, c-literal-limits, + c-literal-limits-fast, c-beginning-of-inheritance-list): Use the + paren cache instead of the impaired ad hoc in + `beginning-of-defun', so that these functions doesn't trip up on + "{" in the first column inside strings or comments. + +2002-12-06 Martin Stjernholm + + * cc-vars.el (c-hanging-braces-alist): Added `statement-cont' and + made it auto newline free by default. + + * cc-cmds.el (c-electric-brace): Added `statement-cont' to the + list of syntactic symbols to consider for auto newlines since it + can be used for in-statement brace lists. + + * cc-vars.el (c-emacs-features): There's no need to have this + constant autoloaded. + +2002-12-04 Martin Stjernholm + + * cc-fonts.el (c-font-lock-declarations): Use + `c-recognize-typeless-decls' to avoid fontifying some macro + constructs as declarations in languages where a preceding type is + mandatory. + + * cc-langs.el (c-recognize-typeless-decls): New language variable. + +2002-11-30 Martin Stjernholm + + * cc-align.el (c-lineup-close-paren): Use `c-syntactic-eol' when + checking if the open paren ends its line. + + * cc-langs.el (c-syntactic-eol): Handle a line continuation + backslash. + +2002-11-26 Martin Stjernholm + + * cc-align.el (c-snug-do-while): Compatibility fix for changed + structure in `c-syntactic-context'. + +2002-11-25 Martin Stjernholm + + * cc-engine.el (c-parse-state): Filter angle bracket arglist + parens in a better way than disabling the syntax table properties + completely. + + * cc-fonts.el (c-cpp-matchers): Handle line continuations in cpp + expressions. Do not fontify symbols after #ifdef etc as variables + since that isn't consistent with how the face is used elsewhere + (i.e. only for the definition of the symbol). + +2002-11-24 Martin Stjernholm + + * cc-mode.el: Added autoload directives for the interface + functions in cc-langs. + +2002-11-19 Martin Stjernholm + + * cc-fonts.el (c-font-lock-declarations): Added a property to + handle refontication in multiline declaration arglists better. + + (c-font-lock-<>-arglists): Fix to handle recursive template + arglists better. (As a side effect this will make fontification + work better in older emacsen too.) + + * cc-engine.el (c-forward-<>-arglist, + c-remove-<>-arglist-properties): Use a common text property + `c-type' for all sorts of CC Mode char classification, to avoid + cases when then same char is given conflicting types. + + (c-forward-<>-arglist): New reparse argument to control that + aspect explicitly. + + (c-forward-name, c-forward-type): Changes in the handling of + recursive template arglists. Fixes to cope with the new 'known + type classification. + +2002-11-16 Martin Stjernholm + + * cc-mode.el (c-basic-common-init): Added the new char property + `c-type' to `text-property-default-nonsticky'. + + * cc-defs.el (c-put-char-property, c-get-char-property, + c-clear-char-property, c-clear-char-properties): Generalized + `c-put-char-syntax' and `c-get-char-syntax' to handle any + property. + + * cc-bytecomp.el (cc-bytecomp-defun): Fixed bug that caused + existing function definitions to be overridden by phonies when the + bytecomp environment is restored. + +2002-11-15 Martin Stjernholm + + * cc-cmds.el (c-mask-paragraph): Masking is necessary in normal + code too to avoid getting a fill prefix from a nearby comment. + Changed the name from `c-mask-comment' to a more accurate one. + + * cc-defs.el, cc-mode.el: Changed the auto-load-alist strategy to + not add entries on package load, to be defensive in the case that + autoloads are updated in older emacsen. The bug that would occur + in that case would probably be rather nasty for the average user. + +2002-11-14 Martin Stjernholm + + * cc-fonts.el (c-font-lock-declarations): Fine tuning of the + decision tree that tells declarations from expressions to produce + better results in some ambiguous cases. + + * cc-fonts.el (c-font-lock-syntactic-face-function): Removed since + it doesn't give the control we want. + + (c-font-lock-invalid-string): Replacement for + `c-font-lock-syntactic-face-function' that puts the error face on + the string opener only, to avoid the annoying excessive use of the + error face while a string literal is being written. + + (c-basic-matchers-before): Use `c-font-lock-invalid-string'. + + * cc-engine.el (c-string-syntax, c-string-limit-regexp): Added + constants to use when handling string limits, since not all old + emacsen react well to the "|" syntax class. + + (c-literal-limits, c-literal-limits-fast, c-literal-type): Use + `c-string-syntax' and `c-string-limit-regexp'. Replaced some + hardcoded comment start regexps with `c-comment-start-regexp'. + +2002-11-08 Martin Stjernholm + + * cc-mode.el: Added an association for pike-mode on + `intepreter-mode-alist'. + +2002-11-04 Martin Stjernholm + + * cc-mode.el: Add the `auto-mode-alist' entries to the end instead + of the start of the list, to avoid overriding user additions that + are made before this file is loaded when the entries don't + correspond to any already on `auto-mode-alist'. + + This is done through the third append argument to + `auto-mode-alist'. That doesn't exist in older (X)Emacsen, so the + function is adviced in cc-defs. However, that advice doesn't help + if the autoloads are updated in an old (X)Emacs with this version + of CC Mode, but I believe it's unlikely that anyone does that when + CC Mode isn't distributed with with it. + + * cc-defs.el (add-to-list): Added advice to get the optional third + append argument in older (X)Emacsen. + + * cc-langs.el (c-keywords-obarray): Kludge for strange bug in + Emacs that gives so odd errors that I frankly don't even muster to + begin trying to narrow it down. If someone is so inclined, + restore the commented code, byte compile, and try to open a C++ + file or something in font lock mode. + +2002-11-03 Martin Stjernholm + + * cc-langs.el: Updated the IDL support from the specs. This also + adds the keywords for the variants PSDL and CIDL. (This is mostly + done from reading the grammars only; very lightly tested.) + + * cc-langs.el (c-type-list-kwds): Added "new" in Java. + + * cc-fonts.el: Made sure that `parse-sexp-lookup-properties' is + properly insulated from clobbering by the font-lock package at all + relevant entry points. + +2002-11-01 Martin Stjernholm + + * cc-langs.el (c-opt-after-id-concat-key): New language constant + to make the recognition of identifier qualifiers more flexible. + Recognize the identifier before ".*" as a qualifier in Java. + + (c-identifier-key): Recognize "::*" inside identifiers in C++. + Recognize identifiers ending with ".*" in Java for the sake of + import directives. + + (c-type-list-kwds, c-ref-list-kwds): Recognize "import" and + "package" declarations in Java. + + * cc-vars.el (c-doc-face, c-doc-marker-face, c-doc-markup-face): + Removed since they aren't used (and probably won't be). + + * cc-langs.el (c-ref-list-kwds): New language constant to specify + keywords followed by references. + + (c-last-identifier-range): New variable to avoid going back to + search for the identifier to font lock after a call to + `c-forward-name'. + + (c-type-prefix-kwds, c-type-list-kwds): Fixed classification of + "@interface" etc in Objective-C. + + * cc-engine.el (c-forward-keyword-clause): Fixed handling of + keyword prefixes in `c-type-list-kwds' and + `c-colon-type-list-kwds' clauses. + + (c-keyword-sym, c-keyword-member): New functions to lookup and + categorize keywords. + + (c-forward-keyword-clause): New function to move over a keyword + and its associated clause according to `c-<>-arglist-kwds' etc. + + * cc-langs.el (c-typeless-decl-kwds, c-type-list-kwds, + c-colon-type-list-kwds, c-colon-type-list-re, c-paren-type-kwds): + New language constants and variables to generalize the recognition + of various language constructs. + + (c-keywords): Did away with the list of `*-kwds' constants. It's + now built through macro expansion. + + (c-keywords-obarray): New language variable which contains each + keyword as a symbol, to make fast reverse lookup of keywords to + the `*-kwds' lists they come from. + +2002-10-31 Martin Stjernholm + + * cc-defs.el (c-lang-defconst-eval-immediately): Added macro to be + able to do direct evaluation in `c-lang-defconst' forms. + + * cc-engine.el (c-syntactic-re-search-forward): Fixed a bug which + could cause the point to end up outside the containing sexp if + PAREN-LEVEL was used. + + * cc-engine.el, cc-fonts.el, cc-langs.el: Generalized the C++ + template arglist support to handle angle bracket arglists in any + language. + + (c-recognize-<>-arglists, c-<>-arglist-kwds, + c-opt-<>-arglist-start): New language variables to control angle + bracket arglists. + + (c-opt-type-suffix-key): Use `c-recognize-<>-arglists' in + Objective-C instead of matching a protocol reference list as a + type suffix. + +2002-10-30 Martin Stjernholm + + * cc-align.el (c-gnu-impose-minimum): Fixed a missing + `save-excursion' that caused the point to jump around. + +2002-10-26 Martin Stjernholm + + * cc-mode.el, cc-menus.el (objc-mode, cc-imenu-init): Fixed + initialization bug that has made the Objective-C support + inoperational since 5.26. + + (cc-imenu-objc-generic-expression): Updated submatch indices due + to changes in `cc-imenu-c++-generic-expression'. + + (cc-imenu-objc-function): Don't add an empty "C" menu since imenu + doesn't like that. + +2002-10-25 Martin Stjernholm + + * cc-align.el (c-lineup-arglist, + c-lineup-arglist-close-under-paren, c-lineup-close-paren): Added + DWIM to the functions that line up at or after the arglist open + paren to avoid that if there are brace blocks inside, e.g. when a + macro contains a code block. + +2002-10-24 Martin Stjernholm + + * cc-vars.el (objc-font-lock-extra-types): Changed default to + treat identifiers starting with capital letters as types, + according to Objective-C naming conventions. The types previously + on the list is part of the language and therefore on + `c-primitive-type-kwds' instead. + + * cc-fonts.el: Fixed font locking in Objective-C. Be more careful + about returning nil from functions used directly as font-lock + matchers. + + * cc-mode.el (c-font-lock-init): Made the syntax table + modification element of `font-lock-defaults' parameterized over + the languages. + + * cc-langs.el: Updated the Objective-C constants according to the + language spec. The "@" chars that start directives are now + considered part of the keywords to make things easier. + +2002-10-23 Martin Stjernholm + + * cc-defs.el: + (c-(up|down)-list-(forward|backward)): Made the position optional + and added docstrings. + + (c-go-(up|down)-list-(forward|backward)): Added variants of the + above that move point and return successfulness instead. + +2002-10-21 Martin Stjernholm + + * cc-fonts.el (c-font-lock-<>-arglists): New function to fontify + all occurrences of template arglists in C++. + + * cc-engine.el (c-disallow-comma-in-<>-arglists): New variable to + be able to avoid false recognition of template arglists in some + cases. + +2002-10-20 Martin Stjernholm + + * cc-fonts.el, cc-langs.el (c-decl-prefix-re, + c-font-lock-declarations): Match template open brackets to get a + declaration in the first template argument. + + (c-complex-decl-matchers): Fontify the second type in a "class X = + Y" expression in C++. + +2002-10-19 Martin Stjernholm + + * cc-engine.el (c-forward-<>-arglist): Broke out the recursive + part to a new function to improve efficiency when a nested + template arglist search turns out to be futile. + +2002-10-13 Martin Stjernholm + + * cc-menus.el (cc-imenu-java-generic-expression): Improved to + avoid false matches on e.g. "else if (foo)". + +2002-10-11 Martin Stjernholm + + * cc-engine.el (c-forward-token-2, c-backward-token-2): New + functions that work like the -1 variants but that handles + multicharacter operator tokens. + + * cc-engine.el (c-inside-bracelist-p, c-guess-basic-syntax): Did + away with the hardcoded regexps to recognize "typedef" declaration + prefixes, "extern" and "namespace" blocks, "enum"-style brace list + declarations and Java-style array initializers with "new". + + * cc-langs.el (c-brace-list-decl-kwds, c-brace-list-key, + c-inexpr-brace-list-kwds, c-opt-inexpr-brace-list-key): New + language constants and variables to parameterize some more of the + hardcoded regexps in cc-engine. + +2002-10-10 Martin Stjernholm + + * cc-align.el (c-lineup-cascaded-calls): Do not allow cascaded + call lists containing both "->" and ".". + +2002-10-09 Martin Stjernholm + + * cc-align.el, cc-cmds.el, cc-defs.el, cc-engine.el, cc-fonts.el, + cc-langs.el, cc-mode.el, cc-styles.el: New language variable + system to make it easier to set up optimized language variables + and to extend them in third party derived modes. cc-langs is no + longer required at runtime. + + * cc-mode.el (c-basic-common-init): No longer initializes the + language variables. It's necessary that the caller does that + directly since the evaluated values for them now get compiled in + directly. + + (c-font-lock-init, c-common-init): Separated the font-lock + initialization from `c-common-init'. + + * cc-mode.el (c-define-abbrev-table): Do not override an existing + abbrev table. + + (c-Java-defun-prompt-regexp): Moved here from cc-langs since + cc-langs isn't always loaded at runtime. + + * cc-langs.el (c-make-init-lang-vars-fun, c-init-language-vars): + Changed to allow language variable initialization from derived + modes. + + (c-mode-menu): New language variable for the mode menu. + + (c-make-mode-syntax-table, c-mode-syntax-table, + make-c++-template-syntax-table): New language variables for syntax + tables. The code that initializes them has been moved to cc-mode + to make it possible to avoid loading cc-langs at runtime. + + * cc-engine.el, cc-langs.el (c-hungry-delete-key, c-auto-newline, + c-auto-hungry-string): Moved these state variables from cc-langs + to cc-engine to make it possible to avoid loading cc-langs at + runtime. + + * cc-defs.el (c-lang-defconst, c-lang-const): Moved from cc-langs + and rewritten to make the language constant system usable from + derived modes. + + (c-add-language): New function intended for use from derived modes + that add new C-like languages. + + * cc-defs.el, cc-vars.el (c-buffer-is-cc-mode): Moved from cc-vars + to cc-defs to define it during compilation. + + * cc-bytecomp.el (cc-require-when-compile): New support macro for + compile time `require's. + +2002-10-08 Martin Stjernholm + + * cc-defs.el, cc-mode.el (c-version): Moved from cc-mode to + cc-defs to make it accessible to the other components. + + * cc-engine.el (c-forward-token-1, c-backward-token-1): + Compatibility fix for emacsen that doesn't understand generic + string delimiters. + + * cc-vars.el (c-emacs-features): Added detection of generic string + and comment delimiters. + + * cc-defs.el, cc-langs.el (c-make-keywords-re): Changed interface + to make it more extensible. + + * cc-langs.el, cc-defs.el (c-regexp-opt, c-regexp-opt-depth, + c-make-keywords-re): Moved from cc-langs to cc-defs since they are + generally useful. + + * cc-bytecomp.el, cc-defs.el (cc-eval-when-compile): Moved from + cc-bytecomp to cc-defs to allow use at runtime. + +2002-10-04 Martin Stjernholm + + * cc-bytecomp.el (cc-eval-when-compile): Workaround for a bug with + nested `eval-when-compile' in XEmacs 21. + +2002-09-27 Martin Stjernholm + + * cc-mode.el: Added autoloaded forms to install the appropriate + file suffixes on `auto-mode-alist'. Necessary in XEmacs 21.5, and + it can be useful elsewhere too. + +2002-09-23 Martin Stjernholm + + * cc-align.el (c-lineup-cascaded-calls): Handle "." too, for use + in Java. + + * cc-engine.el (c-forward-sws, c-backward-sws): Do not handle cpp + directives in languages that doesn't have any. + +2002-09-22 Martin Stjernholm + + * cc-langs.el (c-operators): Added a high level description of all + operators, along with their precedence and associativity. + + * cc-align.el (c-lineup-multi-inher): Fixed bug where the position + of the point and not the beginning of the line was used to + calculate the indentation. + +2002-09-18 Martin Stjernholm + + * cc-defs.el, cc-engine.el (c-backward-single-comment, + c-backward-comments): Added kludge for the bug in + `forward-comment' in most (X)Emacs versions where it moves back + over the "*/" of a block comment if there's no matching "/*". + This has become more important now since it can cause incorrect + caching by `c-backward-sws'. + +2002-09-16 Martin Stjernholm + + * cc-cmds.el (c-hungry-backspace, c-hungry-delete-forward): New + functions to do hungry deletion regardless of hungry-delete mode. + Contributed by Kevin Ryde. + + * cc-engine.el (c-forward-sws, c-backward-sws, + c-invalidate-sws-region): Use text properties to cache regions + with complex syntactic whitespace. This helps a lot in improving + responsiveness when there are lots of comments and cpp directives + before point. + +2002-09-14 Martin Stjernholm + + * cc-guess.el, cc-langs.el, cc-menus.el, cc-mode.el, cc-styles.el, + cc-vars.el, cc-engine.el, cc-fonts.el, cc-cmds.el, cc-defs.el: + Introduced a classification of functions into those that make + "hidden buffer changes" and those who don't. This is prompted by + the increasing use of text properties for various things, to + correctly cover the silly buffer modifications that is caused by + text property changes. + + (c-save-buffer-state): New macro that's put around any code that + can manipulate text properties. + +2002-09-13 Martin Stjernholm + + * cc-mode.el (c-basic-common-init): Setup + `text-property-default-nonsticky' to avoid messing with the + rear-nonsticky property on each character in Emacs 21. + + * cc-defs.el (c-clear-char-syntax, c-put-char-syntax): Macros that + sets and removes the syntax-table property on a single character + and makes the property nonsticky in both directions in a suitable + way for each (X)Emacs flavor. + + * cc-vars.el, cc-defs.el, cc-engine.el, cc-mode.el: Use + `lookup-syntax-properties' in XEmacs to control whether the + syntax-table property has any effect or not. + + (c-parse-sexp-lookup-properties): New macro that expands to either + `parse-sexp-lookup-properties' or `lookup-syntax-properties'. + +2002-09-12 Martin Stjernholm + + * cc-defs.el, cc-engine.el, cc-fonts.el: Put the faces into the + buffer in the same way as the font-lock package does. This fixes + a compatibility problem with XEmacs which sets an extra font-lock + property. + + * cc-fonts.el (c-put-font-lock-face): A macro that finds out the + right way to put font lock faces at compile time. We're + definitely not byte code portable between Emacs and XEmacs now. + + * cc-engine.el (c-forward-sws, c-backward-sws): Implemented a + cache for the last large skipped over syntactic whitespace. This + also has most effect after many macros. + + * cc-engine.el, cc-defs.el (c-forward-syntactic-ws, + c-backward-syntactic-ws): Utilize the limit better when one is + passed. These are now macros to avoid a little overhead when no + limit is given. + + (c-forward-sws, c-backward-sws): New functions called by the + macros above to do the unbounded search. + + * cc-fonts.el (c-font-lock-declarations): Implemented a cache for + the first backward search for a preceding `c-decl-prefix-re' + match. This typically speeds up interactive refontification a lot + on the top level of macro heavy header files. + +2002-09-10 Martin Stjernholm + + * cc-vars.el (c-emacs-features): Added check for syntax text + properties. + + * cc-mode.el (c-basic-common-init): Turn on + `parse-sexp-lookup-properties' if it's supported. Define the + variable in any case since it's used at runtime to check on this. + + * cc-langs.el (c-identifier-key): Support C++ destructor names. + + (c-identifier-start, c-op-token-regexp, c-type-modifier-kwds, + c-opt-type-modifier-key, c-opt-type-component-key, + c-typedef-specifier-kwds, c-typedef-specifier-key, + c-paren-stmt-kwds, c-paren-stmt-key, c-syntactic-ws-start): A + bunch of new language constants and variables to support the + improved handling of names and types. + + * cc-fonts.el (c-font-lock-declarators, c-font-lock-declarations): + Handle C++ template declarations and template references. Fontify + complex types and names more accurately by delegating it to + `c-forward-type' and `c-forward-name'. Fontify the identifiers in + typedef declarations as types. + + * cc-engine.el (c-forward-<>-arglist): New function to move + forward over a C++ template arglist. It also marks the '<' and + '>' chars with paren syntax using the syntax-table property, to + speed up later calls in emacsen that support syntax text + properties (Emacs >= 20 and (undocumented) XEmacs 21). + + This also has the very interesting effect that if font locking is + used with decoration level 3 or higher in these emacsen then + template arglists will behave just like paren sexps with the + various sexp movement commands. + + (c-forward-name): New function to move over a name. Simple in + most languages except C++ where a name can contain template + arglists and therefore almost arbitrary expressions. + + (c-on-identifier): Fix for Pike operator identifiers. + + (c-simple-skip-symbol-backward, c-syntactic-content, + c-remove-<>-paren-properties): New helper functions. + + * cc-defs.el: (c-clear-char-syntax, c-mark-paren-open, + c-mark-paren-close): New support functions to handle syntactic + properties on C++ template arglist brackets. + + (c-put-type-face, c-put-reference-face): Helpers to put faces on + regions, since there are a bit of that inside `c-forward-name' etc + in cc-engine.el. + + * cc-engine.el, cc-fonts.el, cc-langs.el: Fixed the names on a + number of regexp language variables to conform to the nomenclature + and shortened some names. + + * cc-align.el, cc-cmds.el, cc-fonts.el, cc-engine.el + (c-syntactic-re-search-forward): Removed the COUNT argument since + it's never used. Added an argument to tell which subexpression + whose end should be tested for syntactic relevance. Using this + also removes some optimizations, so that it's possible to use a + look behind subexpression that matches the end of a literal or a + close paren when PAREN-LEVEL is used. + + (c-guess-continued-construct): Don't match <<= or >>= for the + stream-op syntactic element. + + * cc-defs.el (c-paren-re, c-identifier-re): Removed these helper + macros since better and more correct tools are now available in + cc-langs.el. + +2002-09-07 Martin Stjernholm + + * cc-align.el (c-lineup-string-cont): New lineup function to line + up string literals that will be concatenated. + +2002-09-05 Martin Stjernholm + + * cc-langs.el (c-populate-syntax-table): XEmacs classifies the + hard space character as a symbol character but it's better to let + it be in the punctuation class so that it's always highlighted + with the inverted invalid face. It can perhaps be argued that + that character is allowed in identifiers in some languages + (haven't checked), but using it would still be extremely + confusing. + +2002-09-04 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Fixed a case when a + labeled substatement caused incorrect association of the following + continuation clause. + + * cc-engine.el (c-syntactic-re-search-forward): Handle the case + when the syntactic match position is in the middle of a comment + starter. + + (c-guess-continued-construct): Analyze the "K&R region" of a + function nested inside a function as func-decl-cont and not + statement-cont. New case E. Also cleaned up case C (stream-op + recognition) a bit. + + * cc-engine.el (c-parse-state, c-check-state-cache): Moved the + check on `c-state-cache-start' from `c-check-state-cache' to + `c-parse-state' so that the state cache isn't zapped if + `c-check-state-cache' but not `c-parse-state' is called during a + temporary narrowing. This fixes a performance problem that could + occur when `fill-paragraph' is used in font lock mode on a comment + at the end of a large class or function. + + (c-state-cache-start): Fixed buffer localness. + +2002-09-03 Martin Stjernholm + + * cc-langs.el: Updates from the C99 standard (or actually from the + latest web accessible draft of it). + +2002-09-02 Martin Stjernholm + + * cc-langs.el: Updated the keywords and operator tokens from the + latest C++ and Java standards. Some other multichar token + corrections. + +2002-09-01 Martin Stjernholm + + * cc-cmds.el, cc-engine.el, cc-vars.el (c-syntactic-context, + c-syntactic-element): Do not bind any values to these variables + globally since they should always be dynamically bound. This + makes it much easier to debug cases when they've gotten global + values somehow. + +2002-08-31 Martin Stjernholm + + * cc-langs.el (c-regexp-opt): Fix to work around the non-greedy + behavior that the regexp engine sometimes exposes. This bug only + shows in (X)Emacs 19 where there's no regexp-opt package. + + * cc-engine.el (c-syntactic-re-search-forward): Added a feature to + filter out matches in the middle of tokens. Changed the comment + to a docstring since I consider this function generally useful. + + * cc-defs.el (c-mode-symbol): Broke out a part of `c-mode-var'. + + * cc-align.el (c-lineup-cascaded-calls, c-lineup-gcc-asm-reg): + Cope with that `c-most-enclosing-brace' might return nil. + +2002-08-30 Martin Stjernholm + + * cc-engine.el (c-found-types, c-clear-found-types, c-add-type, + c-check-type, c-add-complex-type, c-list-found-types, + c-forward-type): Added a sort of symbol table for types: If a name + is recognized as a type in a declaration it's added in an obarray + to be able to recognize it in other ambiguous declarations. + + (c-remove-ws): New helper function to canonicalize fully qualified + identifiers for `c-found-types'. + + * cc-defs.el (c-mode-var): New defsubst to access mode prefixed + variables uniformly. + +2002-08-23 Martin Stjernholm + + * cc-align.el (c-lineup-arglist-close-under-paren): Work correctly + with nested arglist-cont-nonempty symbols. + + (c-lineup-arglist-operators): New lineup function to line up infix + operators under the open paren of the surrounding sexp. + +2002-08-20 Martin Stjernholm + + * cc-engine.el (c-forward-syntactic-ws): Fixed a bug that could + cause an infinite loop if something that looks like a macro begins + in the middle of a line. + + (c-parse-state): Fixed a bug that could cause `c-state-cache' to + contain two conses in sequence when there's an unbalanced open + paren in a macro. + +2002-08-16 Martin Stjernholm + + * cc-defs.el (c-face-name-p): A defsubst to recognize the name of + a face in a way that works also in XEmacs. + + * cc-engine.el (c-forward-type): New function to move past a type + spec. + + * cc-engine.el (c-syntactic-re-search-forward): Fixed behavior + when the limit is reached inside a comment, string, or a macro. + + * cc-align.el, cc-cmds.el, cc-engine.el (c-forward-single-comment, + c-forward-comments, c-backward-single-comment, + c-backward-comments): New replacements for `c-forward-comment' + that wraps `forward-comment' more efficiently in each of the four + different cases it's actually used. These replacements also + treats line continuations as whitespace. + + (c-forward-comment): Removed. The four different cases above are + basically different, so it's better to make them into separate + functions than choose between them at runtime using the argument. + +2002-08-11 Martin Stjernholm + + * cc-align.el (c-gnu-impose-minimum): Fixed bug due to the new + placement of cpp-macro and comment-intro in the syntactic context, + as pointed out by Kevin Ryde. Changed the method that decides + whether point is inside a top-level construct to one that doesn't + depend on the set of syntactic elements so much. + + * cc-defs.el (c-point): Use the functions + `line-beginning-position' and `line-end-position' in emacsen that + have them (currently Emacs 20 and later). + +2002-07-27 Martin Stjernholm + + * cc-cmds.el (c-mask-comment): Fixed a bug that sometimes caused + code after a closed block comment to be taken into account when + the fill prefix is calculated. + +2002-07-25 Martin Stjernholm + + * cc-align.el (c-lineup-arglist, c-lineup-argcont, c-lineup-math, + c-lineup-cascaded-calls, c-lineup-gcc-asm-reg): Fixes to cope + correctly with nested arglists for the lineups that can be used + with arglist-cont-nonempty. + +2002-07-24 Martin Stjernholm + + * cc-engine.el (c-add-stmt-syntax, c-guess-basic-syntax): Changed + the anchor position of arglist-cont-nonempty and arglist-close so + that a relative indentation like + can be used with consistent + results. Prior to this, the indentation engine more or less + assumed that arglist-cont-nonempty always used `c-lineup-arglist'. + Those two syntax symbols also get the opening paren as an extra + position, to make it possible for `c-lineup-arglist' to continue + to do a proper job. + + * cc-engine.el (c-get-syntactic-indentation): A vector with an + absolute indentation column now only overrides the indentation for + surrounding structures, i.e. those whose syntactic elements are + earlier in the `c-syntactic-context' list, but not nested ones. + This so that e.g. `c-lineup-arglist' can reliably line up with the + first argument but still allow relative indentation changes for + nested things, e.g. the arglist-close of a nested argument list. + This change means that the order in `c-syntactic-context' has + become more essential. + + (c-guess-basic-syntax): Changes to make the nesting order of the + returned syntax list correct. + + Compatibility note: This change means that `c-lineup-dont-change' + now (again) isn't absolutely sure to keep the current indentation. + However, I believe that most people use it for comments, macros + and string literals, and since those are nested innermost it won't + matter. + +2002-06-17 Martin Stjernholm + + * cc-align.el, cc-defs.el, cc-engine.el, cc-vars.el + (c-guess-basic-syntax, c-calc-offset, c-get-syntactic-indentation, + c-syntactic-context): Extended the representation of the syntactic + context: Previously it was a list containing cons cells of the + found syntactic symbols and their relpos values. Now each element + is instead a list containing the syntactic symbol in the first + element and the relpos (if any) in the second. After that there + might be more elements, depending on the syntactic symbol. The + line-up functions get these additional elements as extra + arguments. + + This change is slightly incompatible. Although the calling + convention for line-up functions is strictly extended, the format + of the `c-syntactic-context' variable has changed slightly. It's + believed that this incompatibility is minor, though; not a single + line-up function distributed with CC Mode needed to be changed, + for instance. + +2002-06-08 Martin Stjernholm + + * cc-styles.el (c-set-style, c-set-style-1): Added another state + for the `dont-override' flag where it only keeps globally set + variables. + +2002-06-07 Martin Stjernholm + + * cc-mode.el (c-postprocess-file-styles): Do nothing except in CC + Mode modes. + +2002-06-02 Martin Stjernholm + + * cc-vars.el, cc-fonts.el, cc-langs.el, cc-mode.el: Added font + lock support. + + * cc-engine.el (c-beginning-of-syntax): New function to be used + for font-lock-beginning-of-syntax-function. It uses the state + cache to quickly find a good position. + + * cc-defs.el (c-major-mode-is): Allow a list of modes. Made it a + macro ensure that it's optimized to either eq or memq for constant + arguments. + + * cc-mode.el (c-common-init): Did away with the hardcoded setting + of `comment-column'; it's a user variable that we have no business + meddling with. Since the default value for it is 32 in all + supported (X)Emacs versions, it's also safe from a compatibility + perspective. + + * cc-mode.el (c-basic-common-init): New function that contains + only the syntax and line breaking/filling initialization. It's + intended for use by other modes that embed CC Mode. + +2002-05-25 Martin Stjernholm + + * cc-engine.el (c-add-stmt-syntax): Fixed some cases of wrong + anchoring, e.g. for else-if compounds. + +2002-05-01 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Fixed anchor position for + defun-open in K&R style functions. + + * cc-engine.el (c-in-knr-argdecl): Don't trip up on macros. + + (c-search-decl-header-end): Handle C++ template arguments more + correctly. + + (c-beginning-of-decl-1): Fix when the declaration is first in a + macro. + +2002-04-30 Martin Stjernholm + + * cc-engine.el (c-beginning-of-decl-1): Better way to handle + protection labels, one which doesn't get confused by inherit + colons. + + (c-end-of-decl-1): Don't treat functions that have "class" or + "struct" in the return type as classes or structs. + +2002-04-27 Martin Stjernholm + + * cc-langs.el (c-make-keywords-re): Fixed the keyword adornment so + that it works when a keyword ends with "_". + +2002-04-24 Martin Stjernholm + + * cc-cmds.el (c-mask-comment): More fixes when used from + `c-do-auto-fill' and point is at or near the limit of the comment. + Fixed bug when the prefix from `c-guess-fill-prefix' is longer + than the text on the first line of the comment when it's masked. + +2002-04-23 Martin Stjernholm + + * cc-cmds.el (c-mask-comment): Fixed bug where point was moved to + the following line when it was at the first line of a block + comment where comment-start-skip matched to eol. + +Mon Apr 22 2002 Martin Stjernholm + + * Release 5.29 (Test version; this is not a real release.) + + * cc-engine.el: Incorporated change made in Emacs: Don't + assume point-min == 1 when counting lines. + + * cc-mode.el: Incorporated changes made in Emacs: + + (c-define-abbrev-table): New function to pass the SYSTEM-FLAG + to `define-abbrev' in a way that works in emacsen that doesn't + support it. + + (c-mode-abbrev-table, c++-mode-abbrev-table, + objc-mode-abbrev-table, java-mode-abbrev-table, + pike-mode-abbrev-table): Mark all the predefined abbrevs as + "system" abbrevs. + + (c-submit-bug-report): Make sure that the arguments to + `insert' are strings. + +Sun Apr 21 2002 Martin Stjernholm + + * cc-align.el, cc-engine.el, cc-styles.el, cc-vars.el + (c-guess-basic-syntax, c-lineup-topmost-intro-cont): Find + correct anchor for statement-cont in top level constructs. + Analyze variable initializations in top level constructs as + topmost-intro-cont instead of statement-cont. That is an + incompatible change but it gives better consistency. The new + lineup function c-lineup-topmost-intro-cont' compensates for + it and is now put on topmost-intro-cont by default. + + * cc-align.el, cc-engine.el, cc-langs.el (c-lineup-argcont): + Lineup function contributed by Kevin Ryde. + + (c-in-gcc-asm-p): Function to recognize asm statements. + Contributed by Kevin Ryde. + + (c-opt-asm-stmt-key): New language variable to recognize the + beginning of asm statements. + +Sat Apr 20 2002 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Detect variable + declarations after class and struct declarations correctly. + Fixed limit error when finding the anchor for + template-args-cont and topmost-intro-cont. + +Fri Apr 05 2002 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-defun, c-declaration-limits): + Find the "line oriented" declaration start too, just like the + "line oriented" end is found. + +Thu Apr 04 2002 Martin Stjernholm + + * cc-vars.el (c-offsets-alist): A more sane default for + `inexpr-statement'. This is not compatible, though. I think + the benefit of a good default style outweights that in this + case. Besides, `inexpr-statement' is not very common. + +Mon Apr 01 2002 Martin Stjernholm + + * cc-cmds.el (c-electric-delete-forward): Fixed silly bug that + caused it to delete backwards in hungry delete mode. (It's + amazing that this bug hasn't been reported.) + + * cc-cmds.el (c-declaration-limits, c-mark-function): + Extracted the code to get the declaration limits from + `c-mark-function' to a new `c-declaration-limits'. + + (c-indent-defun): Use the same method to get the limits of the + declaration or macro as `c-mark-function'. + + * cc-engine.el (c-beginning-of-decl-1): Handle brace list + initializers correctly (but costly; it ought to be integrated + into `c-beginning-of-statement-1'). + +Sun Mar 31 2002 Martin Stjernholm + + * cc-cmds.el, cc-engine.el (c-beginning-of-defun, + c-end-of-defun, c-mark-function): Rewritten to detect the + declaration limits better. Now handles K&R argdecls, class + definitions followed by variables etc. + + (c-in-knr-argdecl): Broke out the K&R argdecl test in + `c-beginning-of-decl-1' to this new function. + + (c-end-of-statement-1, c-end-of-decl-1): Replaced + `c-end-of-statement-1' with `c-end-of-decl-1', which correctly + handles declarations that continue after the block. + + * cc-engine.el (c-syntactic-re-search-forward): Added an + option to restrict matching to the top level of the current + paren sexp. + + * cc-langs.el (c-opt-block-decls-with-vars-key): New regexp to + recognize declarations that continue after the block. + + (c-syntactic-eol): New regexp to match a "syntactic" eol. + +Sat Mar 30 2002 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Fixed a bug that often + caused the backward limit to be lost at the top level. This + improves performance a bit. + + * cc-engine.el (c-syntactic-re-search-forward): New function + that works like `re-search-forward' but only returns matches + in syntactically significant text. + + * cc-engine.el: Fixed a faster and more accurate way to + recognize K&R argdecls. + + (c-beginning-of-decl-1): New function that put point at the + beginning of the declaration. It handles K&R argdecl blocks. + + (c-guess-basic-syntax): Replaced the `knr-argdecl' recognition + code with one that doesn't depend on the current indentation. + The anchor position for `knr-argdecl' has also changed, but in + a way that is unlikely to cause compatibility problems. + +Mon Mar 25 2002 Martin Stjernholm + + * cc-defs.el, cc-engine.el (c-forward-comment): + `forward-comment' in XEmacs skips over line continuations in + the backward direction. Correct for that. Also made this a + defun since it has grown too large now to be a defsubst. + + * cc-langs.el: More convenient and decentralized setup of the + language specific variables. The regexp-opt mangling is also + done at compile time now. + +Tue Mar 19 2002 Martin Stjernholm + + * cc-cmds.el (c-indent-line-or-region): Call `c-indent-line' + directly instead of through `indent-according-to-mode' so that + this function always indents syntactically. + + * cc-engine.el (c-guess-basic-syntax): Fixed a bug where a + class beginning with a nested class could cause an infinite + loop (the state outside the narrowed out class is never used + now). + +Sun Mar 17 2002 Martin Stjernholm + + * cc-align.el, cc-cmds.el, cc-engine.el, cc-vars.el: Fixes so + that the context sensitive analysis inside macros is + restricted to the bodies of #define's; other things, like #if + expressions, never have anything in common with their + surroundings. The old `cpp-macro-cont' syntax is now used in + situations where the syntactic analysis isn't applicable, and + a new syntactic element `cpp-define-intro' is used to add + indentation in #define bodies. + + (c-lineup-cpp-define): New name for `c-lineup-macro-cont' to + better reflect its use. + + * cc-engine.el (c-guess-basic-syntax): Ignore line + continuation backslashes in the detection of + `arglist-cont-nonempty'. + + * cc-align.el: Use the vector form in the return value in all + cases where lineup functions return absolute columns. + +Sat Mar 16 2002 Martin Stjernholm + + * cc-engine.el (c-add-stmt-syntax, c-guess-basic-syntax): + Anchor `brace-list-intro' and `brace-list-close' better for + brace lists nested inside expressions. + + * cc-engine.el, cc-langs.el, cc-mode.el, cc-styles.el: Cleaned + up the various language specific variables and their + initialization. The keyword regexps are now lists that are + combined with regexp-opt. Some variables have changed names + to fit better with the naming convention. + + * cc-defs.el, cc-vars.el (c-buffer-is-cc-mode): The value is + the mode symbol of the original CC Mode mode. + + (c-major-mode-is): Compare against the buffer local variable + `c-buffer-is-cc-mode', which is faster than using + `derived-mode-class'. + +Sun Mar 10 2002 Martin Stjernholm + + * cc-engine.el (c-forward-syntactic-ws, + c-backward-syntactic-ws, c-forward-token-1, + c-backward-token-1, c-in-literal, c-literal-limits, + c-collect-line-comments, c-literal-type, c-on-identifier, + c-guess-basic-syntax): These functions are now considered part + of the "CC Mode API" and may be used by other code. That's + signified by making their documentation into docstrings. + + (c-whack-state, c-hack-state, c-skip-case-statement-forward): + Removed these internal functions since they aren't used. + + (c-forward-to-cpp-expression): Classified this function as + internal. + +Thu Mar 07 2002 Martin Stjernholm + + * cc-langs.el (c-ObjC-class-key, c-Java-class-key): Simplified + these regexps; the class keywords they contain ought to be + enough to avoid false matches, so checking for following + identifiers etc is just unnecessary (and might also fail for + oddly formatted code). + +Fri Feb 08 2002 Martin Stjernholm + + * cc-engine.el, cc-cmds.el (c-forward-comment-lc): New + function that behaves like `c-forward-comment', with the + exception that line continuations are treated as whitespace. + + (c-beginning-of-statement): Use `c-forward-comment-lc', to + work correctly in macros and other places where line + continuations should be treated as whitespace. + + * cc-engine.el (c-guess-basic-syntax): Analyze a normal label + in a switch block as a case label, to get consistent lineup + with the case labels. + + * cc-engine.el (c-backward-syntactic-ws): Fixed bug in + skipping over a macro that ends with an empty line. + + * cc-styles.el: Require cc-align since styles added with + `c-add-style' often contains references to functions defined + there, and so the `c-valid-offset' check might otherwise + complain on them. + +Sun Jan 20 2002 Martin Stjernholm + + * cc-align.el, cc-mode.texi, cc-vars.el: Added two new lineup + functions: + + (c-lineup-knr-region-comment): A new lineup function to get + (what most people think is) better indentation of comments in + the "K&R region" between the function header and its body. + + (c-lineup-gcc-asm-reg): New lineup function for better + indentation inside gcc asm blocks. Contributed by Kevin Ryde. + + (c-offsets-alist): Use `c-lineup-gcc-asm-reg' and + `c-lineup-knr-region-comment' in the default offset + configuration, since these two functions have little impact + outside their intended use, and they generally do the right + thing when they kick in. + + * cc-engine.el (c-guess-continued-construct, + c-guess-basic-syntax): Handle nested functions in all + languages, not just Pike. In C and C++ there's a gcc + extension for this, and it also gives better treatment of + macros that are followed by blocks. + + * cc-langs.el (c-symbol-key): Made this variable mode + specific, to handle Pike special symbols like `== better. + +Sat Jan 19 2002 Martin Stjernholm + + * cc-cmds.el, cc-engine.el, cc-vars.el + (c-report-syntactic-errors): A new variable to control the + syntactic error messages. It defaults to off; since CC Mode + ignores most syntactic errors it might as well ignore them all + for the sake of consistency. + +Sat Jan 05 2002 Martin Stjernholm + + * cc-mode.texi: Updated the Limitations and Known Bugs + section. Various small fixes. + +Thu Nov 29 2001 Martin Stjernholm + + * cc-engine.el (c-looking-at-inexpr-block): Optimization. Can + give a noticeable speedup if there's a large preceding + function or class body. + +Sun Nov 25 2001 Martin Stjernholm + + * cc-align.el, cc-cmds.el: Use more efficient and correct + insertion functions in many places. Always inherit text + properties correctly if the text is permanent. Also do it for + speed in temporary insertions, since I figure it's less work + to continue the surrounding text properties than to break + them. + + * cc-styles.el (c-read-offset): Unbind SPC in the completion + to make it easier to enter lists. + +Wed Nov 21 2001 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-defun): Fixed bug where + c-state-cache was clobbered. + + * cc-cmds.el, cc-engine.el (c-calculate-state): Moved from + cc-cmds.el to cc-engine.el due to dependency. + +Mon Oct 22 2001 Martin Stjernholm + + * cc-engine.el (c-parse-state): Ignore unbalanced open parens + in macros (if point isn't in the same one). + +Sat Oct 13 2001 Martin Stjernholm + + * cc-cmds.el (c-context-open-line): New function that is the + `open-line' equivalent to `c-context-line-break'. + + * cc-mode.el (c-mode-base-map): Compatibility fix for Emacs 21 + since `indent-new-comment-line' has been changed to + `comment-indent-new-line' there. + +Sun Oct 07 2001 Martin Stjernholm + + * cc-engine.el, cc-langs.el (c-stmt-delim-chars, + c-stmt-delim-chars-with-comma): New variables containing the + character sets used to recognize statement/declaration + boundaries. These variables might help to support languages + like javascript and awk, where newlines sometimes delimits + statements. + + (c-crosses-statement-barrier-p): Use `c-stmt-delim-chars' as + the set of statement delimiting characters, to allow it to be + changed dynamically and per-mode. + +Sat Oct 06 2001 Martin Stjernholm + + * cc-engine.el (c-looking-at-bos, c-looking-at-inexpr-block, + c-add-stmt-syntax, c-guess-basic-syntax): Treat blocks + directly inside function calls like "bare" statements inside + function calls, and not like in-expression statements. This + to make indentation of such blocks consistent with other + statements inside macro calls. + + * cc-engine.el (c-guess-basic-syntax): Made arglist-cont + anchor correctly in arglists that contain statements. + + * cc-engine.el (c-guess-basic-syntax): Fixed consistent + anchoring of defun-block-intro in defuns in code blocks (can + only occur in Pike). + + * cc-engine.el (c-looking-at-inexpr-block, + c-looking-at-inexpr-block-backward): Changed the arguments to + require containing sexps and paren state, for better + efficiency. + +Fri Oct 05 2001 Martin Stjernholm + + * cc-cmds.el, cc-engine.el, cc-vars.el: Improved anchoring of + statement and handling of labels in front of substatements. + + (c-guess-continued-construct, c-guess-basic-syntax): Improved + and unified anchoring at statements. Statements beginning + with comments or labels are now avoided, by going out of + blocks and containing statements if necessary. This nesting + handling also fixes the case when there's a statement after a + block open brace. Added the syntactic symbol + `substatement-label'. + + (c-electric-colon): Map the new `substatement-label' to + `label' when consulting `c-hanging-colons-alist'. + + (c-offsets-alist): Added substatement-label. Updated the + comments for the new anchoring positions at statements. + + * cc-engine.el (c-guess-basic-syntax): Use more sane anchor + points for knr-argdecl-intro and access-label. They used to + refer to some point on the same line, a bug which was + neutralized by a kludge in `c-get-syntactic-indentation' which + ignored such anchor points. + + (c-get-syntactic-indentation): Removed the kludge that was + necessary due to buggy anchor points. + + * cc-engine.el (c-guess-basic-syntax): Do not check the + absence of a comma before arglist-close (case 7A) in any + language, since there's nothing better to do that case anyway. + Added special case to make in-expression statements be + recognized as normal arglist-cont if we're directly in a macro + arglist, for consistency with other "bare" statements. + + * cc-engine.el (c-looking-at-bos): Added optional limit arg + for backward searches. + + * cc-engine.el (c-looking-at-inexpr-block): Anchor gcc + in-expression statements at the surrounding open parenthesis. + Treat a class body as an in-expression class if it's used in + an object clone expression in Pike. + + * cc-engine.el (c-get-offset, c-get-syntactic-indentation): + Allow several anchor positions in the list of syntactic + symbols. Only the first is used as the base for the offset + calculation. + +Tue Oct 02 2001 Martin Stjernholm + + * cc-cmds.el (c-indent-defun): Indent the current macro if + inside one at the top level. Do not throw an error if used at + the top level outside a macro. + + * cc-cmds.el (c-backslash-region): Do tab width alignment only + if the backslashes can't be aligned with surrounding + backslashes. + + * cc-engine.el (c-end-of-macro): New function. + + * cc-engine.el (c-least-enclosing-brace): Rewritten to not be + destructive. + +Sat Sep 29 2001 Martin Stjernholm + + * cc-cmds.el (c-context-line-break): Only do a macro line + break when point is inside the content of it; if it's in the + cpp keyword a normal line break is done. + + * cc-engine.el (c-guess-basic-syntax): Do not add + cpp-macro-cont inside the argument list to a #define. + +Thu Sep 27 2001 Martin Stjernholm + + * cc-defs.el (c-forward-comment): Implemented a kludge to + avoid the problem most forward-comment incarnations have with + `\' together with comment parsing. + +Wed Sep 26 2001 Martin Stjernholm + + * cc-engine.el (c-check-state-cache): Fixed bug which could + cause the state returned by `c-parse-state' to lack a closed + paren element. That in turn could result in very long + searches, since it's common that they start from the last + preceding close brace. + +Tue Sep 25 2001 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Do not treat + else-if as a single continuation, since that'd make it hard to + get the right anchor point when there's a line break between + the two keywords. This change causes else-clause to be + anchored on the closest preceding else-if and not always on + the starting if, but that doesn't affect the indentation for + any reasonably sane style. Also introduced a noerror flag. + + (c-beginning-of-closest-statement): Removed; + c-beginning-of-statement-1 now avoids the problem this one + solved. + + * cc-engine.el (c-guess-continued-construct, + c-guess-basic-syntax): Better and more uniform anchor points + for 'statement-cont and 'substatement. The effect is + noticeable mostly when there's a label on the same line as the + beginning of the statement, or when there are more stuff + before the start of the statement. + + * cc-engine.el (c-looking-at-inexpr-block): Added flag to + disable looking at the type of the surrounding paren since + that confuses c-beginning-of-statement-1 and a couple of other + places. + + * cc-engine.el (c-guess-basic-syntax): Avoid stepping to the + previous statement in case 18. Improvements in recognition of + statement blocks on the top level. + +Sun Sep 23 2001 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1, + c-crosses-statement-barrier-p): Rewritten to get a well + defined and documented behavior. This fixes some tricky cases + in recognition of do-while constructs. + + (c-backward-to-start-of-do, c-backward-to-start-of-if): + Removed; use c-beginning-of-statement-1 instead. + + (c-guess-continued-construct, c-guess-basic-syntax): Various + fixes to not depend on the bugs previously in + c-beginning-of-statement-1. Cleanups in cases 18 and 17 to + use the new behavior of c-beginning-of-statement-1 better. + Fixed recognition of catch blocks inside macros. + + * cc-engine.el (c-backward-syntactic-ws): Fixed bug in + skipping over a macro. + + * cc-langs.el (c-label-kwds): New variable to contain the + appropriate c-*-label-kwds value. + + * cc-vars.el (defcustom-c-stylevar): Fixed value evaluation + bug that caused the widget for c-block-comment-prefix to bug + out. + +Fri Sep 21 2001 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Improved recognition of + statements: They are now recognized in contexts where they + normally can't occur, e.g. on the top level or in function + call arguments. This is mainly useful to recognize statements + in macros at the top level, and in arguments to macros. The + cases has been moved around quite a bit, and case 10 has been + copied to case 18. (The cases has not been renumbered because + of this.) + + (c-guess-continued-construct): New function which has the + rules which are common between cases 10 and 18. + + * cc-engine.el (c-beginning-of-statement-1, + c-backward-to-start-of-do, c-backward-to-start-of-if): Fixes + so that they really obey the passed limits. + + (c-safe-position): Return nil if the state doesn't contain a + suitable position. + + (c-guess-basic-syntax): Fixes some too short limits in calls + to c-beginning-of-statement-1. Some fixes for top level + analysis in ObjC mode. + + * cc-engine.el (c-beginning-of-statement-1): Fixed bug in + do-while statements where the body is not a block. + + * cc-styles.el (c-set-style): Reset c-special-indent-hook to + its global value if in override mode. Fixes problem where + functions on that hook remained after style switch. + + * cc-engine.el (c-evaluate-offset, c-get-offset): Use + c-benign-error to report the c-strict-syntax-p error. + +Thu Sep 20 2001 Martin Stjernholm + + * cc-align.el, cc-defs.el, cc-cmds.el, cc-engine.el, + cc-vars.el: Several fixes to treat macros as code and not + literals and to handle line continuations transparently. + + (c-skip-ws-forward, c-skip-ws-backward): New macros to skip + through whitespace and line continuations, but not comments + and macros. + + (c-in-literal): No longer recognizes macros as literals by + default. An extra flag argument is required to do that. + + (c-macro-start, c-query-macro-start, + c-query-and-set-macro-start): Added a cache for the macro + start position. + + (c-forward-syntactic-ws, c-backward-syntactic-ws): Fixes for + more speed when limits are given. Workaround for bad behavior + in forward-comment in some emacsen when it hits a buffer limit + with a large repeat count. + + (c-lineup-macro-cont): Improved behavior when + c-syntactic-indentation-in-macros is nil. + + (c-syntactic-indentation-in-macros, c-backslash-max-column, + c-auto-align-backslashes): New customization variables to + control macro handling. + + * cc-menus.el (cc-imenu-c++-generic-expression): Fixes to + handle line continuations. + + * cc-defs.el, cc-styles.el (c-get-style-variables, + c-set-offset): Report style errors with message and ding + instead of error signal. This to avoid interrupted mode init + if there's some style problem. + + (c-benign-error): New macro to report errors that doesn't need + to interrupt the operation. + + * cc-defs.el (c-point): Added eonl and eopl positions. + +Tue Sep 18 2001 Martin Stjernholm + + * cc-cmds.el (c-electric-brace, c-indent-region): Removed most + of the c-state-cache fiddling, since the global state cache + now handles this. + + * cc-engine.el (c-guess-basic-syntax): Fixed bug when there's + an open paren at the very first char of the visible buffer + region. + + * cc-engine.el (c-parse-state, c-check-state-cache): Cache the + state globally and invalidate it below every buffer change + with the new after change function `c-check-state-cache'. + This gives a considerable performance boost when editing large + functions or classes. + + * cc-engine.el (c-whack-state-after): Slight optimization. + +Sun Sep 16 2001 Martin Stjernholm + + * cc-engine.el, cc-langs.el, cc-align.el: Improvements to + syntactic analysis inside macros: + + (c-block-stmt-1-kwds, c-block-stmt-2-kwds): New variables used + by `c-guess-basic-syntax'. + + (c-parse-state): Fixed bug with braces inside macros when + using cached state info. + + (c-forward-to-cpp-expression): New function to aid in + syntactic analysis inside macros. + + (c-beginning-of-statement-1, c-backward-syntactic-ws): Fixes + to work better inside macros. + + (c-forward-syntactic-ws): Whitespace between the # and the + command should be allowed in preprocessor directives. + + (c-lineup-macro-cont): New lineup function to get context + sensitive indentation inside macros. + + (c-offsets-alist): Made `c-lineup-macro-cont' the default for + cpp-macro-cont. + +Sat Sep 15 2001 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1, + c-forward-syntactic-ws): Fixes to handle continued lines. + + (c-backward-to-start-of-if, c-guess-basic-syntax): Do + syntactic analysis inside macros. + +Sat Sep 08 2001 Martin Stjernholm + + * cc-cmds.el (c-indent-region): Did a speedup made possible by + the more flexible state cache. + + * cc-engine.el (c-parse-state, c-whack-state-before, + c-whack-state-after, c-hack-state, + c-narrow-out-enclosing-class, c-guess-basic-syntax): Improved + the state cache system. It now can use partial info from an + old cached state to calculate a new one at a different + position. Removed some kludges to avoid the state cache. The + new functions `c-whack-state-before' and `c-whack-state-after' + replace the now obsolete `c-whack-state'. + + * cc-engine.el (c-beginning-of-statement-1): Optimized backing + through a macro. This can speed things up quite a bit when + there are long macros before point. + + (c-beginning-of-macro): Do not ignore the limit. + +Sun Sep 02 2001 Martin Stjernholm + + * cc-cmds.el (c-electric-continued-statement): Fixed a bug + where the keyword wasn't reindented correctly if followed by + another keyword or identifier. + + * cc-engine.el (c-parse-state): Ignore closed brace pairs that + are in macros. Fixes some cases where e.g. the second of two + "do { } while (0)" macros after each other indented + differently. + +Fri Aug 31 2001 Martin Stjernholm + + * cc-engine.el (c-beginning-of-macro, c-forward-syntactic-ws): + Recognize "#!" as a preprocessor directive when it begins a + line, to allow for script interpreter lines like + "#!/usr/bin/pike" at the beginning of the file. + +Thu Aug 30 2001 Martin Stjernholm + + * cc-engine.el (c-looking-at-inexpr-block): Recognize brace + blocks inside a parenthesis expression as inexpr-statement. + Useful when writing statements as macro arguments. + +Sat Aug 25 2001 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph, c-do-auto-fill, + c-mask-comment): Broke out the comment masking code from + `c-fill-paragraph' to a new function `c-mask-comment', to be + able to do the same thing in `c-do-auto-fill'. This should + make auto-fill-mode behave better. + +Mon Aug 20 2001 Martin Stjernholm + + * cc-cmds.el (c-electric-brace, c-electric-paren): Check + `executing-macro' to avoid blinking parens when macros are + executed. + + * cc-mode.el, cc-styles.el (c-setup-filladapt): Moved from + cc-mode.el to cc-styles.el for consistency with + `c-setup-paragraph-variables' (which was placed there due to + the dependency from `c-set-style'). + + * cc-styles.el, cc-vars.el: Fixed bug with incomplete + initialization from the style variable fallbacks if there + already is a style called "user" defined when CC Mode starts + up for the first time. + +Fri Aug 17 2001 Martin Stjernholm + + * cc-cmds.el, cc-vars.el (c-comment-indent, + c-indent-comment-alist): Added new variable + `c-indent-comment-alist' to allow better control over + `c-comment-indent'. + +Tue Aug 14 2001 Martin Stjernholm + + * cc-align.el (c-lineup-C-comments): Try to match both + `comment-start-skip' and the comment prefix on the current + line with the comment starter, so that we line up comments + which matches `c-comment-prefix-regexp' on the first line + (after the `/') without the need to make `comment-start-skip' + match whatever `c-comment-prefix-regexp' matches. + + * cc-mode.el, cc-styles.el (c-common-init, c-set-style-1, + c-setup-paragraph-variables): Moved the variable + initialization based on `c-comment-prefix-regexp' to a new + function `c-setup-paragraph-variables', which is now used both + at mode init and when a style that sets + `c-comment-prefix-regexp' is activated. + +Sat Aug 11 2001 Martin Stjernholm + + * cc-engine.el (c-beginning-of-member-init-list): Better + handling of C++ template args to avoid confusion with `<' and + `>' used as operators in member init expressions. + +Wed Jul 25 2001 Martin Stjernholm + + * cc-engine.el (c-most-enclosing-brace, + c-least-enclosing-brace): Added optional second arg to limit + the search to before a certain point. + + * cc-engine.el (c-guess-basic-syntax): Fixed bug which could + cause incorrect analysis if a cached state is used (usually + only happens when an electric key reindents a line). + +Tue Jul 24 2001 Martin Stjernholm + + * cc-defs.el (c-forward-comment): More idiosyncrasy + insulation. This time for XEmacs 21. + + * cc-engine.el, cc-langs.el: Improved handling of inheritance + lists: + + (c-beginning-of-inheritance-list): Rewritten to use a more + syntactically correct method that doesn't get confused by + badly placed linebreaks and comments. + + (c-guess-basic-syntax): Several fixes to the handling of + inheritance lists in combination with templates. 'inher-intro + is now anchored on the start of the class declaration and not + the indentation of the current line. Switched places on cases + 5D.3 and 5D.4 and made them use more syntactically correct + methods. + + (c-inher-key): Removed since the code in + `c-guess-basic-syntax' now uses token-based search. + + * cc-cmds.el, cc-mode.el (c-mode-menu): Added a submenu to + access some toggles. + + (c-toggle-syntactic-indentation): New function to toggle the + variable `c-syntactic-indentation'. + + * cc-styles.el (c-set-style): Improved the error message for + incorrect offsets a bit. + +Mon Jul 23 2001 Martin Stjernholm + + * cc-cmds.el (c-indent-exp): Don't require that the sexp + follows point immediately, instead find the closest following + open paren that ends on another line. + +Sat Jul 21 2001 Martin Stjernholm + + * cc-align.el (c-lineup-cascaded-calls): New indentation function. + + * cc-engine.el (c-beginning-of-macro): Bugfix for directives + with whitespace between the '#' and the name. + + * cc-mode.texi: Rearranged the indentation functions in + alphabetic order. Documented c-lineup-cascaded-calls. + +Fri Jul 20 2001 Martin Stjernholm + + * cc-engine.el (c-forward-syntactic-ws, + c-backward-syntactic-ws): Handle line continuations as + whitespace. Don't move past a macro if that'd take us past + the limit. + +Wed Jul 11 2001 Martin Stjernholm + + * cc-engine.el (c-beginning-of-macro, c-forward-syntactic-ws): + Multiline strings begin with `#"' in Pike, and that shouldn't + be confused with a preprocessor directive. + +Mon Jul 09 2001 Martin Stjernholm + + * cc-cmds.el: Extended the kludge to interoperate with the + delsel and pending-del packages wrt to the new function + `c-electric-delete-forward'. + +Fri Jul 06 2001 Martin Stjernholm + + * cc-cmds.el (c-indent-exp): Keep the indentation of the block + itself, i.e. only indent the contents in it. + + * cc-styles.el (c-set-style): Use the default argument to + completing-read instead of initial-contents, if the function + is recent enough to support it. + +Mon Jun 11 2001 Martin Stjernholm + + * cc-mode.el (c-mode-help-address): Removed + bug-gnu-emacs@gnu.org from the receiver list for bug reports. + I've almost never seen a bug reported this way that should go + to that list, but it's rather common that the reports concern + the combination CC Mode and XEmacs instead. + +Sun Jun 10 2001 Martin Stjernholm + + * cc-cmds.el (c-electric-paren): Fixed bug when both + brace-elseif-brace and brace-catch-brace are active and + there's a "else if"-block before the catch block. + + * cc-menus.el (cc-imenu-c++-generic-expression): Detect + function headers that span lines. + +Sat May 12 2001 Martin Stjernholm + + * cc-cmds.el (c-electric-brace, c-electric-semi&comma, + c-electric-colon, c-electric-paren): Check for last on line + only for doing the auto-newline-mode stuff, not for the + reindentation. + + * cc-cmds.el (c-electric-brace): Fixed bugs in the handling of + c-syntactic-indentation: When it's nil, indent the new lines + but don't reindent the current one. Reindent the line only + when the inserted brace comes first on it, instead of last. + + * cc-cmds.el (c-electric-brace, c-electric-semi&comma): Fixed + two places where c-syntactic-indentation wasn't heeded. + + * cc-cmds.el (c-electric-pound): Don't be electric inside a + macro. + + * cc-engine.el (c-backward-to-start-of-if): Try a little + harder to find a fallback position when an orphan else is + found. Fixed case where an else following a do-while + statement could be associated with an if inside the do-while. + +Fri May 11 2001 Martin Stjernholm + + * cc-cmds.el (c-guess-fill-prefix): Tuned the dwim for the + fallback to add a single space after the comment prefix. + + * cc-cmds.el (c-indent-new-comment-line): Somewhat better + behavior in some special cases, especially for single-line + comments. Avoid breaking up a comment starter or ender. + +Sat May 05 2001 Martin Stjernholm + + * cc-cmds.el (c-outline-level): Applied patch from the Emacs + sources to make this work in invisible text. + + * cc-langs.el (c-switch-label-key): Fixed regexp to not be + confused by a later ':' on the same line as the label. + +Wed May 02 2001 Martin Stjernholm + + * cc-cmds.el, cc-mode.el (c-electric-delete, + c-electric-delete-forward): Split `c-electric-delete' into two + functions where `c-electric-delete-forward' always deletes + forward and `c-electric-delete' only contains the code + necessary for XEmacs to choose between backward and forward + deletion. `c-electric-delete-forward' is now bound to C-d to + get the electric behavior on that key too. + + * cc-mode.texi: Updated the doc for hungry-delete mode wrt the + Backspace/Delete key handling. Also incorporated a small + clarification from the Emacs people. + +Wed Mar 14 2001 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): Fixed bogus direct use of + c-comment-prefix-regexp, which caused an error when it's a + list. + +Sun Feb 25 2001 Martin Stjernholm + + * Release 5.28 + +Sun Feb 25 2001 Martin Stjernholm + + * cc-mode.el, cc-vars.el (c-common-init, c-default-style): + Removed the hardcoded switch to "java" style in Java mode. + It's instead taken care of by the default value for + c-default-style. + + * cc-mode.texi: Documented the electric keyword feature. + Updated the mentions of the "java" style special case for Java + mode. + +Sat Feb 24 2001 Martin Stjernholm + + * cc-align.el (c-lineup-math): Fix bug where lineup was + triggered by equal signs in string literals. + +Sun Feb 25 2001 Martin Stjernholm + + * cc-mode.el, cc-vars.el (c-common-init, c-default-style): + Removed the hardcoded switch to "java" style in Java mode. + It's instead taken care of by the default value for + c-default-style. + + * cc-mode.texi: Updated the mentions of the "java" style + special case for Java mode. + +Sat Feb 24 2001 Martin Stjernholm + + * cc-align.el (c-lineup-math): Fix bug where lineup was + triggered by equal signs in string literals. + +Wed Feb 21 2001 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): Fixed bug in the paragraph + limit detection when at the ends of the buffer. + + * cc-engine.el (c-guess-basic-syntax): Removed bogus check for + "for" statement clause in case 7F; a better one is done + earlier in case 7D anyway. + +Tue Feb 20 2001 Martin Stjernholm + + * cc-cmds.el (c-guess-fill-prefix): Improved the heuristics + somewhat more and did a small optimization. + +Mon Feb 19 2001 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement, c-end-of-statement): + Use the limit argument only to limit the syntactic context + search, not to limit the actual movement. + + * cc-cmds.el (c-beginning-of-statement): Move by sentence + inside multiline strings, just like in comments. Also various + fixes to the paragraph and comment prefix recognition, block + comment ender handling etc. + +Sun Feb 18 2001 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): Take more care to preserve + the relative position of the point. + + * cc-cmds.el (c-electric-continued-statement): New function to + use as abbrev hook to reindent for keywords such as "else" + that continues an earlier statement. + + * cc-menus.el (cc-imenu-c++-generic-expression): Treat structs + like classes. + + * cc-mode.el (c-mode, c++-mode, java-mode, objc-mode, + pike-mode): Populate the default abbrev tables to reindent for + keywords such as "else" that can continue earlier statements. + Abbrev mode is therefore turned on by default now. (Note that + this doesn't apply to idl-mode, since IDL afaik doesn't have + statements at all.) + +Wed Feb 14 2001 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p): Fix for handling + bracelists where the declaration contains template arguments. + +Fri Feb 09 2001 Martin Stjernholm + + * cc-cmds.el (c-comment-indent): Use + `c-get-syntactic-indentation' to correctly calculate the + syntactic indentation. Fixes bug with lineup functions that + return vectors. + + * cc-engine.el (c-get-syntactic-indentation): Split the + indentation sum calculation from `c-indent-line' to a separate + function. + +Mon Feb 05 2001 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement, c-comment-indent): + Fixed places where it was assumed that preprocessor directives + have to start in column zero. + + * cc-engine.el (c-beginning-of-member-init-list): Handle C++ + template arguments after a class identifier properly. + + * cc-engine.el (c-guess-basic-syntax): Treat initializer brace + lists for `new Foo[]' constructs in Java as expressions and + not top level definition brace lists on the top level, so that + they'll get indented consistently with the same type of + expression in a normal block. + +Sat Feb 03 2001 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): The kludge that checks + whether the adaptive filling package fails to keep the comment + prefix is now kludged further to check for filladapt-mode + which doesn't have that problem. This is really icky, but it's + the only way that works with the current misfeatures/bugs in + both adaptive-fill-mode and filladapt-mode. + + * cc-cmds.el (c-fill-paragraph): Made the way the paragraph + around point is recognized more robust. + +Sun Jan 21 2001 Martin Stjernholm + + * cc-cmds.el, cc-engine.el, cc-lobotomy.el (c-state-cache, + c-in-literal-cache, c-auto-fill-prefix, c-lit-limits, + c-lit-type): Fixed all internal variables used dynamically so + that they are always bound. + + * cc-cmds.el, cc-engine.el: Improved recovery of syntactic + errors: + + (c-indent-region): Fixed reporting of syntactic errors so that + the region is fully reindented even when an error occurs. The + last syntactic error is printed afterwards. Also cleanup up a + whole lot of code that tried to optimize indentation of whole + sexps but in reality accomplishes nothing. + + (c-indent-sexp): Use c-indent-region. + + (c-parsing-error): Changed this variable to hold the message + for any syntactic error that is discovered. + + (c-parse-state): Search backward from point instead of the bod + position when the latter is invalid. This makes CC Mode + recover faster when there are unbalanced close braces. + + (c-backward-to-start-of-if): Use c-parsing-error to report + dangling "else" clauses instead of throwing an error, and fall + back to a reasonable position. + + (c-indent-line): Added argument to avoid reporting syntactic + errors. + + (c-show-syntactic-information): Don't report any syntactic + errors. + +Wed Jan 17 2001 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement): Fixed bugs with + paragraph recognition when moving by sentence in literals. + + * cc-langs.el (c-Java-javadoc-paragraph-start): Modified + paragraph start regexp for javadoc to recognize javadoc markup + in general instead of a specific set of keywords, to be more + future-safe. + + (c-Pike-pikedoc-paragraph-start, + c-Pike-pikedoc-paragraph-separate): New regexps to recognize + pikedoc markup. + + * cc-mode.el: Fixed initialization and use of + c-current-comment-prefix. + + (pike-mode): Initialize paragraph settings pikedoc + recognition. + + * cc-vars.el (c-default-style): Made a nicer Customize widget. + + (c-comment-prefix-regexp): Made it possible to use an + association list on this to specify mode specific regexps. + The default value now use a special regexp in Pike mode to + recognize pikedoc markup. + + (c-current-comment-prefix): New variable containing the actual + regexp from c-comment-prefix-regexp for the current buffer. + +Sun Jan 14 2001 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Fixed check for special brace + lists: We can't look at the syntax, since a brace list can get + recognized as a plain statement-cont. + + * cc-engine.el (c-guess-basic-syntax): Fixed bug where a + special brace list opener broken over two lines got recognized + as a statement on the second line. Case 9A changed. + +Mon Jan 08 2001 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Fixed bug in c-state-cache + adjustment after line is reindented. + +Wed Dec 27 2000 Martin Stjernholm + + * cc-defs.el (c-point): Added optional argument for position + to use instead of the current point. + + * cc-defs.el, cc-engine.el (c-add-class-syntax): Do not add + the in-expression block symbols when the construct starts at + boi, to avoid the extra level of indentation in that case. + Cases 4, 16A and 17E affected. + +Sun Nov 26 2000 Martin Stjernholm + + * cc-cmds.el: Use `indent-according-to-mode' instead of direct + calls to `c-indent-line', to adhere better to Emacs + conventions. + + * cc-engine.el (c-indent-line): Use the syntax already bound + to `c-syntactic-context', if there is any. + +Sun Nov 19 2000 Martin Stjernholm + + * cc-engine.el (c-get-offset): Fixed bug where the indentation + wasn't added up correctly when a lineup function returned nil. + +Fri Nov 17 2000 Martin Stjernholm + + * cc-engine.el (c-collect-line-comments): Fixed bug where + empty lines were ignored when collecting line comments + backwards. + +Sun Oct 08 2000 Martin Stjernholm + + * cc-align.el (c-lineup-dont-change): Return an absolute + indentation column to work correctly in the case when several + syntactic elements are processed for the same line. + + * cc-engine.el, cc-styles.el, cc-vars.el (c-evaluate-offset, + c-get-offset, c-indent-line, c-valid-offset, c-read-offset, + c-set-offset): Added absolute indentation column settings by + using the vector type. + + * cc-mode.texi: Documented the new vector setting for offsets. + +Mon Oct 02 2000 Martin Stjernholm + + * cc-cmds.el, cc-vars.el (c-electric-paren, c-cleanup-list): + Implemented two new cleanups `space-before-funcall' and + `compact-empty-funcall'. + + * cc-mode.texi: Documented the two new cleanups + space-before-funcall and compact-empty-funcall on + c-cleanup-list. + +Sun Oct 01 2000 Martin Stjernholm + + * cc-defs.el (c-paren-re, c-identifier-re): Two new macros for + helping building regexps. + + * cc-engine.el (c-on-identifier): New function for detecting + identifiers. It takes keywords into account. + + * cc-langs.el, cc-mode.el: Added regexps for complete keyword + lists. `c-keywords' is set to a regexp matching all keywords + in the current language. + +Tue Sep 26 2000 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Added '#' to the + list of characters to skip backwards over at the beginning of + a statement, since it can precede string literals in Pike. + +Thu Aug 31 2000 Martin Stjernholm + + * cc-cmds.el (c-guess-fill-prefix): Fixed bug with prefix + recognition when standing on the last line in a C++ comment + with nothing but whitespace after the prefix. + + * cc-engine.el (c-backward-to-start-of-if): Fixed bug when + given no limit argument. + +Wed Aug 30 2000 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p): Fixed brace list + recognition for the `[]= operator symbol in Pike. + +Sat Aug 26 2000 Martin Stjernholm + + * cc-bytecomp.el (cc-eval-when-compile): New macro that works + around a bug in `eval-when-compile' in the byte compiler. + + * cc-engine.el (c-forward-token-1): Fixed bug with return + value when count is zero and there's no token start within the + limit. + + (c-guess-basic-syntax): Don't add 'comment-intro to lines with + "prefix comments", i.e. comments which are followed by code on + the same line. + + * cc-mode-19.el: Fixes so that checks that must be done at + compile time also are done then. + +Fri Aug 25 2000 Martin Stjernholm + + * cc-defs.el: Make sure cc-mode-19 is loaded both at compile + time and at runtime, and only when it's needed. + +Sun Aug 20 2000 Martin Stjernholm + + * Major cleanup for less error prone and more warning free + compilation, including some fixes for bugs due to different + compilation orders. Thanks to Martin Buchholz for providing + the basis for all this. + + cc-bytecomp.el: New file that provides some byte compilation + features: It ensures that files always are loaded from the + current source directory during compilation, and it provides a + set of macros to turn off specific compiler warnings for + specific symbols. (It's not CC Mode specific in any way.) + + Fixed a nearly acyclic dependency tree (both runtime and + compile-time) between all files. + + cc-defs.el: Separated all macros before the inline functions, + to ensure correct compilation. + + cc-defs.el, cc-engine.el: Moved c-beginning-of-macro to from + cc-defs.el to cc-engine.el and made it a function instead. + + cc-mode-19.el: Patch the byte compiler in Emacs 19 not to warn + about char-after. + + cc-vars.el: Cope even when there isn't a custom package + containing defcustom available. + + cc-make.el: Removed since it's no longer necessary. + + README: Updated installation instructions. + +Mon Aug 14 2000 Martin Stjernholm + + * cc-cmds.el, cc-langs.el, cc-mode.el: Moved around things to + improve the modularity: Moved all mode init stuff from + cc-langs.el to cc-mode.el, including the keymap + initialization; cc-langs now only contains the various + variables for configuring the language syntax. + + * cc-engine.el, cc-styles.el (c-evaluate-offset, + c-get-offset): Moved from cc-styles to cc-engine since file + dependency analysis suggests they belong there (which also + makes more sense). Thanks to Martin Buchholz for doing the + analysis. + +Sat Aug 12 2000 Martin Stjernholm + + * cc-cmds.el (c-fn-region-is-active-p): New function that + wraps the corresponding macro, for use in places that aren't + compiled. Thanks to Martin Buchholz for pointing out this. + + * cc-langs.el (c-mode-menu): Use c-fn-region-is-active-p. + + * cc-mode.el (c-prepare-bug-report-hooks): Hook variable to + add things to the bug report. + +Mon Aug 07 2000 Martin Stjernholm + + * cc-cmds.el (c-guess-fill-prefix): Fixed bug where the + returned prefix could contain a newline when the search for a + good prefix line failed. + +Sun Aug 06 2000 Martin Stjernholm + + * cc-cmds.el (c-toggle-auto-state, c-toggle-hungry-state, + c-toggle-auto-hungry-state): Made the argument optional, as + the documentation says it is. + +Sat Aug 05 2000 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Don't treat the Pike + multiline string syntax, #"...", as a cpp macro. + +Mon Jul 10 2000 Martin Stjernholm + + * Release 5.27 + +Sun Jul 09 2000 Martin Stjernholm + + * cc-engine.el (c-looking-at-inexpr-block): Replaced a call to + c-beginning-of-statement-1 that caused a bad case of recursion + which could consume a lot of CPU in large classes in languages + that have in-expression classes (i.e. Java and Pike). + + * cc-engine.el (c-guess-basic-syntax): Check for in-expression + statements before top level constructs (i.e. case 6 is moved + before case 5 and is now case 4) to catch in-expression + classes in top level expressions correctly. + +Sun Jul 02 2000 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Less naive handling of + objc-method-intro. Case 4 removed and case 5I added. + + * cc-langs.el (c-append-paragraph-start): New variable used by + c-common-init to get paragraph-start correct. + * cc-langs.el (c-common-init): Use c-append-paragraph-start to + initialize paragraph-start to make it correct both with and + without the javadoc special case. + + * cc-mode.el (java-mode): Use c-append-paragraph-start to + initialize paragraph-start for javadoc markup. + + * cc-vars.el (c-style-variables-are-local-p): Incompatible + change by defaulting this to t. It's motivated by the + confusing behavior that otherwise arise from the style system + when editing both java and non-java files at the same time + (see the comments about style setting in c-common-init). + +Tue Jun 20 2000 Martin Stjernholm + + * cc-cmds.el (c-indent-new-comment-line): Added a kludge + similar to the one in c-fill-paragraph to check the fill + prefix from the adaptive fill function for sanity. + +Mon May 01 2000 Martin Stjernholm + + * cc-defs.el (c-end-of-defun-1): Fixed forward scanning into + defun block. + +Sun Mar 19 2000 Martin Stjernholm + + * cc-mode.texi Documented the change of cpp-macro. + +Tue Mar 14 2000 Martin Stjernholm + + * cc-align.el (c-lineup-multi-inher): Handle lines with + leading comma nicely. Extended to handle member initializers + too. + + * cc-engine.el (c-beginning-of-inheritance-list, + c-guess-basic-syntax): Fixed recognition of inheritance lists + when the lines begins with a comma. + + * cc-mode.texi Updated doc for c-lineup-multi-inher. + + * cc-vars.el (c-offsets-alist): Changed default for + member-init-cont to c-lineup-multi-inher since it now handles + member initializers and indents better for leading commas. + +Sun Mar 12 2000 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Fixed some bugs in the state + handling that caused class open lines to be recognized as + statement-conts in some cases. + + * cc-cmds.el (c-indent-new-comment-line): Keep the fill prefix + guessed by the adaptive fill function unless point is on the + first line of a block comment. + + * cc-engine.el (c-forward-syntactic-ws): Fixed an infloop bug + when the buffer ends with a macro continuation char. + + * cc-engine.el (c-guess-basic-syntax): Added support for + function definitions as statements in Pike. The first + statement in a lambda block is now labeled defun-block-intro + instead of statement-block-intro. + + * cc-engine.el (c-narrow-out-enclosing-class): Whack the state + so that the class surrounding point is selected, not the one + innermost in the state. + + * cc-engine.el (c-guess-basic-syntax): Fixed bug in + recognition of switch labels having hanging multiline + statements. + + * cc-engine.el (c-beginning-of-member-init-list): Broke out + some code in c-guess-basic-syntax to a separate function. + * cc-engine.el (c-just-after-func-arglist-p): Fixed + recognition of member inits with multiple line arglists. + * cc-engine.el (c-guess-basic-syntax): New case 5B.3 to detect + member-init-cont when the commas are in funny places. + +Thu Mar 09 2000 Martin Stjernholm + + * cc-defs.el (c-auto-newline): Removed this macro since it's + not used anymore. + + * cc-engine.el (c-looking-at-bos): New helper function. + * cc-engine.el (c-looking-at-inexpr-block): More tests to tell + inexpr and toplevel classes apart in Pike. + + * cc-engine.el (c-guess-basic-syntax): Fixed bogus recognition + of case 9A. + + * cc-langs.el, cc-mode.el (c-Pike-inexpr-class-key): New + constant, since "class" can introduce an in-expression class + in Pike nowadays. + +Sun Feb 06 2000 Martin Stjernholm + + * cc-align.el (c-gnu-impose-minimum): Don't impose minimum + indentation on cpp-macro lines. + + * cc-engine.el (c-guess-basic-syntax): Made the cpp-macro + a syntax modifier like comment-intro, to make it possible to + get syntactic indentation for preprocessor directives. It's + incompatible wrt to lineup functions on cpp-macro, but it has + no observable effect in the 99.9% common case where cpp-macro + is set to -1000. + +Sat Feb 05 2000 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Fixed bug with missed + member-init-cont when the preceding arglist is several lines. + +Sat Jan 29 2000 Martin Stjernholm + + * cc-styles.el (c-style-alist): The basic offset for the BSD + style corrected to 8. + +Sun Jan 16 2000 Martin Stjernholm + + * cc-styles.el (c-style-alist): Adjusted the indentation of + brace list openers in the gnu style. + +Sun Jan 09 2000 Martin Stjernholm + + * cc-cmds.el (c-indent-command): Obey c-syntactic-indentation. + + * cc-cmds.el (c-electric-brace, c-electric-slash, + c-electric-star, c-electric-semi&comma, c-electric-colon, + c-electric-lt-gt, c-electric-paren): Don't reindent old lines + when c-syntactic-indentation is nil. + + * cc-engine.el (c-beginning-of-statement-1): Fixed bug where + we were left at comments preceding the first statement when + reaching the beginning of the buffer. + + * cc-vars.el (c-syntactic-indentation): New variable to turn + off all syntactic indentation. + +Tue Dec 28 1999 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): Keep one or two spaces + between the text and the block comment ender when it hangs, + depending on how many there are before the fill. + +Sun Dec 19 1999 Martin Stjernholm + + * cc-engine.el (c-beginning-of-closest-statement): New helper + function to go back to the closest preceding statement start, + which could be inside a conditional statement. + * cc-engine.el (c-guess-basic-syntax): Use + c-beginning-of-closest-statement in cases 10B.2, 17B and 17C. + + * cc-engine.el (c-guess-basic-syntax): Better handling of + arglist-intro, arglist-cont-nonempty and arglist-close when + the arglist is nested inside parens. Cases 7A, 7C and 7F + changed. + + * cc-langs.el (c-Java-javadoc-paragraph-start): Brought + up-to-date with javadoc 1.2. + +Fri Dec 17 1999 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Fixed handling of + multiline Pike type decls. + +Tue Dec 14 1999 Martin Stjernholm + + * cc-cmds.el (c-indent-new-comment-line): Always break + multiline comments in multiline mode, regardless of + comment-multi-line. + +Mon Dec 13 1999 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Fixed bug with + fully::qualified::names in C++ member init lists. Preamble in + case 5D changed. + +Sat Dec 04 1999 Martin Stjernholm + + * cc-langs.el (c-common-init): Handling of obsolete variables + moved to c-initialize-cc-mode. More compatible style override + when using global style variables. + * cc-mode.el (c-initialize-cc-mode): Handling of obsolete + variables moved here. + + * cc-mode.texi Documented the special behavior of + c-special-indent-hook as a style variable. Don't talk about + doing (c-make-styles-buffer-local t) in a mode hook, since + that's already too late to work right. + + * cc-styles.el (c-make-styles-buffer-local): Flag style + variable localness in c-style-variables-are-local-p to make + the compatibility measure in c-common-init work well. + + * cc-styles.el (c-set-style-1): c-special-indent-hook can no + longer contain set-from-style. + * cc-styles.el (c-initialize-builtin-style): Don't check for + set-from-style on c-special-indent-hook. + * cc-styles.el (c-copy-tree): Obsolete. The standard function + copy-alist is sufficient now. + + * cc-styles.el (c-set-style, c-set-style-1, + c-get-style-variables): Fixes to variable initialization so + that duplicate entries in styles have the same effect + regardless of DONT-OVERRIDE. + + * cc-styles.el (c-set-style-2): Fixed bug where the + initialization of inheriting styles failed when the + dont-override flag is set. + + * cc-vars.el (c-special-indent-hook): Don't use set-from-style + on this. + +Mon Nov 22 1999 Martin Stjernholm + + * cc-defs.el (c-forward-comment): Removed the workaround + introduced in 5.38 since it had worse side-effects. If a line + contains the string "//\"", it regarded the // as a comment + start since the \ temporarily doesn't have escape syntax. + +Sun Nov 21 1999 Martin Stjernholm + + * Release 5.26 + +Sun Nov 21 1999 Martin Stjernholm + + * cc-cmds.el (c-forward-conditional): Handle an arbitrary + target depth. Optionally count #else lines as clause limits, + as suggested by don provan . #elif + handling fixed. + + * (c-up-conditional-with-else, c-down-conditional, + c-down-conditional-with-else): New commands that uses the + added functionality in `c-forward-conditional'. + + * cc-mode.texi: Documented the new up/down preprocessor + conditional function varieties. + +Tue Nov 09 1999 Martin Stjernholm + + * cc-mode.texi: Updated for all the new features and + proofread. Major changes: + o All text filling and line breaking issues is collected in a + new top-level chapter. The section on auto-fill mode + interaction have been incorporated into this. + o The list of the standard lineup functions is expanded with + better explanations and examples. It's moved to a + top-level chapter since it's hard to find under Customizing + Indentation / Advanced Customizations / Custom Indentation + Functions. + o The sections on Permanent Customization and Styles are + mostly rewritten due to the changes in the style system. + The part about the mode hooks has gotten an own section. + +Tue Oct 26 1999 Martin Stjernholm + + * cc-align.el (c-lineup-comment): Preserve the alignment with + a comment on the previous line instead of preserving the + comment-column. + +Sun Sep 26 1999 Martin Stjernholm + + * Fixes to IDL mode after input from Eric Eide + : + * cc-engine.el (c-beginning-of-statement-1): Allow + `c-conditional-key' to be nil, for the benefit of IDL mode. + * cc-engine.el (c-guess-basic-syntax): Ditto. + cc-langs.el (C-IDL-class-key): Fixed. Don't match `class' + but do match CORBA 2.3 `valuetype'. + * cc-langs.el (c-IDL-access-key): New defconst. Should be nil + for IDL. + * cc-langs.el (c-IDL-conditional-key): New defconst. Should + be nil for IDL. + * cc-langs.el (c-IDL-comment-start-regexp): New defconst. + Like C++. + * cc-mode.el (idl-mode): Use new `c-IDL-*' defconsts. Also, + set `c-method-key' and `c-baseclass-key' to nil. + +Wed Aug 25 1999 Martin Stjernholm + + * cc-menus.el (cc-imenu-c++-generic-expression): Match classes + with nonhanging open braces. + +Sun Aug 15 1999 Martin Stjernholm + + * cc-align.el: Added docstrings to all lineup functions. + + * cc-align.el (c-lineup-java-throws): Handle a hanging throws + keyword. + + * cc-align.el (c-lineup-C-comments): Handle free form text + comments. Use c-comment-prefix-regexp and comment-start-skip + instead of hardcoded regexps. + +Sat Aug 14 1999 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-defun, c-end-of-defun): Fixed eob + behavior and return value as documented. + +Sat Jul 31 1999 Martin Stjernholm + + * Changes for new style variable init system: + * cc-langs.el (c-common-init): Dito. + * cc-styles.el: c-offsets-alist moved to cc-vars.el since it's + now customizable. + * cc-vars.el: Style variables may now take a value + 'set-from-style to make them take their value from the style + system. This value is now the default on all these variables. + * cc-vars.el (c-valid-offset): New function to verify a + syntactic symbol offset setting. + * cc-vars.el (c-offsets-alist): Variable moved from + cc-styles.el since it's now customizable in a similar way to + the other style variables. + * cc-vars.el (c-old-style-variable-behavior): New variable to + revert to the old style init behavior. + + * cc-vars.el (c-hanging-comment-starter-p, + c-hanging-comment-ender-p): These variables are now obsolete and + therefore removed. + + * cc-vars.el (c-file-style, c-file-offsets): Made always + buffer local. + + * cc-menus.el (cc-imenu-c++-generic-expression): Don't match + the throws clause that might follow the function prototype in + C++. + +Sat Jul 24 1999 Martin Stjernholm + + * cc-defs.el (c-beginning-of-macro): Fixed bug where point + could move forward for macros that doesn't start in column 0. + +Thu Jul 08 1999 Martin Stjernholm + + * cc-align.el (c-indent-multi-line-block, + c-lineup-whitesmith-in-block): Two new lineup functions for + use in whitesmith style. + + * cc-styles.el (c-style-alist): More fixes to whitesmith + style. It should now handle all different braces uniformly in + both hanging and non-hanging cases. + +Wed Jul 07 1999 Martin Stjernholm + + * cc-mode.texi: Documented the default behavior when a symbol + doesn't exist on c-hanging-braces-alist. + +Mon Jul 05 1999 Martin Stjernholm + + * cc-cmds.el (c-indent-exp): Use a marker to save point to + make it stay in the same position relative to the surrounding + text. + + * cc-cmds.el (c-fill-paragraph): Force the line comment prefix + when adaptive-fill-mode doesn't manage to get it correct. + + * cc-menus.el (cc-imenu-java-generic-expression): Handle types + with dotted notation, e.g. foo.bar.Gnu. + + * cc-mode.el (c-initialize-cc-mode): Wrap all function calls + within unwind-protect (previously only some were wrapped so it + would be possible to register mode initialization when full + initialization did not finish). + + * cc-styles.el (c-style-alist): Corrected the brace placement + in the whitesmith style. Thanks to Sean Luke + . Also extended the bsd and whitesmith + styles with consistent brace placement for all constructs. + +Sun Jul 04 1999 Martin Stjernholm + + * cc-cmds.el (c-context-line-break): Continue C++ comments too + when point is in the middle of them. + + * cc-cmds.el: Line breaking and paragraph filling code + rewritten: + (c-guess-fill-prefix): New function that uses various + heuristics to guess the comment prefix. + (c-fill-paragraph): Rewritten to use `c-guess-fill-prefix'. + It now assumes adaptive filling is active to preserve the line + prefix inside comments. + (c-indent-new-comment-line): Replacement for the now + obsolete `c-comment-line-break-function' that uses + `c-guess-fill-prefix' when appropriate. It now observes the + setting of `comment-multi-line', which has effect in C-style + block comments. + + * cc-cmds.el (c-context-line-break): New function intended to + be put on RET. It's essentially `newline-and-indent', but + continues C block comments with the appropriate line prefix. + + * cc-cmds.el (c-do-auto-fill): New function put on + `normal-auto-fill-function' to implement the + `c-ignore-auto-fill' variable. + + * cc-cmds.el (c-beginning-of-statement): Use + `c-comment-prefix-regexp' to avoid ending up inside the + comment prefix. Better handling of comment starters and + enders. Catch comments better when traversing code. Stop at + preprocessor directives. + + * cc-defs.el (c-forward-comment): New subst to hide platform + dependent quirks in `forward-comment'. + + * cc-engine.el (c-literal-limits): Added NOT-IN-DELIMITER + argument. + (c-literal-limits-fast): Implemented NEAR and NOT-IN-DELIMITER + arguments. Activate this function by default when + `parse-partial-sexp' supports it (currently Emacs 20.x). + + * cc-engine.el (c-guess-basic-syntax): Anchor the `c' syntax + on the comment opener to make constants usable as lineup + arguments. + + * cc-align.el (c-lineup-C-comments): Fixes to handle the + changed anchor position in the `c' syntactic symbol. Handle + more than stars in the comment prefix; use the new variable + `c-comment-prefix-regexp'. Don't indent text not preceded by + a comment prefix to the right of the comment opener if it's + long. + + * cc-langs.el: Fixes to mode initialization for new line + breaking and paragraph filling method. Adaptive fill mode is + now activated at startup instead of deactivated. The + variables used for adaptive filling and paragraph movement are + also changed to incorporate the value of + `c-comment-prefix-regexp'. `substitute-key-definition' is + used to override some functions in the global map instead of + overriding their default bindings. + + * cc-mode.el (java-mode): Modify `paragraph-start' for the + javadoc markup at mode init. + + * cc-mode.el (c-setup-filladapt): A new convenience function + to configure Kyle E. Jones' Filladapt mode for CC Mode. This + function is intended to be used explicitly by the end user + only. + + * cc-vars.el (c-comment-prefix-regexp): New variable used to + recognize the comment fill prefix inside comments. + (c-block-comment-prefix): New name for + `c-comment-contiuation-stars', which is now obsolete. It's + generalized to handle any character sequence. + (c-ignore-auto-fill): New variable used to selectively disable + Auto Fill mode in specific contexts. + +Tue Jun 29 1999 Martin Stjernholm + + * cc-cmds.el (c-comment-indent): Leave at least one space + between the comment and the last nonblank character in the + case where we look at the indentation of the comment on the + previous line (case 4). + + * cc-engine.el (c-beginning-of-statement-1): Added ``' to the + list of characters that may start a statement (it's a sort of + prefix operator in Pike, and isn't used at all in any of the + other languages). + +Tue Jun 15 1999 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Report brace list opens + inside continued statements as statement-cont instead of + brace-list-open. The reason is that one normally adjusts + brace-list-open for brace lists as top-level constructs, and + brace lists inside statements is a completely different + context. Case 10B.2 changed. Also changed (the somewhat + esoteric) case 9A to cope with this. + +Sat May 29 1999 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Added electric handling of + the open brace for brace-elseif-brace. + +Thu May 27 1999 Martin Stjernholm + + * cc-defs.el (c-with-syntax-table): New macro to easily switch + syntax tables temporarily. + + * cc-engine.el (c-guess-basic-syntax): Handle template and + member init argument lists split over several lines. Case 5D + changed. + + * cc-langs.el (c-Java-javadoc-paragraph-start): Added new tag + @throws introduced in Javadoc 1.2. + + * cc-menus.el (cc-imenu-java-generic-expression): Applied + patch from RMS to avoid infinite backtracking. + +Sun May 16 1999 Martin Stjernholm + + * cc-align.el (c-lineup-arglist): Handle "arglists" surrounded + by [ ]. + +Sat May 15 1999 Martin Stjernholm + + * cc-align.el (c-lineup-dont-change): Compensate properly for + the column in langelem. + + * cc-engine.el (c-syntactic-information-on-region): New + function to help debugging the syntactic analysis. + +Mon May 03 1999 Martin Stjernholm + + * cc-align.el (c-lineup-template-args): Handle nested template + arglists. + + * cc-langs.el (c++-template-syntax-table): New syntax table + that makes `<' and `>' parenthesis characters, which is useful + to switch to temporarily when analyzing template arglists. + + * cc-styles.el: Changed default alignment of labels in the + java style to conform to the examples in the Java Language + Specification. + + * cc-styles.el (c-offsets-alist): Use `c-lineup-template-args' + by default. + +Fri Mar 12 1999 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Pike allows a comma + immediately before the closing paren in an arglist, so don't + check that in Pike mode. Case 7A changed. + +Sat Mar 06 1999 Martin Stjernholm + + * cc-cmds.el (c-indent-region): Fixed bug where comment-only + lines were ignored under certain conditions. + +Fri Mar 05 1999 Martin Stjernholm + + * cc-align.el (c-lineup-template-args): New function for + aligning continued template argument lists. + + * cc-engine.el (c-guess-basic-syntax): Fix for member init + lists containing function arglists split over several lines. + Case 5D.1 changed. + + * cc-engine.el (c-guess-basic-syntax): Fixed bug where + template-args-cont didn't get recognized when the first + arglist opener line doesn't contain a template argument. New + case 5K. + +Sat Feb 27 1999 Martin Stjernholm + + * cc-defs.el (c-point): Changed from subst to macro for + efficiency. + (c-beginning-of-defun-1, c-end-of-defun-1): New + beginning-of-defun/end-of-defun wrappers separated from + c-point. + + * cc-menus.el (imenu-generic-expression, + imenu-case-fold-search, imenu-progress-message): Dummy + definitions to avoid compiler warnings if imenu can't be + loaded. + * cc-menus.el (cc-imenu-init): New function called at mode + init. + * cc-mode.el (c-mode, c++-mode, objc-mode, java-mode): Moved + imenu initializations to cc-imenu-init. + +Sun Feb 21 1999 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Slightly better check + for lambda-intro-cont in Pike mode. Case 6 changed. + + * cc-engine.el (c-looking-at-inexpr-block): Fixed bug where + anything following "new Foo()" was considered an anonymous + class body in Java mode. + +Fri Feb 12 1999 Barry A. Warsaw + + * cc-cmds.el (c-comment-line-break-function): When breaking in + a string, don't insert a new line. + +Sun Jan 31 1999 Barry A. Warsaw + + * cc-engine.el (c-at-toplevel-p): New interface function which + returns information useful to add-on authors. It tells you + whether you're at a toplevel statement or not. + +Tue Dec 22 1998 Barry A. Warsaw + + * cc-cmds.el (c-comment-line-break-function): It is possible + that forward-line does not land us at the bol, say if we're on + the last line in a file. In that case, do a + back-to-indentation instead of a forward-comment -1. + +Fri Dec 11 1998 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Don't catch + "default:" as normal label in case 4. + +Thu Dec 10 1998 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Use c-bitfield-key to + recognize continued bitfield declarations. Case 5D.1 changed. + * cc-langs.el: New variable c-bitfield-key. + * cc-mode.el: New variable c-bitfield-key. + +Wed Dec 09 1998 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p): Tighter test for Java + anonymous array expressions (i.e. "new Foo[] {.. bracelist + ..}"). + +Sun Dec 6 1998 Martin Stjernholm + + * Release 5.25 + +Mon Nov 18 1998 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Fixed some bugs with + comments with tricky contents in obscure places inside + bracelists. Cases 5A.3 and 9C-D changed. + +Mon Nov 11 1998 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p): Don't trip up on C++ + "operator[]". + +Mon Oct 31 1998 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Fixed bug where + point would end up further down afterwards. Recognize '@' as + a prefix operator for Pike. + +Mon Oct 24 1998 Barry A. Warsaw + + * cc-defs.el (c-major-mode-is): New defsubst to encapsulate + major-mode checking. + + * cc-cmds.el, cc-engine.el, cc-lang.el: All major-mode + checking is now spelled (c-major-mode-is 'mode) + +Mon Oct 23 1998 Barry A. Warsaw + + * cc-cmds.el (c-comment-indent): CASE 3: the looking-at should + match against c-comment-start-regexp instead of comment-start. + + * cc-engine.el (c-inside-bracelist-p): Further + dekludgification. When in C++ mode and searching to see if + we're in a template definition, don't get tripped up by + #include syntax! + + * cc-mode.el (c-submit-bug-report): Add comment-column to list + of variables reported. + +Mon Oct 20 1998 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1): Do not trip on + whitespace when skipping backwards over characters that can + start a statement. + +Mon Oct 17 1998 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p): Check for class open in + Pike mode. + +Mon Oct 16 1998 Barry A. Warsaw + + * cc-langs.el (c-common-init): Make adaptive-fill-mode a + buffer local variable and set it to nil. + +Mon Oct 15 1998 Barry A. Warsaw + + * cc-langs.el (c-common-init): Implement the new semantics for + c-default-style. + + * cc-mode.texi: Document the new semantics for c-default-style. + + * cc-vars.el (c-default-style): Slightly different default + semantics when the value is an alist, and there's a new + special symbol in the choices: `other'. This is used when the + major-mode is not specifically listed. + +Wed Oct 14 22:34:50 1998 Barry A. Warsaw + + * Release 5.24 + +Thu Oct 08 1998 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Added inexpr-class-open and + inexpr-class-close handling. + + * cc-vars.el (c-hanging-braces-alist): Added inexpr-class-open and + inexpr-class-close and changed the default setting for those two. + +Wed Oct 07 1998 Barry Warsaw + + * cc-cmds.el (c-electric-delete): Use function delete-forward-p if + it exists. This is the blessed XEmacs 21 way of checking for this + condition. + +Wed Sep 16 1998 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): CASE 15: Handle labels at + beginning of blocks with hanging braces. + +Tue Sep 08 1998 Barry Warsaw + + * Bug reporting address is now bug-cc-mode@gnu.org + +Mon Aug 31 1998 Barry Warsaw + + * cc-defs.el (c-region-is-active-p): New function which + encapsulates region activeness determination in both XEmacs and + Emacs, regardless of whether region highlighting + (e.g. zmacs-regions / transient-mark-mode) is turned on. + + * cc-langs.el (c-mode-menu): Use c-region-is-active-p so + appropriate menu entries are active correctly across all + X/Emacsen. + + * cc-vars.el Added definition of `other' widget type, which allows + any value other than t or nil, but doesn't let the user type in + any old thing. This is used in c-tab-always-indent as per Per's + recommendation. + +Fri Aug 28 1998 Barry Warsaw + + * cc-langs.el (c-use-java-style): Removed as obsolete. + + (c-common-init): Implement the new semantics for + c-default-style. Should be backwards compatible with old behavior, + but allow for per-major-mode setting of the default style. + + * cc-mode.el (java-mode): No longer hard code the style setting to + "java" style. This is now all handled by the new semantics for + c-default-style. + + * cc-styles.el (c-initialize-builtin-style): No longer call + c-set-style to set the default style. This is all handled by the + new semantics for c-default-style. + + * cc-vars.el (c-default-style): This variable can now take either + a string or an association list, mapping major mode symbols to + style names. Update the docstring to describe the new interface, + and elaborate the Custom widget to accept either type. + +Thu Aug 27 1998 Barry Warsaw + + * cc-styles.el (c-offsets-alist): The offset for a syntactic + symbol can now also be a list, which is recursively evaluated + using the previous semantics. The first non-nil value succeeds. + + (c-get-offset, c-evaluate-offset): Function to implement recursive + evaluation for when a symbol's offset is a list (the first one to + return a non-nil value succeeds -- should this be a stricter check + for an integer return value?). Factored out of c-get-offset. + + (c-set-offset, c-read-offset): Error message indicates value could + be a list. In former function, add listp check. + + * cc-vars.el (c-strict-syntax-p): Describe addition responsibilities. + +Mon Aug 24 1998 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p, c-guess-basic-syntax): In + Java brace lists may follow the new operator. Do not recognize + them as in-expression statements. Case 7B changed in + c-guess-basic-syntax. + +Sun Jun 07 1998 Martin Stjernholm + + * cc-engine.el (c-beginning-of-statement-1, c-guess-basic-syntax): + Fixed indentation of try-catch-finally blocks nested inside + if-statements. New case 13 in c-guess-basic-syntax; cases 13-16 + renamed for this. New syntactic symbol catch-clause. + + * cc-styles.el New syntactic symbol catch-clause. Changed the + default to not alter the indentation of multiline strings in any + way. + +Sat Jun 06 1998 Martin Stjernholm + + * cc-langs.el Added recognition of IDL specific top-level keywords. + +Tue May 19 1998 Martin Stjernholm + + * cc-engine.el (c-search-uplist-for-classkey, + c-looking-at-inexpr-block, c-guess-basic-syntax): Fixed bug in + recognizing anonymous Java classes. Cleanups in the code that + handles in-expression brace constructs. + +Sun May 03 1998 Martin Stjernholm + + * cc-engine.el (c-inside-bracelist-p): Rewrote the `=' detection + loop to make it more clear and in some cases a lot + faster. + + (c-forward-token-1, c-backward-token-1): Use narrowing for limits + to improve speed when the limit is inside a huge balanced paren. + +Mon Apr 27 14:54:33 1998 Barry A. Warsaw + + * Release 5.23 + + * (c-electric-pound): Do electric stuff only if # is hit at the + beginning of the line. + +Mon Apr 27 1998 Martin Stjernholm + + * cc-align.el (c-lineup-math): Indent with c-basic-offset if the + equal sign ends the first line. + +Thu Apr 23 1998 Martin Stjernholm + + * cc-align.el, cc-cmds.el, cc-compat.el, cc-engine.el: Use + c-{forward,backward}-sexp instead of {forward,backward}-sexp. + +Mon Apr 20 1998 Barry Warsaw + + * cc-engine.el (c-inside-bracelist-p): Don't recognize operator=() + method definitions as bracelists. + +Sun Apr 19 1998 Barry Warsaw + + * cc-styles.el (c-style-alist): In "gnu" style, set inline-open + offset to zero. + +Thu Apr 16 1998 Martin Stjernholm + + * cc-cmds.el (c-electric-brace): Check for and exclude Pike-style + brace lists from the auto-newline feature. + +Wed Apr 15 1998 Martin Stjernholm + + * cc-cmds.el (c-electric-paren): New function for electric + auto-indenting behavior for parenthesis. + +Tue Apr 14 1998 Barry Warsaw + + * cc-mode.el (c-submit-bug-report): Don't include + c-special-indent-hook iff hook is of length 1 and contains only + c-gnu-impose-minimum. + +Mon Apr 13 1998 Martin Stjernholm + + * cc-engine.el (c-add-class-syntax): New function that handles all + inclass and related symbols in one place. The anchor position of + inclass has changed in some situations. + +Sun Apr 12 1998 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement): Handle blocks inside + expressions. + +Wed Apr 08 1998 Barry Warsaw + + * cc-cmds.el (c-mark-function): Much better implementation which + catches all the expected cases. + + (c-end-of-defun): When called programmatically with no arguments, + arg is nil, so set it to 1. + + * cc-defs.el (c-point): Added 'eod. + +Mon Apr 06 1998 Martin Stjernholm + + * cc-engine.el (c-search-uplist-for-classkey, + c-inside-bracelist-p, c-looking-at-inexpr-block, + c-guess-basic-syntax): Support for Java anonymous classes. New + case 6D in c-guess-basic-syntax. + + * cc-langs.el, cc-mode.el, cc-styles.el: Support for Java + anonymous classes. New syntactic element inexpr-class. + +Sun Apr 05 1998 Martin Stjernholm + + * cc-align.el (c-lineup-inexpr-stat): Added lineup of statements + inside expressions. + + * cc-engine.el (c-inside-bracelist-p, c-looking-at-inexpr-stat, + c-guess-basic-syntax): Added recognition of the gcc extension for + statements inside expressions. They're handled as + `inexpr-statement' now. Changed cases: 6, 10, 15A, 16E. New case + 7B; old 7B-F renumbered. + +Fri Apr 03 1998 Barry Warsaw + + * cc-cmds.el (c-electric-brace): Removed brace-list-entry from the + list of symbols that can be electrified because all cases where + brace-list-entry was used should now be brace-entry-open's. Add + new brace-entry-open to list of braces which can be electrified. + + * cc-engine.el (c-guess-basic-syntax): CASE 9C: brace-list-open => + brace-entry-open. + + * cc-styles.el (c-style-alist): In "linux" and "python" styles, + add brace-entry-open to mimic brace-list-open. Added description + and entry for brace-entry-open, a new syntactic symbol. + + * cc-vars.el (c-hanging-braces-alist): Added brace-entry-open to + mimic brace-list-open in default value. Updated docstring and + defcustom spec to describe brace-entry-open and remove + brace-list-entry. + +Thu Apr 02 1998 Martin Stjernholm + + * cc-align.el (c-lineup-inexpr-stat): New lineup function used in + Pike mode. + + * cc-langs.el: New variables c-lambda-key and + c-special-brace-lists for Pike. + + * cc-styles.el: New syntactic symbols inlambda, lambda-intro-cont, + and inexpr-statement for Pike. + + * cc-engine.el: Support for the Pike language. Handle Pike-style + brace lists ('({ })', '([ ])', '(< >)') and in-expression + statements. New case 6 in c-guess-basic-syntax; CASES >= 6 ARE + RENAMED because of this. New functions: + c-looking-at-special-brace-list, c-looking-at-inexpr-stat, + c-looking-at-inexpr-stat-backward. + + * cc-mode.el (pike-mode): New function; support for the Pike language. + +Tue Mar 31 1998 Martin Stjernholm + + * cc-cmds.el (c-comment-line-break-function): Insert newline when + in a string literal. + +Fri Mar 27 1998 Barry Warsaw + + * cc-defs.el (c-forward-sexp, c-backward-sexp): Implementations of + replacement defsubst to insulate ourselves from changes to + forward-sexp and backward-sexp user level command. + + * cc-styles.el (c-read-offset): A better prompt which includes the + syntactic symbol being changed. + +Wed Mar 18 1998 Barry Warsaw + + * cc-cmds.el (c-indent-line-or-region): New command. Remove `*' + from interactive spec. + + * cc-langs.el (c-mode-menu): Change "Indent Line" to "Indent Line + or Region". + +Mon Mar 16 19:13:24 1998 Barry A. Warsaw + + * Release 5.22 + +Thu Mar 12 1998 Barry Warsaw + + * cc-menus.el (cc-imenu-c++-generic-expression): Fix to handle + explicitly specialized template classes. + + * cc-mode.texi: Added a paragraph on + signal-error-on-buffer-boundary in the Limitations and Known Bugs + section. + +Wed Mar 11 1998 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Fixed bug with member inits + on the same line as the function header. Case 5D.1 changed. + +Wed Mar 11 1998 Barry Warsaw + + * cc-mode.el (c-submit-bug-report): Add + signal-error-on-buffer-boundary to the list of variables that get + reported. This is a losing XEmacs variable that breaks many + things and should never be set by the user. + +Fri Mar 6 00:25:29 1998 Barry A. Warsaw + + * Release 5.21 + +Sat Feb 28 1998 Martin Stjernholm + + * cc-mode.el (c-initialize-on-load): Variable removed. + +Sat Feb 28 1998 Barry Warsaw + + * cc-engine.el (c-inside-bracelist-p): Fix for enum test. + +Fri Feb 27 1998 Martin Stjernholm + + * cc-mode.el (c-initialize-cc-mode): Moved require's to top level. + +Wed Feb 25 1998 Martin Stjernholm + + * cc-cmds.el (c-fill-paragraph): Always keep point in the same + relative position. Fill comment before point if there's nothing + else on the same line. Fill block comments after code a little + better. Try harder to find a good fill-prefix when point is on a + block comment ender line. Use c-Java-javadoc-paragraph-start in + block comments in Java mode. Leave block comment ender alone when + c-hanging-comment-ender-p is nil and point is on that line. + Detect paragraph-separate in multiparagraph comments. Fix for bug + that may strip the `*' off `*/' if fill-prefix ends with `*' and + c-hanging-comment-ender-p is t. Added filling of multiline string + literals. Always return t to disable filling in any unhandled + area, i.e. actual code where fill-paragraph only mess things up. + +Tue Feb 24 1998 Martin Stjernholm + + * cc-engine.el (c-collect-line-comments): Require same comment + start column. + + * cc-langs.el Added c-Java-javadoc-paragraph-start for use in + c-fill-paragraph. + +Tue Feb 24 1998 Barry Warsaw + + * cc-cmds.el (c-fill-paragraph): Bind fill-paragraph-function to + nil when calling fill-paragraph to avoid bogus recursion which + will signal an error. + +Sat Feb 21 1998 Martin Stjernholm + + * cc-engine.el (c-guess-basic-syntax): Fixes for nesting of and + repeated defun-open's inside extern and namespace clauses. This + is done by passing a relpos to 'inextern-lang and 'innamespace. + Also, the relpos in 'defun-open is no longer always bol. It's + always bol when on the top level, however. Changed cases: 5A.5, + 5I, 14A. + +Thu Feb 19 1998 Martin Stjernholm + + * cc-engine.el (c-forward-token-1, c-backward-token-1): New + functions to move by tokens. + + (c-guess-basic-syntax): Fixes for Java 1.1 array initialization + brace lists. + +Tue Feb 17 1998 Martin Stjernholm + + * cc-mode-19.el: Only define the functions if they aren't defined + already. + +Tue Feb 10 1998 Martin Stjernholm + + * cc-make.el: Require cc-mode-19 if needed before batch compile, + because it contains macro definitions that must be defined during + compilation. + +Sun Feb 8 15:30:43 1998 Barry A. Warsaw + + * Release 5.20 + +Wed Feb 04 1998 Barry Warsaw + + * cc-mode.el (c-mode, c++-mode, objc-mode, java-mode): set + imenu-case-fold-search to nil. + +Tue Feb 03 1998 Barry Warsaw + + * cc-langs.el (c-postprocess-file-styles): If a file style or file + offsets are set, make the variables local to the buffer (via + make-local-variable). + + * cc-styles.el (c-make-styles-buffer-local): Take an optional + argument which switches between make-variable-buffer-local and + make-local-variable. Generalize. + +Mon Feb 02 1998 Martin Stjernholm + + * cc-align.el (c-lineup-close-paren, c-indent-one-line-block): New + indentation functions. + + * cc-cmds.el (c-beginning-of-statement, c-end-of-statement): Do + not move by sentence in strings. Doc fixes. + + * cc-mode.texi: Document new indentation functions. + +Sat Jan 24 1998 Barry Warsaw + + * cc-defs.el (c-point): In XEmacs, use scan-lists + + buffer-syntactic-context-depth to radically speed up locating + top-level defun opening brace in some situations. When the braces + hang, this can make c-parse-state from between 3 to 60 times + faster. When they don't hang, this may be a few percentage points + slower (not noticeable to me though). The variable + c-enable-xemacs-performance-kludge-p toggles the behavior. This + change has no effect on Emacs, which lacks the built-in function + buffer-syntactic-context-depth. + + * cc-mode.texi: Discuss c-enable-xemacs-performance-kludge-p in + the section on performance. + + * cc-vars.el (c-enable-xemacs-performance-kludge-p): New variable. + +Fri Jan 23 1998 Barry Warsaw + + * cc-cmds.el cc-defs.el cc-engine.el (c-beginning-of-defun, + c-indent-defun, c-parse-state): Use (c-point 'bod) instead of + beginning-of-defun directly. + +Tue Jan 20 1998 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement): Speedup; it's only + necessary to call `c-literal-limits' once when the function is + entered. + +Mon Jan 19 1998 Barry Warsaw + + * cc-align.el (c-semi&comma-no-newlines-before-nonblanks, + c-semi&comma-no-newlines-for-oneline-inliners): New functions, + appropriate for c-hanging-semi&comma-criteria, but not placed on + that variable by default. + + * cc-langs.el (c-mode-base-map): Comment out c-beginning-of-defun + and c-end-of-defun bindings, since RMS doesn't want these to be + the default. + + * cc-mode.texi: Describe c-beginning-of-defun and c-end-of-defun. + Describe the new c-hanging-semi&comma-criteria functions. + +Sun Jan 18 1998 Martin Stjernholm + + * cc-cmds.el (c-beginning-of-statement): Handle multiple C++ line + comments a little better. + + Almost completely rewritten. It's now more thorough when handling + strings and comments and the transitions between them and the + surrounding code. The statement parsing is also rewritten because + `c-{beginning|end}-of-statement-1' does no longer do what we want + in this function (e.g. c-b-o-s-1 doesn't go into blocks). It also + works better for different counts and when sentence-flag is nil. + + * cc-engine.el (c-forward-syntactic-ws, c-backward-syntactic-ws): + Removed the narrowings which doesn't seem to have much effect. + Instead a simple check is made against the given limit. In + `c-backward-syntactic-ws' this means that there's no need to + search for bod, which helps up speed quite a lot in some areas. + + (c-collect-line-comments): New function that given the limits of + one C++ style line comment returns the range for all adjacent line + comments. This functionality is moved from the functions + `c-literal-limits' and `c-literal-limits-fast'. + + (c-literal-limits): New function that finds the start and end pos + of a comment or string surrounding point. This function is Emacs + 19.34 compatible and it has a workaround for what seems to be a + bug in `parse-partial-sexp' when we use an existing state to get + the state for the very next character. + + (c-literal-limits-fast): A faster variant of `c-literal-limits' + for newer Emacsen where the state returned from + `parse-partial-sexp' contains the starting pos of the last + literal. This does not contain the workaround described above. + The function is not yet tested and therefore not in use for now. + Note that these functions regard the position between the first + and second char of a comment starter to be part of the comment. + Although `parse-partial-sexp' (in Emacs 19 anyway) doesn't do + this, it seems more intuitive to me. Maybe `c-in-literal' should + do this too? + +Thu Jan 15 1998 Martin Stjernholm + + * cc-mode-19.el: Added `when' and `unless'. + +Thu Jan 15 1998 Barry Warsaw + + * cc-engine.el (c-guess-basic-syntax): Fixed a few byte compiler + warnings. + +Wed Jan 14 1998 Barry Warsaw + + * cc-cmds.el (c-beginning-of-defun, c-end-of-defun): New commands + which mimic the standard built-ins, but do a much better job of + finding the open brace when it's hung on the right side (as is the + case with the most common Java style). + + * cc-engine.el (c-backward-to-start-of-do): Break infloop for + illegal code, e.g. when someone types while (TRUE) { at the top of + a buffer, we shouldn't hang when the { is typed! + +Tue Jan 13 1998 Barry Warsaw + + * cc-cmds.el (c-beginning-of-statement): When moving forward by + sentences, because we're either inside or at the start of a + comment, be sure to limit movement to only within the extent of + the comment. + +Sat Jan 10 1998 Barry Warsaw + + * cc-langs.el (c-java-method-key): I really don't remember why + this was added, but it seems to do more harm than good. Besides, + its value was clearly wrong, being inherited from Objective-C. + + * cc-mode.el (java-mode): Set c-method-key to nil. I don't think + this is necessary for Java, and besides, the old value was + inherited from Objective-C which was clearly not right. With this + change, all regression tests pass and the example by Bengt + Martensson also passes: + + class Baz + { + int blah() + { + return 1 + + 2 + + 3 + + foobar() + + 5 + + 6; + } + } + + * cc-mode.texi Add some explanation to "gnu" style and "user" + style, describing the relationship between these and user + Customizations. + + * cc-vars.el (c-default-style): Change this back to "gnu" after + (re-reading old) discussions with RMS. This may confuse users who + set variables in the top-level of their .emacs files, or using the + Custom interface, since those changes will get incorporated into + the "user" style. RMS insists, however, that the default style be + "gnu". + +Sun Jan 04 1998 Barry Warsaw + + * cc-cmds.el (c-electric-colon): Newlines should not be inserted + before or after scope operators, regardless of the value of + c-hanging-colons. + + * cc-engine.el (c-backward-to-start-of-if): Workaround a nasty to + track down bug. If point is < lim, then this function can + actually land you forward into the buffer. This can cause an + infloop in c-beginning-of-statement-1. It is probably a bug that + this function gets called with a lim > point, but that's even + harder to figure out, so if that's the case when this function is + called, it's simpler just to ignore lim and use bod. This breaks + the infloop without causing broken indentation. + +Sat Jan 03 1998 Barry Warsaw + + * cc-align.el (c-lineup-dont-change): New lineup function that + leaves the current line's indentation unchanged. Used for the new + cpp-macro-cont syntactic symbol. + + * cc-cmds.el (c-electric-brace): namespace-open and + namespace-close braces can hang. + + * cc-defs.el (c-emacs-features): Added autoload cookie which Steve + Baur claims is necessary for XEmacs. + + * cc-engine.el (c-search-uplist-for-classkey): When searching up + for a class key, instead of hardcoding the extended search for + "extern", use the new variable c-extra-toplevel-key, which is + language dependent. For C++, this variable includes the keyword + "namespace" which will match C++ namespace introducing blocks. + + (c-guess-basic-syntax): Support for recognizing C++ namespace + blocks, by elaborating on the mechanism used to find external + language blocks. Searches which hardcoded "extern" now use + c-extra-toplevel-key, a language dependent variable. Case clauses + that were modified: CASE 5A.1, CASE 5A.4, CASE 5F, CASE 5I, CASE + 14A. + + CASE 3: we can now determine whether we're at the beginning of a + cpp macro definition, or inside the middle of one. Set syntax to + 'cpp-macro in the former case, 'cpp-macro-cont in the latter. In + both cases, the relpos is the beginning of the macro. + + (c-forward-syntactic-ws): Added code that skips forward over + multi-line cpp macros. + + (c-beginning-of-macro): Moved, and made into a defsubst. This + function can now actually find the beginning of a multi-line C + preprocessor macro. + + (c-backward-syntactic-ws): Use c-beginning-of-macro to skip + backwards over multi-line macro definitions. + + (c-in-literal, c-fast-in-literal): Use c-beginning-of-macro to + find out whether we're in a multi-line macro definition. + + * cc-langs.el (c-C-extra-toplevel-key, c-C++-extra-toplevel-key, + c-extra-toplevel-key): New variables which parameterize the search + for additional top-level enclosing constructs. In all languages, + extern lang blocks are supported (but maybe this should just be C + and C++?). In C++, also namespace blocks are supported. + + * cc-menus.el Imenu patches by Masatake Yamato and Jan Dubois. + + * cc-mode.el (c++-mode): Set c-extra-toplevel-key to + c-C++-extra-toplevel-key. + + (c-initialize-on-load): New variable, *not* customized. When set + to t -- the default -- c-initialize-cc-mode is called when the + cc-mode.el file is loaded, e.g. via (require 'cc-mode). This is + backwards compatible with .emacs files that used CC Mode 4. I'm + still not 100% sure this is the right thing to do. + + * cc-mode.texi: Added descriptions of the new C++ namespace + syntactic symbols: namespace-open, namespace-close, innamespace. + Added an example for this and also multi-line macros. + + Describe c-lineup-dont-change and the new cpp-macro-cont syntactic + symbol. Remove the `known limitation' that multi-line macros + aren't supported. + + * cc-styles.el (c-offsets-alist): Three new syntactic symbols: + innamespace, namespace-open, namespace-close. These support C++ + namespace blocks. + + Added new syntactic symbol cpp-macro-cont, by default bound to + c-lineup-dont-change. This symbol is assigned to subsequent lines + of a multi-line C preprocess macro definition. + + * cc-vars.el (c-default-style): Variable is user customizable so + it's docstring should start with a `*'. + +Fri Jan 02 1998 Barry Warsaw + + * cc-engine.el (c-fast-in-literal): Function which should be + faster than c-in-literal. This uses buffer-syntactic-context + which is a speedy built-in that exists only in XEmacs. Make it's + alias conditional on that built-in's existance. To be honest, the + performance effects should be tested. Also c-fast-in-literal + knows about multi-line cpp macros while c-in-literal does not. + The latter should be taught about this, but this change will wait + for a future mega-patch to handle multi-line macros. + +Thu Jan 01 1998 Barry Warsaw + + * cc-cmds.el (c-comment-line-break-function): When breaking a + line-oriented comment, copy the comment leader from the previous + line instead of hardcoding it to "// ". This ensures that + whitespace between the slashes and the text is preserved. + +Tue Nov 18 1997 Barry Warsaw + + * cc-langs.el (c-mode-base-map): Bind c-mark-function using a + portable representation of C-M-h that differentiates this from + M-BS on both XEmacs and Emacs. + +Sat Nov 15 1997 Barry Warsaw + + * cc-cmds.el (c-electric-pound, c-electric-brace, + c-electric-slash, c-electric-star, c-electric-semi&comma, + c-electric-colon, c-electric-lt-gt, c-scope-operator, + c-indent-command, c-indent-exp, c-indent-defun, + c-backslash-region, c-fill-paragraph): Added "*" to interactive + spec to barf-if-buffer-read-only. + +Fri Nov 14 1997 Barry Warsaw + + * cc-cmds.el (c-fill-paragraph): regexp-quote the fill-prefix when + search forward for the end of line oriented comments. This is in + case the fill-prefix contains regexp special characters + (e.g. fill-prefix == " //* ") + + (c-backslash-region): Do not preserve the zmacs region (XEmacs). + +Wed Nov 12 1997 Barry Warsaw + + * cc-langs.el (c-mode-base-map): c-mark-function moved back to + M-C-h. RMS says: "It ought to be on M-C-h, because that is the + key to mark one function definition in whatever language you're + using." I don't remember why it was moved in the first place. + +Tue Nov 04 1997 Barry Warsaw + + * cc-cmds.el (c-electric-backspace, c-electric-delete): + Interactive spec should have a read-only *. + +Thu Oct 30 1997 Barry Warsaw + + * cc-styles.el (c-styles-alist): Merged "jdk" into "java" style + and removed "jdk" style. Only differences now are inline-open and + c-basic-offset. + +Wed Oct 29 1997 Barry Warsaw + + * cc-mode.texi Document "jdk" style. + + * cc-styles.el (c-style-alist): "jdk" style given by Martin + Buchholz for conformance with Sun's JDK style. + +Fri Oct 10 1997 Barry Warsaw + + * cc-styles.el (c-set-style-2, c-initialize-builtin-style): Don't + special case "cc-mode", it's a derived style. + + Fix setup of derived style "cc-mode". + + Introduce the new default style "user" which contains all user + customizations. The style "cc-mode" is retained as an alias, but + it's use is deprecated. The default style variable has been + renamed c-default-style. + + * cc-vars.el (c-site-default-style): Renamed to c-default-style. + Also, the default value is now "user". + +Mon Oct 6 19:12:51 1997 Barry A. Warsaw + + * Release 5.19 + +Mon Oct 6 19:09:17 1997 Barry A. Warsaw + + * cc-engine.el (c-guess-basic-syntax): + CASE 5F: extern-lang-close relpos should be + element 0 of inclass-p, not element 1. + + * cc-cmds.el (c-progress-init, c-progress-fini): + Be slient if c-progress-interval + is nil. + + * cc-vars.el (c-progress-interval): Document new semantics + +Fri Oct 3 23:10:04 1997 Barry A. Warsaw + + * cc-engine.el (c-beginning-of-statement-1): + Watch out for keywords which have a + preceding underscore. + +Fri Sep 26 23:30:58 1997 Barry A. Warsaw + + * cc-menus.el: Patches to Imenu support given by + "Masatake (jet) YAMATO" . + (Jan Dubois) jan.dubois@ibm.net + + * cc-cmds.el (c-comment-line-break-function): + Fix for when comment starts at + comment-column and there is non-whitespace preceding this on the + current line. + + * cc-mode.el (c-submit-bug-report): Remove c-recognize-knr-p. Add + c-comment-continuation-stars. + +Mon Sep 22 15:47:02 1997 Barry A. Warsaw + + * cc-styles.el (c-initialize-builtin-style): + Only use copy-tree if it is + funcall-able. This is the right patch, and was given by Erik Naggum + + +Tue Sep 16 19:23:24 1997 Barry A. Warsaw + + * Release 5.18 + +Tue Sep 16 23:17:15 1997 Barry A. Warsaw + + * cc-menus.el (cc-imenu-c-prototype-macro-regexp): New variable. + + (cc-imenu-c++-generic-expression): Patches to better match C++ code. + Given by jan.dubois@ibm.net (Jan Dubois) + + * cc-menus.el (cc-imenu-java-generic-expression): + Removed test for declaration + statements. Patch given by Ake Stenhoff , as + forwarded to me by RMS. + + * cc-menus.el: + Imenu support for Objective-C given by Masatake (jet) YAMATO. + + * cc-mode.el (objc-mode): Bind imenu-create-index-function to + cc-imenu-objc-function to enable Imenu support for Objective-C. + Contributed by Masatake (jet) YAMATO. + +Mon Sep 15 23:21:51 1997 Barry A. Warsaw + + * cc-styles.el (c-initialize-builtin-style): + Use existing copy-tree if it's defined. + + copy-sequence doesn't work; the + c-offsets-alist must be copied recursively. Use copy-tree solution + given by Simon Marshall. + +Fri Sep 5 04:47:03 1997 Barry A. Warsaw + + * cc-cmds.el (c-beginning-of-statement): + Fixes in sentence movement to properly + handle M-e moving forward into a comment when looking at preceding + whitespace, and M-a moving backward into comment when looking at + following whitespace. + + Uncommented the looking-at call in the + sentence-flag clause so that moving by forward-sentence when looking + at the beginning of a comment works again. A previous log message in + cc-mode.el indicates this was commented out "because + c-beginning-of-statement-1 should do the right thing", but clearly it + doesn't. + + I don't know if this breaks something else, because I can't figure out + why it was commented out in the first place. + + * cc-langs.el: + Define `/' in c-mode-base-map since all modes now support + c-electric-slash. + + Define C-c C-e in mode-specific maps instead of c-mode-base-map since + c-expand-macro is meaningless in Java and IDL. + + * cc-engine.el (c-end-of-statement-1): + Wrap backward-up-list in a c-safe call so no + error results when buffer contains only a comment and point is at + eob. + +Fri Sep 5 00:50:41 1997 Barry A. Warsaw + + * Release 5.17 + +Fri Sep 5 04:47:03 1997 Barry A. Warsaw + + * cc-cmds.el (c-beginning-of-statement): + Fixes in sentence movement to properly + handle M-e moving forward into a comment when looking at preceding + whitespace, and M-a moving backward into comment when looking at + following whitespace. + + * cc-langs.el: + Define `/' in c-mode-base-map since all modes now support + c-electric-slash. + + Define C-c C-e in mode-specific maps instead of c-mode-base-map since + c-expand-macro is meaningless in Java and IDL. + + * cc-engine.el (c-end-of-statement-1): + Wrap backward-up-list in a c-safe call so no error results when + buffer contains only a comment and point is at eob. + + * cc-cmds.el (c-beginning-of-statement): + Uncommented the looking-at call in the + sentence-flag clause so that moving by forward-sentence when looking + at the beginning of a comment works again. A previous log message in + cc-mode.el indicates this was commented out "because + c-beginning-of-statement-1 should do the right thing", but clearly it + doesn't. + + I don't know if this breaks something else, because I can't figure out + why it was commented out in the first place. + +Tue Aug 26 22:31:55 1997 Barry A. Warsaw + + * cc-styles.el (c-style-alist): "python" style, knr-argdecl-intro == + + +Mon Aug 25 17:25:12 1997 Barry A. Warsaw + + * cc-engine.el (c-inside-bracelist-p): + Add a test to the enum list test so that the + following code won't erroneously recognize as inside a brace list: + + static PyObject ** + unpack_sequence(v, argcnt, why) + PyObject **v; + int argcnt; + enum *why_code; + { + int i; + + Otherwise, the `enum' in the K&R decl trips this code up. + + * cc-styles.el (c-style-alist): "python" style, fill-column = 78 + +Fri Aug 22 20:25:57 1997 Barry A. Warsaw + + * cc-cmds.el (c-comment-line-break-function): + Don't break line in the middle of a string. + +Mon Aug 18 17:37:24 1997 Barry A. Warsaw + + * cc-styles.el (c-style-alist): + "python" style change: arglist-intro <= + + "python" style change: inextern-lang <= 0 + +Fri Aug 15 18:39:10 1997 Barry A. Warsaw + + * cc-styles.el (c-style-alist): + "python" style requires c-comment-continuation-stars + to be "". + +Fri Aug 15 17:26:05 1997 Barry A. Warsaw + + * Release 5.16 + +Fri Aug 15 18:39:10 1997 Barry A. Warsaw + + * cc-styles.el (c-style-alist): + "python" style requires c-comment-continuation-stars + to be "". + + * cc-engine.el (c-end-of-statement-1): + Eliminate false hits on important characters + inside literals (strings, comments). + +Tue Aug 12 21:47:18 1997 Barry A. Warsaw + + * cc-cmds.el (c-comment-line-break-function): + In this function, and the defadvice, + call indent-new-comment-line if not in a comment. + + * cc-vars.el (c-buffer-is-cc-mode): Definition moved to cc-mode.el + + * cc-mode.el (c-buffer-is-cc-mode): + Definition moved here from cc-vars.el. Also, + put permanent-local property on variable so it's value won't get + killed by kill-all-local-variables. This makes it easier for non-CC + Mode derived modes to be initialized correctly. + + * cc-cmds.el (c-electric-brace): + In preserve-p test, don't test char-before when at + bobp. Open brace at bobp is illegal in most modes, but not awk-mode, + which depends on CC Mode. + +Mon Aug 11 15:37:04 1997 Barry A. Warsaw + + * cc-mode.el (c++-mode, java-mode, objc-mode, idl-mode): + Remove obsolete variable c-double-slash-is-comments-p. + + * cc-langs.el (c-double-slash-is-comments-p): Remove obsolete variable. + + * cc-cmds.el (c-fill-paragraph): + Remove conditional on obsolete variable + c-double-slash-is-comments-p. + + * cc-styles.el (c-style-alist): + Conform comment settings to RMS's preferences. + +Thu Aug 7 19:21:32 1997 Barry A. Warsaw + + * cc-styles.el (c-set-offset): Added autoload cookie. + +Thu Aug 7 18:13:12 1997 Barry A. Warsaw + + * Release 5.15 + +Thu Aug 7 19:21:32 1997 Barry A. Warsaw + + * cc-styles.el (c-set-offset): Added autoload cookie. + + * cc-langs.el (c++-mode-syntax-table, java-mode-syntax-table, + objc-mode-syntax-table, idl-mode-syntax-table): Added autoload + cookies. c-mode-syntax-table already has one. + +Wed Aug 6 21:50:08 1997 Barry A. Warsaw + + * cc-mode.el (c-initialize-cc-mode): + Check all cc-mode-19 interface requirements. + +Tue Aug 5 21:56:02 1997 Barry A. Warsaw + + * cc-align.el (c-lineup-java-throws): + Change the `when' clause to an `if-progn' :-( + + * cc-langs.el (c-common-init): + Make comment-line-break-function buffer local iff it's boundp. + + * cc-cmds.el: + defadvice for indent-new-comment-line keys off of c-buffer-is-cc-mode + instead of an explicit major-mode list. this means non-CC Mode + derived modes will work properly + + * cc-mode.el (c-initialize-cc-mode): Set c-buffer-is-cc-mode to t. + + * cc-vars.el (c-buffer-is-cc-mode): New variable + + * cc-mode.texi: + In FAQ section, document use of c-mode-base-map instead of c-mode-map. + + * cc-mode.el (c-initialize-cc-mode): + Give in to the pressure. require 'cc-mode-19 + if functionp is not bound. Too many novice errors without this. + + * cc-cmds.el: + Added advice for indent-new-comment-line so older Emacsen work if they + don't have the variable comment-line-break-function. + +Mon Aug 4 14:55:40 1997 Barry A. Warsaw + + * cc-langs.el (c-mode-base-map, c++-mode-map): + Move `/' as an electric character + from c++-mode-map to c-mode-base-map for all languages. + + * cc-cmds.el (c-electric-slash): + Make this work as the final slash in a */ block + oriented comment closing token. + + * cc-vars.el (c-comment-continuation-stars): + Can take a nil value. Also, the default value is "* ". + + * cc-cmds.el (c-comment-line-break-function): nil value for + c-comment-continuation-stars means use old semantics + +Fri Aug 1 22:44:49 1997 Barry A. Warsaw + + * cc-cmds.el (c-comment-line-break-function): + Added optional soft argument + + * cc-langs.el (c-common-init): Set comment-multi-line and + comment-line-break-function here for all modes. + + * cc-mode.el (c-mode, c++-mode, objc-mode, java-mode, idl-mode): + Don't set comment-multi-line here. + + * cc-vars.el (c-comment-continuation-stars): New variable + + * cc-cmds.el (c-comment-line-break-function): New function for proposed + mode-specific comment-line-break-function variable. + + * cc-mode.el (c-mode): comment-multi-line => nil + + * cc-mode.texi: Removed the description of c-enable-//-in-c-mode. + + * cc-langs.el (c-C-comment-start-regexp): Obsolete. + + (c-comment-start-regexp): Initialize from c-C++-comment-start-regexp. + + (c-populate-syntax-table, c-setup-dual-comments): Merge both functions + into c-populate-syntax-table. With the new 9X draft C standard, both + line and block oriented comments are supported in all modes, so always + set up the syntax tables to support both comment styles. + + (c-mode-syntax-table, c++-mode-syntax-table, java-mode-syntax-table, + objc-mode-syntax-table, idl-mode-syntax-table): Use the new syntax + table initialization idioms. + + (c-enable-//-in-c-mode): Obsolete. + + * cc-mode.el (c-mode): + c-comment-start-regexp uses c-C++-comment-start-regexp to + support line oriented comments. + +Wed Jul 30 00:01:45 1997 Barry A. Warsaw + + * cc-engine.el (c-guess-basic-syntax): + CASE 5D.4: template argument continuation + lines are now analyzed as template-args-cont. + + * cc-styles.el (c-offsets-alist): + Added template-args-cont syntactic symbol + + * cc-mode.texi: + Added description of template-args-cont syntactic symbol + +Sat Jul 26 16:03:33 1997 Barry A. Warsaw + + * cc-styles.el (c-styles-alist): + In "java" style, set c-hanging-comment-starter-p to + nil to preserve Javadoc starter lines. + +Sat Jul 26 12:24:20 1997 Barry A. Warsaw + + * Release 5.14 + +Sat Jul 26 16:03:33 1997 Barry A. Warsaw + + * cc-styles.el (c-styles-alist): + In "java" style, set c-hanging-comment-starter-p to + nil to preserve Javadoc starter lines. + +Fri Jul 25 22:17:07 1997 Barry A. Warsaw + + * cc-engine.el (c-beginning-of-statement-1): + When checking for bare semi, don't match + on a semi following a close brace, otherwise the following legal code + fails: + + void foo() + { + static struct Pattern nums + = {1, 2, 3}; + + int j = 2; + } + + This might break some bare semi idioms but those are probably more + rare than static initializers. + + * cc-mode.texi: Describe support for idl-mode + + * cc-vars.el (idl-mode-hook): New variable. + + * cc-mode.el (idl-mode): Support for CORBA's IDL language. + + * idl-font-lock.el: Unsupported font-lock definitions for IDL. + This should be merged in with font-lock.el + + * cc-mode.el (c-initialize-cc-mode): + move the calling of c-make-styles-buffer-local + into c-initialize-builtin-style. + + * cc-styles.el (c-set-style-2): + Fixed broken implementation of inherited styles. + + * cc-mode.texi: + Document c-initialization-hook. Also rewrite the "Getting Connected" + section on byte compiling the source. + + * cc-mode.el (c-initialize-cc-mode): + Run the c-initialization-hook, but only once + per Emacs session. + + * cc-vars.el (c-initialization-hook): New variable. + + * cc-engine.el (c-guess-basic-syntax): + CASE 5I: When adding 'inclass syntax, use the + relpos pointing to the class opening brace, unless that hangs on the + right side, in which case, use the start of the class/struct keyword. + +Thu Jul 17 03:36:22 1997 Barry A. Warsaw + + * cc-langs.el (c-symbol-key): + first character must be a letter or underscore + +Wed Jul 16 23:56:58 1997 Barry A. Warsaw + + * Release 5.13. + +Thu Jul 17 03:36:22 1997 Barry A. Warsaw + + * cc-langs.el (c-symbol-key): + first character must be a letter or underscore + + * cc-defs.el (c-load-all): Function deleted. + + * cc-mode.el (c-initialize-cc-mode): New function. + (c-mode, c++-mode, objc-mode, java-mode): Call it. + +Tue Jul 15 04:18:38 1997 Barry A. Warsaw + + * cc-mode.texi: + Describe the variable c-indent-comments-syntactically-p. + +Mon Jul 14 23:43:33 1997 Barry A. Warsaw + + * cc-langs.el (c-make-inherited-keymap): Change to a defun + + * cc-langs.el: + Added (require 'cc-defs) to pick up the definition of c-emacs-features. + + * README: Simplified instructions + + * cc-make.el: New file to aid in byte-compiling in older Emacsen. + +Sun Jul 13 21:24:37 1997 Barry A. Warsaw + + * cc-cmds.el: cc-defs is required to pick up the c-add-syntax macro + + * cc-langs.el (c-mode-menu): + Added uncomment region and slight rearrangement of + items + + * cc-cmds.el (c-electric-backspace): + Must get 'supercede property values to work + with delsel and pending-del. + +Thu Jul 10 20:46:09 1997 Barry A. Warsaw + + * cc-engine.el (c-maybe-labelp): + defvar this to shut up the byte compiler + +Wed Jul 9 22:08:58 1997 Barry A. Warsaw + + * cc-styles.el (c-initialize-builtin-style): + use copy-sequence instead of copy-tree + so the cl module isn't necessary. + + * cc-cmds.el (c-electric-brace): + fix ebola eradication consequence in the + preserve-p test. + +Tue Jul 8 23:47:47 1997 Barry A. Warsaw + + * Release 5.12 + +Mon Jul 7 23:47:02 1997 Barry A. Warsaw + + * cc-styles.el, cc-mode.el, cc-menus.el, cc-langs.el, cc-engine.el, cc-compat.el, cc-cmds.el, cc-align.el: + Reorganization to support byte-recompile-directory. + + * Release: Don't put release number in tar file + +Thu Jul 3 22:54:03 1997 Barry A. Warsaw + + * cc-langs.el (c-mode-base-map): + Proper binding of c-electric-backspace and + c-electric-delete, based on the policy of the various maintainers. + Thank goodness for delete-key-deletes-forward! + + * cc-vars.el (c-tab-always-indent, c-hanging-braces-alist): + Minor changes to the + cutomize format. + + * cc-mode.texi: Fixed spelling of Texinfo + + * cc-mode-19.el: Initial revision + + * cc-menus.el, cc-engine.el, cc-compat.el, cc-cmds.el, cc-align.el: + Major Ebola eradication. + +Wed Jul 2 21:33:04 1997 Barry A. Warsaw + + * cc-engine.el (c-crosses-statement-barrier-p, c-guess-basic-syntax): + Ebola + eradication. + + * cc-cmds.el (c-indent-region): + Call c-echo-parsing-error to echo last parsing + error that may have occurred. + + * cc-engine.el (c-echo-parsing-error): New function. + + * cc-engine.el (c-parsing-error): new variable + + (c-parse-state): When an unbalanced close brace is discovered, don't + raise an error (prevents insertion of character). Insert the + character, display a warning message, and set c-parsing-error so + syntax echoing will be disabled. + + (c-show-syntactic-information, c-indent-line): Suppress syntax echoing + if c-parsing-error is non-nil. + + * cc-styles.el: Added require of cl to pick up definition of copy-tree. + +Mon Jun 30 21:41:00 1997 Barry A. Warsaw + + * cc-langs.el, cc-mode.el (c-mode-map, c++-mode-map, objc-mode-map, java-mode-map): + Moved + defvars from cc-langs.el to cc-mode.el for use in c-mode, c++-mode, + objc-mode, and java-mode docstrings. Actual population of these mode + maps remains in cc-langs.el. + + * cc-mode.el: + Require cc-langs at top level, so as to get the definitions for + c-mode-map, et al. that are used in the *-mode docstrings. + +Fri Jun 27 17:33:32 1997 Barry A. Warsaw + + * cc-langs.el (c-mode-syntax-table): + Added autoload cookie for gdb-mode. + +Thu Jun 26 21:12:56 1997 Barry A. Warsaw + + * cc-engine.el (c-guess-basic-syntax): + CASE 5H: Whack one ebola infection (e.g. using + memq with the results of following-char in XEmacs 20). + + * cc-styles.el: + Added two require's that make autoload call of (c-set-style) work. + +Sun Jun 22 16:40:30 1997 Barry A. Warsaw + + * cc-cmds.el (c-electric-delete): + Don't call c-electric-backspace interactively. + +Fri Jun 20 20:40:33 1997 Barry A. Warsaw + + * cc-mode.el (c-mode, c++-mode, objc-mode, java-mode): + Make sure to call + c-update-modeline after the hooks are run, so that the modeline + accurately reflects auto-newline and delete-key minor modes if the + hooks set c-hungry-delete-key or c-auto-newline directly. + + * cc-align.el (c-lineup-java-throws): Fixed some regressions. + +Fri Jun 20 19:55:55 1997 Barry A. Warsaw + + * Public Release 5.11 + + * cc-mode.texi: + Describe changes to support separation of Backspace and Delete in + XEmacs 20. + + * cc-vars.el (c-delete-function): renamed to c-backspace-function. + + (c-backspace-function): New variable. + + * cc-cmds.el (c-electric-backspace, c-electric-delete): + Old X/Emacs 19 behavior + typically bound to the backspace keysym is renamed to + c-electric-backspace (which consults c-backspace-function). + c-electric-delete (c-delete-function) is now bound to the delete + keysym, which in XEmacs 20 is separated. + + * cc-langs.el (c-mode-base-map): + No longer bind "\177" as a way to spell [delete] + and [backspace]. Bind these two keys separate to support XEmacs 20's + separation of forward deletion and backward deleteion. This means + that in Emacs 19 and XEmacs 19, the backspace keysym is now bound to + c-electric-backspace, but the functionality is the same (although the + variable this consults is now called c-backspace-function). + + * cc-engine.el (c-show-syntactic-information): Minor optimization. + +Tue Jun 17 03:21:50 1997 Barry A. Warsaw + + * cc-align.el (c-lineup-multi-inher): Fixed small order dependency + + * cc-align.el (c-langelem-col): + New defsubst. Convert all appropriate calls + calculating the column of the langelem's relpos to use this function. + + * cc-align.el (c-lineup-java-throws): New function + + * cc-styles.el (c-style-alist): + "java" style's func-decl-cont is associated with + c-lineup-java-throws so long throws lines line up exceptions. + + * cc-styles.el (c-offsets-alist): + Substituted RMS's description of func-decl-cont, + with a minor change. + + * cc-mode.texi: + Substituted RMS's description of func-decl-cont, with a minor change. + +Thu Jun 12 13:57:35 1997 Barry A. Warsaw + + * cc-styles.el (c-styles-alist): + Changed topmost-intro-cont offset to + in Java + style. This is closer to what people expect for default instance + variable initializations. + +Wed Jun 11 18:20:59 1997 Barry A. Warsaw + + * cc-mode.texi: LFD => C-j + + RMS> I've decided to mostly stop using LFD as the name of an input + RMS> character because PCs do not have a linefeed key. So please + RMS> change the cc-mode manual to use @kbd{C-j} rather than @key{LFD}. + +Mon Jun 9 15:20:10 1997 Barry A. Warsaw + + * cc-styles.el (c-offsets-alist): A few minor changes to the docstring. + +Mon Jun 2 23:37:51 1997 Barry A. Warsaw + + * Beta Release 5.09 + +Sun Jun 1 16:23:11 1997 Barry A. Warsaw + + * cc-mode.el (c-load-all): cc-menus depends on cc-langs. + + * cc-langs.el (c-mode-base-map): + New variable. All maps, including c-mode-map + inherit from this map. This makes menu creation more straightforward + for Emacs, although it is unnecessary for XEmacs. + + (c-make-inherited-keymap): Use c-mode-base-map as the parent map. + +Sat May 31 17:35:55 1997 Barry A. Warsaw + + * cc-langs.el (c-common-init): + Conversion to the easymenu library for creation of + popup and menubar menus. + + * cc-menus.el: + Conversion to the easymenu library for creation of popup and menubar + menus. + + * cc-mode.el (c-emacs-features): Make this work for Emacsen after + 19.34. + +Fri May 30 15:38:09 1997 Barry A. Warsaw + + * cc-mode.el (c-emacs-features): + Change the XEmacs 19 test from vectorp to arrayp, + since we're using aref to access an element. Use this test also + for Emacs 19, with a few key differences: the element returned in + Emacs 19 is a cons cell. Also, arrayp doesn't return t for + char-tables in Emacs 19.34, but will in Emacs 19.35. + +Tue May 27 21:23:51 1997 Barry A. Warsaw + + * cc-engine.el (c-guess-basic-syntax): + CASE 5C.3: changing looking-at regexp to + throws[ \t\n] + + CASE 15E: if we're in Java and looking at the throws clause that + follows a method's parameter list, we need to go back to the beginning + of the statement to find the start of the method. + +Fri May 23 14:58:30 1997 Barry A. Warsaw + + * Beta Release 5.07 + + * cc-vars.el: Added a require of the custom library, for Emacs + 19.34 compatibility. + +Thu May 22 22:53:25 1997 Barry A. Warsaw + + * cc-mode.texi: + Document the new default for c-style-variables-are-local-p. This + variable is now nil by default. + + * cc-styles.el (c-make-styles-buffer-local): + New function. By default all style + variables are now global in value. Call this function to make them + buffer local. This function is called automatically at load time if + c-style-variables-are-local-p is non-nil. + + * cc-vars.el (c-style-variables-are-local-p): Default value is now nil. + +Tue May 20 23:59:19 1997 Barry A. Warsaw + + * cc-menus.el (c-popup-menu): Obsolete. + + (c-mode-menu): Optional argument to add " Mode Commands" to the + title, in XEmacs only. + + * cc-langs.el (c-common-init): + Get rid of the pre-XEmacs-19.10 way of doing popup + menus. Make sure that in XEmacs, the menubar title is just the + modename, but the popup has "MODENAME Mode Commands". + +Tue May 13 22:57:24 1997 Barry A. Warsaw + + * cc-align.el (c-lineup-C-comments): + Fixes to handle all situations where the first line of a block + comment has more stars on it than subsequent lines. This not only + picks up the Javadoc style, but also + + /********************************************************************* + * Routines formerly in objectPalette.c + *********************************************************************/ + + * cc-engine.el (c-guess-basic-syntax): + CASE 6A: Removed tests for ObjC & Java method + closing parens since none of the test cases touched this code, and it + broke close-paren on a separate line being recognized as + arglist-close. + + * cc-langs.el: + Removed most byte-compiler warnings by removing many obsolete + variables. + +Fri May 9 21:54:27 1997 Barry A. Warsaw + + * cc-cmds.el (c-fill-paragraph): + Included franl@world.std.com (Francis Litterio) + patch that makes c-fill-paragraph preserve fill-prefix. + + * cc-engine.el (c-guess-basic-syntax): + CASE 6C: when checking for a `for' statement, + watch out for underscore separated symbols: for_each + +Tue May 6 23:18:13 1997 Barry A. Warsaw + + * Restructuring completed for version 5.xx + +Tue May 6 19:16:48 1997 Barry A. Warsaw + + * cc-mode.el (c-style-alist, c-set-style-1): Added support for + inherited styles. + + * Restructuring began for version 5.00 + +Sat Mar 29 20:01:42 1997 Barry A. Warsaw + + * Public Release 4.389. + +Fri Mar 28 16:48:31 1997 Barry A. Warsaw + + * cc-mode.el (c-guess-basic-syntax): + CASE 5C: watch out for Java abstract method + definitions. These are distinguished from normal throws clauses since + they cross statement boundaries. + +Tue Mar 25 03:19:17 1997 Barry A. Warsaw + + * cc-mode.el (c-guess-basic-syntax): CASE 5A.3: use boi instead of bol. + +Thu Mar 20 16:46:13 1997 Barry A. Warsaw + + * cc-mode.el (c-Java-comment-start-regexp): + Recognize the three Java styles of + comments: 1) traditional C block; 2) javadoc style /** ...; 3) C++ + style. + + (java-mode): Set buffer local variable c-comment-start-regexp to + c-Java-comment-start-regexp. + + (c-fill-paragraph): Use c-comment-start-regexp derived regular + expression when checking for c-hanging-comment-starter-p, so javadoc + styles are handled correctly in Java mode. + + * cc-mode.el (c-lineup-C-comments): + Change the re-search-forward to a looking-at in + the innermost test. This catches these styles of comments: + + /* Test for garbage collection. If the pool's free size is greater thaasds asdf + asdf asdf asdf asdf asd fas fa asdf asf asdf asdf adf asdf asdf asdf asdf + asdf glob chob stillp nasty toes winko stagilly frankly sut sut hoey */ + =!= + + * cc-mode.el (c-add-syntax): + Move macro definition to before it's first use. + + * cc-mode.el (c-submit-bug-report): + capture buffer local variable values which are + printed in the post-hook, while the current buffer is the CC Mode + buffer we're interested in. reporter-submit-bug-report leaves the + current buffer as the mail buffer, so buffer local variables will not + get the proper value. + +Tue Mar 18 16:43:13 1997 Barry A. Warsaw + + * cc-mode.el (c-inher-key): + Require the regexp group that contains the `:'. + Previously it was optional, but that broke other code. + +Sun Mar 16 16:17:57 1997 Barry A. Warsaw + + * cc-mode.el (c-fill-paragraph): + Do not set fill-prefix to "*" when looking-at + "*/", otherwise the following example does not fill properly (the last + start gets deleted). + + /* this is a comment + */ + +Mon Mar 10 16:25:49 1997 Barry A. Warsaw + + * cc-mode.el (c-lineup-C-comments): + Handle more cases, especially when comment + lines aren't prefixed with stars. + +Sun Mar 9 20:09:16 1997 Barry A. Warsaw + + * Public Release 4.379. + +Mon Mar 10 01:04:38 1997 Barry A. Warsaw + + * cc-mode.el (c-lineup-C-comments): + Handle more cases, especially when comment + lines aren't prefixed with stars. + +Sat Mar 8 00:36:55 1997 Barry A. Warsaw + + * cc-mode.el (c-Java-class-key): + optional space after protection key should be + inside first paren group. + +Fri Feb 28 18:12:02 1997 Barry A. Warsaw + + * cc-mode.el (c-functionp, c-copy-tree): + Better compatibility checks between XEmacs + and Emacs. + + (c-mapcar-defun): Obsolete. + +Mon Feb 24 22:49:43 1997 Barry A. Warsaw + + * cc-mode.el (c-guess-basic-syntax): + CASE 5B.1: watch out for throw() clauses which + could follow a member init list in a constructor. + +Thu Feb 20 19:32:20 1997 Barry A. Warsaw + + * cc-mode.el (c-submit-bug-report): + Display c-indentation-style, but not in the + setq. + + * cc-mode.el (c-Java-special-key): + New variable recognizes Java "implements", + "extends", and "throws" keywords. + + (c-guess-basic-syntax): CASE 5C: recognize Java constructs + "implements", "extends", and "throws"; CASE 5C.3: differentiate + between "throws" == func-decl-cont, and "implements" or "extends" == + inher-intro or inher-cont; CASE 5D.3: removed; CASE 5D.4 => 5D.3; + CASE 5D.5 => CASE 5D.4; CASE 5D.6 => CASE 5D.5; CASE 5K: don't need to + look for Java keywords. + + (c-lineup-java-inher): Better indentation calculation for Java + inheritance constructs. + +Wed Feb 19 23:29:00 1997 Barry A. Warsaw + + * Beta Release 4.372. + +Thu Feb 20 04:07:11 1997 Barry A. Warsaw + + * cc-mode.el (c-Java-special-key, c-guess-basic-syntax, + c-lineup-java-inher): Recognize Java "extends", "implements", and + "throws" clauses and map them into 'inher-intro, 'inher-cont, and + 'func-decl-cont syntactic symbols. Do the indentation as + of Java inheritance lines better. + +Tue Feb 18 03:31:57 1997 Barry A. Warsaw + + * cc-mode.texi: Change documentation to reflect syntactic symbol + change from 'ansi-funcdecl-cont to 'func-decl-cont. + + * cc-mode.el (c-offsets-alist): Changed the syntactic symbol + 'ansi-funcdecl-cont to 'func-decl-cont. This symbol is useful in + Java throws declarations. + + (c-lineup-java-inher): New function for lining up "implements" + continuations (i.e. inheritance in Java). + + (c-style-alist): In "java" style, set 'inher-cont to + c-lineup-java-inher. + + (c-Java-class-key): Optional c-protection-key can appear before the + "class" keyword. + +Thu Feb 13 21:39:38 1997 Barry A. Warsaw + + * cc-mode.el (c-beginning-of-statement-1): First, check for bare + semi-colon, which is a legal statement but not caught by the more + intense loop later on. + + * cc-mode.el (c-style-alist): Fixes to "ellemtel" style given by + Colin Rafferty . + + * cc-mode.el (c-beginning-of-statement): Don't use + forward-sentence when looking at a C block comment start. + c-beginning-of-statement-1 will do the right thing. + +Sun Feb 9 07:28:42 1997 Barry A. Warsaw + + * cc-mode.el (c-guess-basic-syntax): CASE 5C: watch for scope operators + + * cc-mode.el (c-lineup-C-comments): Watch out for no leading stars. + +Thu Feb 6 19:07:09 1997 Barry A. Warsaw + + * cc-mode.texi: Document that c-set-style is bound to `C-c .' + + * cc-mode.el (c-set-style): Add initial contents (the value of + c-indentation-style), and history on the style name. + + (c-mode-map): Bind c-set-style on `C-c .' + + * cc-mode.el (c-read-offset, c-read-offset-history): Use + completing-read, with REQUIRE-MATCH nil, so that offsets can be + completed when they are function names. Also implement read + history. + + * cc-mode.el (c-guess-basic-syntax): CASE 15D: fix infinite loop + problem in while... clause looking for statement starting at boi, + when using run-in statement styles. + + * cc-mode.el (cc-imenu-java-generic-expression): New variable for + integration of java-mode with imenu. + + (java-mode): Use cc-imenu-java-generic-expression. + + * cc-mode.texi: Describe the use of c-hanging-comment-starter-p and + c-hanging-comment-ender-p, as well as the fill-paragraph command. In + the known bugs section, do not recommend using filladapt. + +Wed Feb 5 23:50:52 1997 Barry A. Warsaw + + * cc-mode.el (c-hanging-comment-starter-p): New variable, + analogous to c-hanging-comment-ender-p. + + (c-fill-paragraph): Use c-hanging-comment-starter-p. + +Mon Feb 3 16:36:03 1997 Barry A. Warsaw + + * cc-mode.texi: Added a note about c-Java-defun-prompt-regexp in + the section on performance. + + * cc-mode.el (java-mode): Do not set defun-prompt-regexp to + c-Java-defun-prompt-regexp. In the following example, putting + point on he brace that opens main() and hitting M-C-a will send + both Emacs 19.34 and XEmacs 19.15 into tight CPU loops. + + -------------------- snip snip -------------------- + import java.io.*; + import java.lang.*; + + class foo + { + public static void main(String[] args) throws java.io.IOException, java.io.FileNotFoundException + { + FileInputStream bs = new FileInputStream("j.dat"); + System.out.println(bs.readLine()); + } + } + +Sun Feb 2 18:11:17 1997 Barry A. Warsaw + + * cc-mode.el (c-guess-basic-syntax): + CASE 2: relpos for 'c and 'c++ is now boi. + +Mon Jan 27 18:55:02 1997 Barry A. Warsaw + + * Public Release 4.353 + +Mon Jan 27 16:25:57 1997 Barry A. Warsaw + + * cc-mode.el (c-guess-basic-syntax): + CASE 15D: do not assume that boi of previous + statement is the beginning of a statement. + +Wed Jan 22 23:42:59 1997 Barry A. Warsaw + + * cc-mode.el: + Removed the require of imenu. This currently breaks in XEmacs if you + have imenu around (which hasn't been completely ported yet), and I + think it's no longer necessary for Emacs. + +Tue Jan 21 20:47:23 1997 Barry A. Warsaw + + * cc-mode.el (c-cleanup-list, c-electric-brace): + New clean-up option: brace-elseif-brace. + + * cc-mode.el (c-style-variables-are-local-p): + New variable which controls whether + indentation style variable are buffer local are not. By default, for + backwards compatibility, this variable is t. + +Tue Jan 7 23:53:43 1997 Barry A. Warsaw + + * cc-mode.el (c-Java-access-key): + set to nil since Java doesn't have C++-like + access labels. + +Mon Jan 6 23:03:21 1997 Barry A. Warsaw + + * cc-mode.texi: Document new built-in styles. + + * cc-mode.el (c-style-alist): Added "python" style. + +Thu Jan 2 21:13:52 1997 Barry A. Warsaw + + * cc-mode.el (c-mode-menu): New function + + (c-popup-menu, c-common-init): use new function to handle XEmacs menus + better (uses add-submenu where appropriate). + +Tue Dec 24 18:55:10 1996 Barry A. Warsaw + + * cc-mode.el (c-lineup-C-comments): + A much better implementation that handles all + common star-prefixed block comment styles (see below). + + (c-block-comments-indent-p): obsolete and removed. + + int main() + { + /* + * + */ + + /* + ** + ** + */ + + /** + ** + ** + **/ + + /*** + *** + *** + *** + ***/ + + /** + *** + *** + **/ + } + + * cc-mode.el (c-indentation-style): + take default value from c-site-default-style. + +Mon Dec 23 23:48:26 1996 Barry A. Warsaw + + * cc-mode.el (adaptive-fill-regexp): + For all but XEmacs 19.13, the default should + be nil. + +Thu Dec 19 21:10:35 1996 Barry A. Warsaw + + * cc-mode.el (c-emacs-features): detect Infodock. + + (c-common-init, c-mode-map): Don't install menus for Infodock. + + * cc-mode.el (c-indent-exp): + fixed infinite loop when multi-line C comment is last + thing in buffer. + + (c-guess-basic-offset): fixed error when K&R C-like macro is first + non-syntactic whitespace in file. + + * cc-mode.el (c-C++-comment-start-regexp): + use a more efficient representation. + +Tue Dec 10 20:32:21 1996 Barry A. Warsaw + + * cc-mode.el (c-buffer-style): New variable. + +Fri Oct 4 19:10:15 1996 Barry A. Warsaw + + * Public Release 4.322 + +Fri Oct 4 20:28:14 1996 Barry A. Warsaw + + * cc-mode.el (c-backslash-region): + If a line ends at the end of the region, always + delete backslash from it. + + Given by Richard Stallman 1996-08-31 + + (c-backslash-region): In XEmacs, keep region active. + + * cc-mode.el (c-mode-map): + Install FSF mode menu into menubar using the name + "CC-Mode" for all supported modes. + + (c++-mode-map, objc-mode-map, java-mode-map): Don't install an + additional FSF menu. + + * cc-mode.el: + Removed the following variables from the built-in "cc-mode" style: + + c-echo-syntactic-information-p + c-string-syntax-p + c-tab-always-indent + c-inhibit-startup-warnings-p + + These control how the mode acts, not how code looks. + +Mon Sep 30 22:24:48 1996 Barry A. Warsaw + + * cc-mode.el (c-indent-command): + Sync docstring with texinfo documentation, and + actual behavior. + +Thu Sep 19 18:13:13 1996 Barry A. Warsaw + + * cc-mode.el (c-style-alist): + Added "linux" style. + +Tue Aug 20 21:08:13 1996 Barry A. Warsaw + + * cc-mode.el (c-lineup-comment): preserve comment-column. + +Mon Aug 19 22:24:41 1996 Barry A. Warsaw + + * cc-mode.el (c-gnu-impose-minimum): + Don't impose minimum on comment-only lines. + +Tue Aug 6 21:11:39 1996 Barry A. Warsaw + + * cc-mode.el (c-mark-function): Moved to C-c C-m + + (c-show-syntactic-information): Optional universal argument inserts + analysis as a comment on the line. + +Fri Jul 5 23:57:19 1996 Barry A. Warsaw + + * cc-mode.el (c-insert-tab-function): + New variable allowing tab-to-tab-stop to be + used instead of insert-tab. + + (c-indent-command): Use c-insert-tab-function variable. + +Fri Jun 7 14:31:47 1996 Barry A. Warsaw + + * cc-mode.el (java-mode): Use (c-set-style "java"); i.e. lowercase. + + * cc-mode.el (c-functionp): + Emacs 19.3x doesn't have functionp, so lift the version + from XEmacs 19.13. + + (c-electric-brace, c-read-offset, c-set-offset, c-get-offset): Use + c-functionp. + +Fri May 31 14:42:07 1996 Barry A. Warsaw + + * cc-mode.el (c-offsets-alist): New syntactic symbols: + extern-lang-open, extern-lang-close, inextern-lang + + (c-hanging-braces-alist): Hang extern-lang-open by default. + + (c-electric-brace): Add extern-lang-open and extern-lang-close to + list of symbols that can hang. + + (c-guess-basic-syntax): CASE 5A.4 => 5A.5; New CASE 5A.4 added to + recognize extern-lang-open; CASE 14C => 14D; New CASE 14C added to + recognize extern-lang-close + + (c-recognize-knr-p): defconst it. + + (c-search-uplist-for-classkey): When searching for c-class-key, + concat "\\|extern[^_]". The logic for determining whether we are + inclass-p and inextern-p is essentially the same so this seems to + work very well in all test cases. + + (c-guess-basic-syntax): If inclass-p, do an additional check to + see whether this is really inside an external language definition + block or a class definition and set inextern-p accordingly (a + boolean only). + + (c-guess-basic-syntax): CASE 5A.4 => 5A.1; 5A.1-5A.3 => 5A.2-5A.4; + New CASE 5F to check for extern-lang-close; CASE 5F-5J => 5G-5K; + CASE 5I: modifier could either be 'inclass or inextern-lang; CASE + 14A: closing brace isn't an inline-close if we're inside an extern + language block; CASE 14B: watch out for same. + +Thu May 30 14:42:07 1996 Barry A. Warsaw + + * cc-mode.el (c-guess-basic-syntax): CASE 5A.3: an inline-open + brace should also be given inclass syntax. The problem is that + this breaks indentation for brace that start inline-inclass + functions inside a nested class since they will twice add the + indentation of the inner class to the running total. + + The solution is to not give one of the two symbols a relpos. The + decision was made to omit the relpos of the 'inline-open symbol. + + (c-mode-help-address): Added cc-mode-help@python.org as the new + address. + + (c-recognize-knr-p, c++-mode, java-mode): Made into a non-user + configurable variable. This variable is always t for C and + Objective-C modes and nil for C++ and Java modes. + + (c-guess-basic-syntax): CASE 5G: Although we still test on + c-recognize-knr-p, this is no longer user configurable, and no + longer imposes potentially disasterous impact on performance. + Adopt c-mode.el assumption that argdecls are indented at least one + space and that function headers are not indented. This prevents + us from potentially searching back to the top of the file when + looking at a large number of top-level delarations. + + (c-gnu-impose-minimum): New function + + (c-label-minimum-indentation): New buffer-local variable + + (c-style-alist): In "gnu" style, add c-gnu-impose-minimum to + c-special-indent-hook so case-label and label syntaxes will have a + minimum indentation. + + (c-submit-bug-report): report on c-label-minimum-indentation + + (c-set-style-1): special case c-special-indent-hook + + make c-special-indent-hook buffer local + +Wed May 29 20:13:34 1996 Barry A. Warsaw + + * cc-mode.el (c-skip-conditional): `try' clauses in C++ skip only + 1 sexp. Also take care of finally and synchronized statements. + +Fri May 24 15:30:27 1996 Barry A. Warsaw + + * cc-mode.el (c-lineup-arglist-close-under-parent): New function. + + (c-C-conditionals): New constant. + + (c-C-conditional-key, c-C++-conditional-key, c-Java-conditional-key): + Use c-C-conditionals. + + (c-Java-conditional-key): Added support for "synchronized" keyword. + +Fri May 3 22:03:13 1996 Barry A. Warsaw + + * cc-mode.el (c-Java-conditional-key): New variable. + + (java-mode): Set buffer-local variable c-conditional-key to + c-Java-conditional-key. + +Thu May 2 21:18:56 1996 Barry A. Warsaw + + * cc-mode.el (c-C++-access-key): Allow for whitespace between the + protection key and the colon. + +Wed Apr 10 04:50:50 1996 Barry A. Warsaw + + * cc-mode.el (c-set-style): as a last resort, match exact case for + stylename. + +Wed Apr 3 16:19:08 1996 Barry A. Warsaw + + * cc-mode.el (c-get-offset, c-read-offset, c-set-offset): Use + functionp instead of fboundp to test for OFFSET being a function. + This makes the documentation more accurate and allows for + lambda expressions to be used as offsets, instead of allowing + only symbols with function bindings. + +Mon Apr 1 16:12:27 1996 Barry A. Warsaw + + * Public Release 4.282 + +Tue Feb 6 22:35:36 1996 Barry Warsaw + + * cc-mode.el (c-common-init): typo + +Mon Feb 5 15:54:08 1996 Barry Warsaw + + * cc-mode.el (c++-mode-map, objc-mode-map, java-mode-map): + In XEmacs, use set-keymap-parents if it is fboundp. + + * cc-mode.el (c-delete-backslash): + Sync with old-c-mode.el. Given by Ben Wing . + +Mon Jan 22 23:25:21 1996 Barry Warsaw + + * cc-mode.el: Added back autoload cookies. + + * cc-mode.el (c-emacs-features): + Determine which paragraph filling regexp suite to use based on the + Emacs version number. + + (c-fill-paragraph): Use the paragraph filling regexp suite as + determined in c-emacs-features. + +Fri Jan 19 18:57:01 1996 Barry Warsaw + + * cc-mode.el: + imenu is required in Emacs 19, but doesn't exist in XEmacs + + * cc-mode.el (c-site-default-style): New variable. + +Thu Jan 18 23:51:17 1996 Barry Warsaw + + * cc-mode.el: + (java-mode, java-syntax-table, java-mode-map, java-mode-abbrev-table): + New in support of Java. + +Tue Jan 16 00:09:41 1996 Barry Warsaw + + * cc-mode.el (c-common-init): Make comment-multi-line a local variable. + +Mon Jan 15 23:56:06 1996 Barry Warsaw + + * cc-mode.el (c-set-style): + Conditional up-casing of stylename for backwards compatibility. + +Fri Jan 12 02:07:54 1996 Barry Warsaw + + * cc-mode.el (c-backward-to-start-of-do): + Eliminate infinite loop in perverse cases. + + * cc-mode.texi: Explain that style names are case insensitive. + + * cc-mode.el (c-style-alist, c-set-style, c-add-style): + All style names are case insensitive, but default to lowercase. + +Sat Jan 6 01:08:45 1996 Barry Warsaw + + * cc-mode.el (cc-imenu-c++-generic-expression): + New variable. Integrated w/ FSF changes. + + (cc-imenu-c-generic-expression): New variable. Integrated w/ FSF + changes. + + (c++-mode): Set imenu-generic-expression. Integrated w/ FSF changes. + + (c-mode): Set imenu-generic-expression. Integrated w/ FSF changes. + + (c-common-init): Make imenu-generic-expression buffer local. + + * cc-mode.el (c-progress-fini): + Integrate RMS change: Fix "done" message. + + * cc-mode.el (c-electric-lt-gt): New command. + + * cc-mode.el (c-mode-map): + Only rebind M-q if fill-paragraph-function doesn't exist, as in + pre-Emacs 19.30. Integrated with FSF changes. + + (c-common-init): Set fill-paragraph-function if it exists. + Integrated with FSF changes. + + (c-fill-paragraph): Return t if did special filling. Otherwise + return nil and don't change the buffer. Integrate with FSF changes + for Emacs 19.30. + + * cc-mode.el: Switch to GNU style only the first time file is loaded. + + * cc-mode.el (c-guess-basic-syntax): + CASE 5B.3: ansi-funcdecl-cont could include legal C++ `throw' + declaration. + + (c-offsets-alist): ansi-funcdecl-cont => + + +Fri Jan 5 23:14:12 1996 Barry Warsaw + + * cc-mode.el (c-beginning-of-statement-1): + Restore old CASE 3 logic -- checking for at a c-conditional-key. + + (c-guess-basic-syntax): CASE 5A.2: watch out for enum function + return types. CASE 15D: check for landing on a brace that opens a + nested function. + +Wed Nov 22 14:55:12 1995 Barry Warsaw + + * (c-beginning-of-statement-1): CASE 3, can't just return t at + end of let clause since this will break arglist-cont-nonempty + lines (see buggy line below). Doing a backward-up-list could + be slow, but I don't see any other way of doing this. + + void + C_entries (c_ext, inf) + int c_ext; /* extension of C */ + FILE *inf; /* input file */ + { + /* Consider token only if some complicated conditions... */ + if ((definedef != dnone + || (cblev == 0 && structdef != scolonseen) + || (cblev == 1 && structdef == sinbody)) /* buggy line */ + && typdef != tignore + && definedef != dignorerest + && funcdef != finlist) + { + } + } + +Fri Nov 17 22:01:36 1995 Barry Warsaw + + * cc-mode.el (c-guess-basic-offset, c-beginning-of-statement-1): + Do not check for c-conditional-key when skipping backwards over + statements that look sort of like conditionals. This makes + statements following nested functions indent correctly. CASE 9B.3 + (unknown catchall) now gets triggered by the brace that opens a + nested function. These will get indented moderately correctly, + but they are not assigned the correct syntax. I'm not sure + exactly what they *should* be assigned. Also, this changes the + relpos for top-level defun-open braces, but that will be very hard + to fix, and it may break backward compatibility. + + * cc-mode.el (c-guess-basic-offset): + CASE 5H, inclass relpos should be relative to boi of the open + brace, not the beginning of the class keyword. + +Thu Nov 16 00:20:59 1995 Barry Warsaw + + * cc-mode.el (c-guess-basic-syntax): + CASE 5D.5, watch out for c-access-key set to nil, as in this case + (in c-mode): + + typedef struct { + unsigned count:24, + age:6, + dirty:1, + reserved:1, + }; + +Wed Nov 15 23:38:05 1995 Barry Warsaw + + * cc-mode.el (c-beginning-of-statement, c-end-of-statement): + Watch out for c-end-of-statement being called interactively. + +Mon Aug 28 20:39:43 1995 Barry Warsaw + + * cc-guess.el (cc-guess-region): + wrap relpos calculation in a save-excursion. + +Mon Aug 28 16:57:26 1995 Barry Warsaw + + * Version 4.241 released. + +Mon Aug 21 23:41:21 1995 Barry Warsaw + + * cc-mode.el (c-backslashify-current-line): Obsolete. + + (c-append-backslash, c-delete-backslash): Taken from XEmacs' + old-c-mode.el + + (c-backslash-region): Use the version from XEmacs' old-c-mode.el + since it does a better job of aligning the backslashes. + + * cc-mode.el (c-indent-defun): Watch out for point being on the + first top-level open brace in the buffer. + +Tue Aug 1 22:14:32 1995 Barry Warsaw + + * cc-mode.el (c-copy-tree, c-mapcar-defun): Define functions only + available in XEmacs 19.12, or Emacs 19 + lucid.el. + +Tue Jul 25 22:27:37 1995 Barry Warsaw + + * cc-mode.el (c-lineup-ObjC-method-call): New implementation + better handles 1. indentation of arguments to keyword parameters, + 2. multiline method calls. + +Fri Jul 21 22:08:04 1995 Barry Warsaw + + * cc-mode.texi (Customizing Indentation): Added a better + explanation of the difference between setq and setq-default + w.r.t. setting cc-mode indentation variables. + +Thu Jul 20 20:19:33 1995 Barry Warsaw + + * cc-mode.el (c-electric-brace): Fixed preservation of + no-whitespace before brace. + + * cc-mode.el (c-guess-basic-syntax): CASE 5A.1: Watch out for + c-state-cache; it may or may not be in place, but it should be + ignored. + + * cc-mode.el (c-electric-colon): In call to c-lookup-lists, fixed + incorrect quoting of symbols in the quoted list. + +Mon Jul 10 15:44:55 1995 Barry Warsaw + + * cc-mode.el (c-search-uplist-for-classkey): Watch out for + embedded c-class-key keywords. + +Mon Jul 3 18:05:33 1995 Barry Warsaw + + * cc-mode.el (c-common-init): Make a deep copy of c-offsets-alist + so that changing the buffer-local value in one buffer doesn't + affect the global value, or other buffers. + + * cc-mode.el (c-snug-do-while): forward-sexp call could fail; + wrap it in a c-safe. + +Fri Jun 30 21:42:23 1995 Barry Warsaw + + * cc-mode.el (c++-mode, objc-mode): comment-multi-line must be nil + if // is the default comment style. + +Sun Jun 11 18:05:20 1995 Barry Warsaw + + * cc-mode-18.el (c-emacs18-bsws): Installed while loop patch given + by "David P. Baker" to fix infinite loops + when lim is reached while still inside whitespace. + +Sun Jun 11 16:58:39 1995 Barry A. Warsaw + + * Version 4.222 Released. + +Sun Jun 11 18:05:20 1995 Barry A. Warsaw + + * cc-mode-18.el (c-emacs18-bsws): + installed while loop patch given by "David P. Baker" + to fix infinite loops when lim is reached while + still inside whitespace. + +Thu Jun 1 16:51:16 1995 Barry A. Warsaw + + * cc-mode.el (c-hack-state): watch out for null state with 'open brace. + +Tue May 30 23:11:57 1995 Barry A. Warsaw + + * cc-mode.el (c-outline-level): new function. + + (c-common-init): compatibility with outline-minor-mode. Given by Per + Abrahamsen + +Fri May 19 00:15:06 1995 Barry A. Warsaw + + * cc-mode.el (c-electric-colon): + when adding a newline for a non- `before' -hanging + colon, watch out for when they already start on their own line. + +Thu May 18 23:49:51 1995 Barry A. Warsaw + + * cc-mode.el (paragraph-start, paragraph-separate): backed out of the + 4.191 -> 4.192 change due to breakage in c-fill-paragraph + and dabbrev-expand. + +Wed May 17 22:51:46 1995 Barry A. Warsaw + + * cc-mode.el (c-guess-basic-syntax): + CASE 5C: more robust in searching for c-baseclass-key when not + followed by a colon. + + * cc-mode.el (c-enable-//-in-c-mode, c-setup-dual-comments): + new functions to allow users to optionally enable // as comment + delimiters in c-mode. + + (c-C-comment-start, c-C++-comment-start): new variables. + + (c-mode, c++-mode, objc-mode): use new variables. + + * cc-mode.el (c-guess-basic-syntax): + CASE 5D.4: watch out for <> characters in literals. CASE 5D.5: + skip forward over any literals encountered after point. + +Mon May 8 23:11:35 1995 Barry A. Warsaw + + * cc-mode.el (c-set-style): + Ignore case in completion. Use appropriate mode name in prompt + string. + + * cc-mode.el (c-in-literal): + Faster implementation for skipping over cpp macros, at the expense + of prohibiting `#' characters as first non-whitespace char on a + line inside another literal (i.e. string or block comment). + +Wed May 3 22:52:32 1995 Barry A. Warsaw + + * cc-mode.el (c-read-offset): change to have an interface consistent w/ + switch-to-buffer + +Mon May 1 20:31:13 1995 Barry A. Warsaw + + * cc-mode.el (c-style-alist): + fixed the 'label offset for GNU, K&R, BSD, Stroustrup, and + Whitesmith. + +Sat Apr 29 00:46:53 1995 Barry A. Warsaw + + * cc-mode.el (c-mode-map): + C-c C-v unbound since it conflicts with OOBR, which has a more + useful binding. + +Mon Apr 17 16:48:06 1995 Barry A. Warsaw + + * cc-mode.el (c-lineup-ObjC-method-call): Installed Lele Gaifax + patch as suggested by + mccallum@cs.rochester.edu for Objective-C method call indentation + styles. + +Wed Apr 12 21:02:46 1995 Barry A. Warsaw + + * cc-mode.el (paragraph-start, paragraph-separate): + Installed the FSF's patch as explained below: + + Thu Mar 2 10:22:30 1995 Boris Goldowsky + + * ada.el (ada-mode): Remove "^" used as anchor from + paragraph-start and paragraph-separate values, so that they will + work with non-0 left-margin settings. + [...] + * cc-mode.el (c-common-init, c-fill-paragraph): Likewise. + + * cc-mode.el (c-hanging-semi&comma-criteria): new variable + + (c-semi&comma-inside-parenlist): new function + + (c-electric-semi&comma): use new variable + c-hanging-semi&comma-criteria to determine if a newline should be + added after a semicolon or comma, instead of hardcoding this logic in. + +Mon Apr 10 22:00:28 1995 Barry A. Warsaw + + * cc-mode.el (c-electric-brace): + When hanging a close brace, add just-one-space if there was + already whitespace before point. + +Fri Mar 31 01:15:07 1995 Barry A. Warsaw + + * cc-mode.el (c-offsets-alist, c-read-offset, c-set-offset, + c-get-offset): added two new offset shortcuts, '* and '/ which + stand for *0.5 and *-0.5 respectively. + + * cc-mode.el (c-beginning-of-statement-1): + added a new CASE 4 to catch labels just above the current line. + +Thu Mar 30 19:00:02 1995 Barry A. Warsaw + + * cc-mode.el (c-protection-key, c-symbol-key): had to move these before + c-baseclass-key which uses them. + +Wed Mar 29 23:11:57 1995 Barry A. Warsaw + + * cc-mode.el: + (c-baseclass-key, c-mode, c++-mode, objc-mode, c-guess-basic-syntax): + This can be nil in all modes other than c++-mode. Make this variable + buffer local and it saves one looking-at call in the + c-guess-basic-syntax tight loop. + +Mon Mar 27 23:18:30 1995 Barry A. Warsaw + + * cc-mode.el (c-recognize-knr-p): default value is nil for all modes. + +Wed Mar 22 16:45:53 1995 Barry Warsaw + + * cc-mode.el: + CC-MODE style has to make a deeper copy of non-atomic lists + + * cc-mode.el: set "GNU" style just after creating the CC-MODE style + + * cc-mode.el: + added c-recognize-knr-p and c-hanging-comment-ender-p variables to + "CC-MODE". + + * cc-mode.el (c-C++-friend-key): new constant + + (c-guess-basic-syntax): use c-C++-friend-key to find friend + declarations. Note that template class friends don't start with the + word "friend". + + * cc-mode.el (c-indent-region): + wrap a backward-sexp call in a c-safe to avoid bogus error + conditions. + +Mon Mar 20 23:58:32 1995 Barry Warsaw + + * cc-mode.el: + Only add the "CC-MODE" style and set the "GNU" style on the first load + of cc-mode.el (not (featurep 'cc-mode)). + + (c-guess-basic-syntax): skip over case/default labels before skipping + over other labels. + + * cc-mode.el (c-style-alist, c-set-style): + "Default" style is renamed to "CC-MODE" style so as not to confuse + matters (too much). + + * cc-mode.el (c-indent-comments-syntactically-p): new variable + + (c-comment-indent): use c-indent-comments-syntactically-p instead of + comment-column==nil to control M-; acting like TAB. The latter + behavior was too broken to work correctly. + +Mon Mar 13 22:09:46 1995 Barry Warsaw + + * cc-mode.el (c-mode): setq comment-multi-line to t. + + * cc-mode.el (c-common-init): + (c-set-style "GNU") moved out of this defun and into the top level + of cc-mode.el. This is pushed down towards the bottom of the + file, to just after the calculation of the "Default" style. Also, + the style variables are not made buffer local until after this + call. Seems kludgy that its all order dependent, but it addresses + the problem of setq-default at the .emacs top level not doing the + expected thing. + +Thu Mar 9 21:31:28 1995 Barry Warsaw + + * cc-mode.el (c-guess-basic-syntax): CASE 5J: Watch out for + c-beginning-of-statement-1 leaving us at bob with a following comment. + + * cc-mode.el (c-comment-indent): + When comment-column is nil, indent according to c-offsets-alist, + i.e. behavior is identical to hitting TAB. + + * cc-mode.el (c-guess-basic-offset): + CASE 5D.5: skip over any access specifiers found if inclass-p. + CASE 5D.1: looking at a hanging member init colon only if not + attached to an access specifier. + + * cc-mode.el (c-guess-basic-syntax, c-lineup-comment): + TAB should always indent comment-only lines according to + c-offsets-alist. It should never pin comments appearing at + comment-column. Use M-; for that. + + * cc-mode.el (c-common-init): Default mode is now GNU + + * cc-mode.el (c-styles-alist): Mention the Default style. + + * cc-mode.el (c-offsets-alist-default): obsolete + + (c-offsets-alist): now contains default values. These will always be + captured in the "Default" style and all styles now inherit from + "Default". + + (c-offsets-alist, c-basic-offset, c-comment-only-line-offset, + c-block-comments-indent-p, c-cleanup-list c-hanging-braces-alist, + c-hanging-colons-alist, c-hanging-comment-ender-p, + c-backslash-column): All variables are now buffer-local. + + (c-set-style-1): new function + + (c-set-style): 1. removed &optional local argument -- use + make-variable-buffer-local instead if buffer local style settings are + desired; 2. Reset the style to "Default" before instituting the new + style. This means all styles derive from the "Default" style. + +Sat Mar 4 00:41:01 1995 Barry Warsaw + + * cc-mode.el (c-comment-only-line-offset): + Fixed the docstring to follow current semantics of the variable. + + (c-style-alist): Fixed GNU style for c-comment-only-line-offset to + '(0 . 0) so that column zero comments will not anchor. + + * cc-mode.el: + Moved the setup of the "Default" style to further down in the file. + Also, this uses the new c-add-style API. + + * cc-mode.el (c-add-style): + Added set-p flag for optional setting of the style. + + * cc-mode.el (c-conditional-key, c-class-key, c-comment-start-regexp): + setq-default their values to the `C' values so that + non-cc-mode-ized modes that rely on BOCM behavior still work + (e.g. awk-mode). + +Wed Mar 1 21:30:56 1995 Barry Warsaw + + * cc-mode.el (c-add-style): New command. + + * cc-mode.el (c-backward-to-start-of-if): + better error message for orphaned else + error. It now prints the line number of the orphaned else. + + * cc-mode.el: + added pending-delete and delete-selection properties for proper + co-operation with pending-del and delsel modes. + +Thu Feb 16 01:38:27 1995 Barry Warsaw + + * cc-mode.el (c-hack-state): + it is legal for cdr to be nil when 'close brace is + encountered. Do we need the (consp car) test??? + + (c-guess-basic-syntax): CASE 5H: Removed the test for preceding-char = + to ?:. This fixes two problems. First, in objc-mode, there is no + colon after access specifiers. Also, some people might use macros for + PRIVATE and PROTECTED, and these also don't have trailing colons. + +Wed Feb 15 15:38:37 1995 Barry Warsaw + + * cc-mode.el (c-electric-brace): + when ACTION is a function, the second argument is + the buffer position the brace was inserted, regardless of any + implementation details (i.e. may not be the same as where the brace + actually resides during the callout). + + (c-hanging-braces-alist): update docstring to new callout semantics. + +Tue Feb 14 19:54:50 1995 Barry Warsaw + + * cc-mode.el (c-beginning-of-statement-1): + when looking for an else-if clause, + watch out for #else gotchas. + +Mon Feb 13 23:14:51 1995 Barry Warsaw + + * cc-mode.el (c-guess-basic-syntax): + CASE 5D.3: syntactic symbol should be + 'inher-cont instead of 'inher-cont-1. + +Wed Feb 8 22:52:15 1995 Barry Warsaw + + * cc-mode.el (c-electric-brace): + In punt section, nil out the syntax cache too, + since its out-of-date. + +Tue Feb 7 17:38:42 1995 Barry Warsaw + + * cc-mode.el (c-electric-brace): + When hanging the brace, figure out when to punt + and recalculate the entire state. + +Mon Feb 6 17:07:45 1995 Barry Warsaw + + * cc-mode.el (c-whack-state): New function. + + (c-electric-brace): use c-whack-state to adjust state when inserting + hanging closing braces. + +Thu Feb 2 16:49:21 1995 Barry Warsaw + + * cc-mode.el (c-adjust-state): New function + + (c-electric-brace): make sure state is adjusted when preceding lines + are re-indented via c-indent-line. + +Mon Jan 30 16:49:10 1995 Barry Warsaw + + * cc-mode.el (c-safe-position): + takes a buffer position and a state list since it + must determine a safe position farther up the buffer than the give + buffer position. + + (c-electric-brace): use new c-safe-position call sequence + + (c-guess-basic-syntax): CASE 14: when finding relpos, and calling + c-b-o-s-1, lim must be higher in buffer than containing-sexp, so call + c-safe-position to find this position. + +Wed Jan 18 15:47:11 1995 Barry Warsaw + + * cc-mode.el (c-electric-brace): + When c-auto-newline is nil, no newlines or + re-indentation is performed. + + * cc-mode.el (c-guess-basic-syntax): + CASE 9D: after-cond-placeholder can be nil, + tripping up (max ...). + +Tue Jan 17 14:52:02 1995 Barry Warsaw + + * cc-mode.el (c-guess-basic-syntax): CASE 15D: safepos should be + c-most-enclosing-brace of fullstate. This could potentially be + slower, but it is accurate. + + * cc-mode.el (c-guess-basic-syntax): + CASE 15F: Watch out for lim == point. In that + case, use (c-safe-position state) as the most enclosing known safe + buffer position. + +Mon Jan 16 23:55:43 1995 Barry Warsaw + + * cc-mode.el (c-guess-basic-syntax): CASE 9D: Kludged fix for + c-beginning-of-statement-1 possibly leaving us at a buffer position + before lim `after-cond-placeholder'. c-b-o-s-1 should be fixed, but + I'm worried about side-effects at this point. It will be fixed in v5. + + * cc-mode.el (c-crosses-statement-barrier-p): + Do not reset lim if, after skipping + characters, point is inside a literal. Point in a literal, is not + considered safe. + +Wed Jan 4 23:57:11 1995 Barry Warsaw + + * cc-mode.el (c-snug-do-while): + Watch out for non-hanging open brace on `do'. + + * cc-mode.el (c-electric-brace): + In (memq 'before newlines) clause, when updating + the c-state-cache, point can be <= the (car of c-state-cache) for us + to strip out the most enclosing brace. + + * cc-mode.el (c-electric-delete): + Added delete-selection and pending-delete + 'supersede properties for proper "delete-erases-current-selection" + behavior. + +Wed Dec 28 16:05:02 1994 Barry Warsaw + + * cc-mode.el (c-indent-exp): + Don't try to call c-progress-fini if c-progress-init + was never called (i.e. due to error having been signaled). + +Wed Dec 21 00:28:24 1994 Barry Warsaw + + * cc-mode.el (c-electric-brace): + If the temporary newline must be deleted (because + it hangs), use delete-indentation instead of the delete-region + hackery. + + * cc-mode.el (c-snug-do-while): New function. + + (c-hanging-braces-alist, c-cleanup-list, c-electric-semi&comma): To + eliminate the newline between the brace that closes a `do' block and + the following `while', make the c-hanging-braces-alist ACTION for + 'block-close be 'c-snug-do-while by default. There is no more need + for the 'snug-do-while cleanup. + +Tue Dec 20 23:51:52 1994 Barry Warsaw + + * cc-mode.el (c-electric-brace): + In updating the cache during the 'before section, + watch out for c-state-cache being nil. + + * cc-mode.el (c-electric-brace): Implement new semantics for + c-hanging-braces-alist. Also, fix state cache during re-indentation + of preceding line when 'before newline is added. + +Mon Dec 19 23:30:47 1994 Barry Warsaw + + * cc-mode.el (c-intersect-lists, c-lookup-lists): New functions. + + (c-electric-brace, c-electric-colon): Use the new functions to + simplify the flow of logic in determining hanginess. + + * cc-mode.el (c-hack-state): + When adding a close brace, watch out for balanced + block sitting on list in car of cdr position. + + * cc-mode.el (c-electric-semi&comma): + Some minimal efficiency additions by + including a backscan limit. + + * cc-mode.el (c-electric-semi&comma, c-cleanup-list): + Added a new clean-up: + snug-do-while which will snuggle the `while' of a do-while up to after + the closing brace. + + * cc-mode.el (c-lineup-objc-method-args, + c-lineup-objc-method-call, c-offsets-alist-default, + c-beginning-of-statement-1, c-guess-basic-syntax): + Jumbo Lele Gaifax Objective-C patch. + +Fri Dec 16 15:41:05 1994 Barry Warsaw + + * cc-mode.el (c-guess-basic-syntax): + CASE 10: watch out for false else clauses + (e.g. else_thing). + +Wed Dec 14 23:11:59 1994 Barry Warsaw + + * cc-mode.el (c-postprocess-file-styles): + Renamed from c-find-file-hook. Hang this + off of hack-local-variables-hooks, which won't be supported until + future Emacs 19's. + +Tue Dec 13 23:58:48 1994 Barry Warsaw + + * cc-mode.el (c-beginning-of-statement-1): Watch out for lim! + + * cc-mode.el (c-hack-state, c-safe-position): New functions. + + (c-electric-brace, c-parse-state, c-inside-brace-list-p, + c-guess-basic-syntax): Implemented two major performance enhancements + used both in general, but also specifically during brace insertion. + First, call c-beginning-of-statement-1 directly instead of wasting + time in the user-command version. Second, and most importantly, + implement a c-parse-state cache so that the brace state for a + particular line doesn't have to be completely recalculated 4 times for + every brace insertion. + +Mon Dec 12 20:20:49 1994 Barry Warsaw + + * cc-mode.el (c-inside-bracelist-p): + Fixed aggregate logic w.r.t. failures in + forward-sexp. + + * cc-mode.el (c-inside-bracelist-p): + Order of magnitude improvement in performance + by eliminating often costly calls to c-backward-syntactic-ws. + +Fri Dec 9 23:39:31 1994 Barry Warsaw + + * cc-mode.el (c-inside-bracelist-p): + Special case speed up for when most enclosing + brace of brace-state is nil. + +Sat Sep 10 13:27:11 1994 Barry A. Warsaw (warsaw@anthem.nlm.nih.gov) + + * Public Release of 4.85. + +Wed Sep 7 18:41:29 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-mode-fsf-menu, c-mode-map, c++-mode-map, + objc-mode-map): + use a better feature test to figure out how to set the menu title + string. + +Tue Sep 6 13:49:46 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-search-uplist-for-classkey): + in `class' keyword verification section, only skip forward for ?> + template char if a matching ?< char was found previous to + search-start. This eliminates false match of template base + classes. + +Thu Sep 1 22:30:23 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-submit-bug-report): updated var list + + * cc-mode.el (c-mode-fsf-menu, c-mode-map, c++-mode-map, + objc-mode-map): + do a better job of getting the menu title string appropriate for + the mode being edited in. Bogus, but necessary. XEmacs is better + in this respect. + + * cc-mode.el (c-search-uplist-for-classkey): Lele patch for objc-mode + + * cc-mode.el (c-search-uplist-for-classkey): + avoid "invalid search bound" error + + * cc-mode.el (c-beginning-of-statement-1): + skip special modifier chars in all cases, not just in "no balanced + expr found" case. + + * cc-mode.el (c-guess-basic-syntax): + CASE 9: generalize and collect common code for finding position + after conditional statements, and check for `while' statement of a + `do' loop. In that case, skip over the trailing semi. + +Wed Aug 31 22:20:47 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-progress-init, c-progress-update, c-progress-fini): + use a marker for end (and be sure to free it!) so that as + indentation occurs, % can't go above 100. + + * cc-mode.el (c-mode-map): + check on feature (fboundp 'add-menu) for FSF 19 (which doesn't + have it). + + * cc-mode.el (c-progress-info, c-progress-init, + c-progress-update, +c-progress-fini): + new vars/defuns for better long indentation progress + reporting + + (c-indent-exp, c-indent-region): use new progress reporting + +Tue Aug 30 21:57:37 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-guess-basic-syntax): + CASE 6F, go forward 1 char from b-o-s of containing-sexp bufpos to + find proper relpos of an arglist-cont. + + * cc-mode.el (c-offset-alist-default): + statement-case-open default offset is zero + + (c-skip-case-statement-forward): new function + + (c-guess-basic-syntax): CASE 15: use c-skip-case-statement-forward in + proper places to find the real relpos of statement's inside switch + case/default bodies. CASE 15D: remove special handling when looking + at c-conditional-key. + + * cc-mode.el (c-offsets-alist, c-cleanup-list, c-mode-menu, + c-mode-map, c-symbol-key, c-indent-line, c-popup-menu): + make sure ObjC is properly documented. + + * cc-mode.el (c-least-enclosing-brace): new function + + (c-enclosing-brace, c-guess-basic-syntax): renamed + c-enclosing-brace to c-most-enclosing-brace + + (c-indent-defun): handle opening braces not in column 1 + + * cc-mode.el (c-beginning-of-statement-1): + skip over statement mod characters that don't preceed an open + paren. + +Fri Aug 26 17:42:24 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-guess-basic-syntax): + be careful to check for c-access-key non-nil before calling + (looking-at c-access-key). For C, this is nil. + + * cc-mode.el (c-beginning-of-statement-1): + swapped CASE 3 and 4, so that conditional statements are picked up + properly + + * cc-mode.el (c-guess-basic-syntax): + CASE 15D, calculate relpos from boi of beginning of statement + prior to indent-point, unless we're looking at a conditional key + + * cc-mode.el (c-mode-map, c++-mode-map, objc-mode-map): + change test of 'FSF in c-emacs-features to an fboundp + set-keymap-parent test + +Thu Aug 25 13:31:31 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-just-after-func-arglist-p, + c-guess-basic-syntax, c-lineup-objc-method-args-2): + more objc patches from Lele + +Wed Aug 24 21:06:05 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-indent-command): + with optional arg, shift-amt had wrong sign + + * cc-mode.el (c-lineup-arglist): + better handling of comments preceding arg lists + + * cc-mode.el (c-guess-basic-syntax): + swapped CASE 6A and 6B so that empty arglists with close paren on + separate line are properly recognized. + + * cc-mode.el (c-mode-menu, c-emacs-features, c-mode-map, + c-common-init): + remove dependency on string "Lucid" in emacs-version. Use + features based means where such descrimination is necessary. + +Tue Aug 23 18:43:28 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-fill-paragraph): + merge with c-mode.el uses fill-region-as-paragraph + + * cc-mode.el (c-offsets-alist-default, c-offsets-alist, + c-hanging-braces-alist, c-electric-brace, c-guess-basic-syntax): + added syntactic symbol statement-case-open for + statement-case-intro's that contain an open brace. + + * cc-mode.el (c-lineup-math): watch for equal signs in literals + + * cc-mode.el (c-beginning-of-statement-1): + CASE5 and CASE 6, better pick up of label's with potential + embedded colons (scope operators). + +Mon Aug 22 22:28:03 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-hanging-comment-ender-p): new variable + + (c-fill-paragraph): looks at c-hanging-comment-ender-p to see if + */ should be left on its own line. c-mode.el behavior is default + value t, but there have been *many* requests for nil's behavior. + +Wed Aug 17 23:05:01 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-recognize-knr-p, c-common-init): + fix the way this var is made buffer local + +Tue Aug 16 20:05:49 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-recognize-knr-p, c-mode, c++-mode, objc-mode): + make it so c-recognize-knr-p is settable from c-mode-common-hook. + +Thu Aug 11 20:40:06 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-recognize-knr-p): new variable + + (c-offsets-alist-default, c-offsets-alist, c-guess-basic-syntax): + changed syntactic symbol c++-funcdecl-cont to ansi-funcdecl-cont + + (c-mode, c++-mode, objc-mode): use new c-recognize-knr-p variable + + (c-guess-basic-syntax): use new c-recognize-knr-p variable; swap + CASE 5B.2 and 5B.3. + +Wed Aug 10 17:54:53 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-offsets-alist, c-read-offset, c-set-offset): + can accept variable symbols as offsets. + + (c-get-offset): can now accept ++ and -- symbols, which evaluate + to 2* positive and negative c-basic-offset. + +Thu Aug 4 15:29:43 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-guess-basic-syntax): + case 9C added small performance improvment to c-in-literal call + +Wed Aug 3 17:37:30 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-beginning-of-statement-1): + use c-in-literal-cache, and limit backscanning in CASE 5 to known, + non-literal position. + + * cc-mode.el (c-in-literal, c-guess-basic-syntax): + caching of last literal result + +Tue Aug 2 20:18:10 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-guess-basic-syntax): + CASE 15D, calculate 'statement relpos as the + beginning-of-statement relative to indent-point. + + * cc-mode.el (c-beginning-of-statement-1): + CASE 4, check for conditional keywords which could be followed by + a balanced paren expr. I.e. while(foo) + +Tue Jul 26 15:55:21 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c++-mode-syntax-table, objc-mode-syntax-table): + give CR same syntax as newline, for selective-display. + +Fri Jul 22 18:42:38 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-electric-star): + fixed indentation problem when a star is not preceded by a slash. + + * cc-mode.el (c-indent-defun): + removed condition-case inside unwind-protect. All error + conditions are properly handled at other levels of the code. + +Thu Jul 21 22:34:19 1994 Barry A. Warsaw, ITB + + * cc-mode.el (c-class-key, c-search-uplist-for-classkey): + greatly simplified, this constant now contains a regexp that only + matches valid `class' keywords, in the C++ sense. It now ignores + any template, extern, static, etc. keywords. + +Tue Jul 19 09:53:37 1994 Barry A. Warsaw (warsaw@anthem.nlm.nih.gov) + + * Public Release of 4.35. + +Sun Jul 17 18:29:51 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-syntax): + Lele Gaifax's patch to fix an Objc problem... + + "this patch, applied to 4.32, will correct a little bug in ObjC + mode. Currently objc-mode fails to recognize a continued arglist, + as it guesses every such construct is a continued method call." + +Fri Jul 15 13:48:39 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-search-uplist-for-classkey): don't get fooled by + the following C construct: + + struct shmid_internal + shmconv( + register int s) + { + int foo = 1; + } + +Tue Jul 12 14:36:10 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-parse-state): in body of `something bad happened' + part, don't use beginning-of-defun to find "real" bod since based + on some coding styles, this could loop us all the way back to + bob. E.g.: + + int foo() { + int a = 7; + { + foobar(); + }} + + int foo() { + int a = 7; + { + foobar(); + }} + + + Instead use scan-lists and be more robust about crossing + unbalanced close braces. Now even antisocial coding styles like + the above can be quickly parsed correctly. + + * cc-mode.el (c-parse-state): small but important fix in + `something bad happened' test. make sure that placeholder close + brace ends up before indent point, otherwise we didn't cross it. + +Thu Jul 7 13:56:08 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-parse-state): in `something bad' section, + placeholder will always be just after any close brace so we need + to 1- from it to check for ?}. Also, we probably don't need to + check for placeholder-1 being nil. + +Thu Jun 30 21:03:55 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-switch-label-key): a paren can follow the `case' + keyword without any intervening whitespace. + + * cc-mode.el (c-beginning-of-statement-1): when skipping over + unary ops, remember that whitespace could be intermixed before the + paren + + * cc-mode.el (c-electric-brace): added brace-list-intro and + brace-list-entry to list of hangables + + (c-hanging-braces-alist): added docstring for b-l-i and b-l-e + hangability + + * cc-mode.el (c-beginning-of-statement-1): CASE 6: be sure to + ignore switch labels too. + + * cc-mode.el (c-lineup-arglist-intro-after-paren): new lineup + function to conform to GNU style. + + (c-style-alist): for style GNU, arglist-intro set to + c-lineup-arglist-intro-after-paren and arglist-close set to + c-lineup-arglist to conform to BOCM GNU style. + +Wed Jun 29 00:48:56 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-syntax): installed this patch: + + In ObjC mode 4.6 the tests 6D and 6E in c-guess-basic-syntax need + to be swapped. Otherwise what is a continued method call line will + be recognized as a 'arglist-cont-nonempty. Swapping these test + will not interfere with the normal behaviour of cc-mode, since the + test for the method call is surrounded with a test on (eq + major-mode 'objc-mode). + + Emanuele (lele) Gaifax | ...calling Emacs convenient, of course, is + lele@nautilus.sublink.org | like calling oxygen useful -- Rens Troost + + * cc-mode.el (c-mark-function): new implementation based on + c-parse-state. I think this should work much better for people. + +Tue Jun 28 23:57:42 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-just-after-func-arglist-p): partial fix for this bug: + + class foo + { + foo() + : // member-init-intro + a (0), // topmost-intro-cont??? + b (0) // member-init-cont + {} + }; + + + note that if there is a comment after foo(), its still broken. + But that probably won't happen too often... + + * cc-mode.el (c-lineup-arglist): don't limit skippages forward + over syntactic ws to eol. + +Mon Jun 27 18:25:42 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-parse-state): when looking to see if `something + bad happened', and guaranteeing that the char-after placeholder is + = to ?}, make sure that char-after placeholder is less than + point-max (i.e. char-after placeholder returns non-nil). + + * cc-mode.el (c-electric-star): should not re-indent line if + introducing a comment not on a comment-only line + +Thu Jun 23 17:54:49 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-inside-bracelist-p): when finding an enum, check + to be sure its not a type descriptor on a return value of a func + (i.e. skip-chars-forward for not semi or open paren). + +Wed Jun 22 19:23:43 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-parse-state): when trying to find out if + "something bad happened" be sure to check for crossing a close + *brace* and not a close paren or square bracket. Only crossing a + close brace indicates badness. + +Mon Jun 20 00:32:46 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-set-offset): initial contents of prompt is the + last syntactic symbol on the syntactic analysis list -- the most + likely symbol that the user wants to change. + +Fri Jun 17 22:25:41 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-lineup-arglist): fixed problem of skipping too + many close parens when finding the relpos of arglist-close. + + * cc-mode.el (c-guess-basic-syntax): CASE 6F fixed incorrect + relpos + + * cc-mode.el (c-guess-basic-syntax): CASE 8B and CASE 8C: when an + otherwise brace-list-entry or brace-list-intro is found to start + with an open brace, the line is given brace-list-open syntax + instead + + (c-inside-bracelist-p): fix small bug in recognizing open brace at + brace-list-intro line, and infinite loop problem. + + * cc-mode.el (c-inside-bracelist-p): more accurate handling of + nested aggregates. Now uses brace-state as provided by + c-parse-state. + +Tue Jun 14 22:25:09 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-forward-conditional): break infinite loop when + finding commented out conditionals + +Mon Jun 13 17:40:08 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-submit-bug-report): Use new interface for + reporter.el 2.x + +Fri Jun 10 13:42:02 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-submit-bug-report): remove defun-prompt-regexp + from the list of vars if it is not boundp (i.e. v18) + +Thu Jun 9 14:15:00 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-syntax): repaired all CASE numbers + + * cc-mode.el (c-offsets-alist-default): added syntactic symbols + objc-method-intro objc-method-args-cont objc-method-call-cont. + + (c-offsets-alist): added descriptions for above new syntactic symbols + + (objc-mode-hook) (objc-mode-abbrev-table) (objc-mode-map) + (objc-mode-syntax-table) (objc-mode): added for Objective-C support + + (c-objc-method-key): new regexp desribing an ObjC method intro. + + (c-electric-slash): objc-mode understands // comments + + (c-fill-paragraph): objc-mode understands // comments + + (c-beginning-of-statement-1): added CASE 7 for objc-mode + + (c-in-objc-method-def-p): checks to see if inside an Objective-C + method definition. + + (c-just-after-func-arglist-p): check for Objective-C method def + + (c-guess-basic-syntax): many modifications to look for Objective-C + syntactic symbols: CASE 3.5, CASE 4G, CASE 4I, CASE 5E. + + (c-lineup-objc-method-call) (c-lineup-objc-method-args): new custom + lineup functions for Objective-C methods. + + (c-submit-bug-report): look for ObjC mode + +Mon Jun 6 19:47:19 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-style-alist): another fix to Ellemtel style. + Since the style guide recommends braces around the body of all + case statements, statement-case-intro should be 0, letting + statement-block-intro of the following line pick up the proper + indentation + + * cc-mode.el (c-style-alist): Ellemtel style should have + c-hanging-braces-alist for substatement-open be before and after + +Thu Jun 2 23:09:16 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-strict-syntactics-p): changed to c-strict-syntax-p + + (c-guess-basic-syntactics): changed to c-guess-basic-syntax + + (c-add-syntactics): changed to c-add-syntax + + (various): use new function and variable names + +Wed Jun 1 15:46:19 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: bumping to version 4 in anticipation of objc-mode + support + +Tue May 31 23:51:08 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-strict-semantics-p): changed to c-strict-syntactics-p + + (c-echo-semantic-information-p): changed to + c-echo-syntactic-information-p + + (c-semantics): changed to c-syntactic-context + + (c-guess-basic-semantics): changed to c-guess-basic-syntactics + + (c-show-semantic-information): changed to c-show-syntactic-information + + (cc-mode.el): other internal changes to make terminology consistent + + * cc-mode.el (c-guess-basic-semantics): + CASE 14.E, if defun opening brace is not at + boi, its because its hung on right side so we need a different relpos + + * cc-mode.el (c-guess-basic-semantics): + CASE5, various. Extend the notion of + arglists to bracket lists, i.e. [...] + + * cc-mode.el (c-search-uplist-for-classkey): + when skipping over commas after + classkey's watch out for inheritance lists... + + * cc-mode.el (c-beginning-of-statement-1): + ignore labels and access keys + +Tue May 24 22:04:15 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * Public Release 3.349 + + * cc-mode.el (c-search-uplist-for-classkey): + break out of infinite loop when + finding `struct' keyword in arglist + +Mon May 23 15:43:07 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-electric-brace): + we need to recalculate semantics if, when + re-indenting the preceding line, point changes. If this happens, the + relpos for semantics is invalid. + +Thu May 19 22:27:55 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-style-alist): + updated the various styles to set the correct values + for substatement-open + + (c-style-alist): added dynamic setting of default style. The way this + works may or may not be a feature? + +Wed May 18 22:07:15 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-backward-to-start-of-if): + fix to correctly handle `else-if' + clauses, which should be skipped when looking for the matching if. + + * cc-mode.el (c-search-uplist-for-classkey): + don't get confused by a single struct + type arg in a function's arglist + + * cc-mode.el (c-beginning-of-statement-1): + on backward-sexp failure, skip over + funny chars and whitespace only when just before a paren + + (c-search-uplist-for-classkey): watch out for comma ending struct arg + declarations which doesn't leave us in a class definition. + + * cc-mode.el (c-mode-map): + fix the setting of mode-popup-menu for Lemacs 19.10. + Menu must have a title string. + + * cc-mode.el (c-style-alist): + changes to Ellemtel style: substatement sets its + offset to 3, substatement-open sets its offset to 0. Given by: + Lars Lindberg. + +Tue May 17 22:46:22 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-beginning-of-statement-1): + when backward-sexp fails and doing + backward-up-list, and before skipping over noise characters, skip over + any preceding syntactic whitespace: + + --------------V + if ( ! backup_dev || + sep1 != ':' || ) + + * cc-mode.el (c-beginning-of-statement-1): + fixed small infinite loop in CASE5 test + when barrier char is in literal. + + * cc-mode.el (c-guess-basic-semantics): + CASE 13: don't limit the search backwards + for the beginning of statement + + * cc-mode.el (c-beginning-of-statement-1): + completely rewritten to properly account + for cpp macros and statement barrier characters (e.g. { } ;) in + literals. + +Mon May 16 20:21:12 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-inside-bracelist-p): + must check that enum keyword truly introduces + a bracelist and not that it is a type identifier for a declaration. + + I.e. match: + + enum foo { /* ... */ } + + but not: + + enum foo bar; + +Thu May 12 22:52:12 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + CASE 4A.2 watch out for enum keywords in + K&R argdecl lists. These don't open enum definitions, but they are + declarations instead. E.g.: + + ret_stat (rpt_stat, filename, pcode) + enum xrpt_status_codes rpt_stat; + char filename[]; + enum xpippop_codes pcode; + { + + * cc-mode.el: + (c-C-conditional-key) (c-C++-conditional-key): new regexps which + describe conditionals in the two supported languages. This is + necessary because `try' and `catch' blocks are defined as + substatements equivalent to `while', `for', etc., in C++ only + + (c-mode) (c++-mode): set c-conditional-key, which is now buffer-local, + to either c-C-conditional-key or c-C++-conditional-key. + + * cc-mode.el (c-parse-state): + when we discover that an open brace we thought + specified the bod, actually isn't the bod, we backup and search for + another potential bod. This is necessary so that open braces in + column zero that aren't really defun opening braces don't trip us up. + Our test for invalid bod is if we cross over an unbalanced close + brace. + + * cc-mode.el (c-guess-basic-semantics): + CASE 4G, in c-mode, fix recognition of the + last line in the following construct: + + typedef int (*foobar) /* if I break this into 2 lines ...*/ + (int foo, char *bar); + extern foobar really; /* this is incorrectly indented */ + +Tue May 10 16:42:13 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-indent-region): + fixed a bug where comment-only lines were being + skipped. Wrapped an unwind-protect around mark copying so we can't + leak marks. + + * cc-mode.el (c-emacs-feature): use variables emacs-major-version and + emacs-minor-version if they exist + +Fri May 6 21:09:58 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-style-alist): + small changes to the Ellemtel style: inline-open and + topmost-intro-cont are changed to 0 offset. + + * cc-mode.el (c-hanging-braces-alist): + added (substatement after) so that braces + will hanging on substatement blocks + +Thu May 5 22:48:23 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-lineup-math): + can now line up equals signs even if the equals isn't + at boi. E.g., it can now handle: + + float a = 1.0, + b = 7, + c = 9; + + * cc-mode.el (c-comment-start-regexp): + new buffer-local variable which describes + how comments start. This improves generality for C-like modes with + different comment intro styles. + + * cc-mode.el (c-indent-via-language-element): + renamed to c-indent-line for better + backwards compatibility, i.e. awk-mode + +Tue Apr 26 16:17:29 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-parse-state): + make sure we ignore any bogus beginning-of-defun + bufpos's when we're searching back 2 bods + + * cc-mode.el (c-search-uplist-for-classkey): + after finding what looks like a class + header, search for both a semi (denoting a fwd decl), and an equals + (denoting a struct init). + +Thu Apr 21 21:12:26 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + (c-electric-brace) (c-electric-semi&comma) (c-electric-colon) + (c-indent-command) (c-indent-exp) (c-indent-region) + (c-indent-via-language-element): eliminated extraneous optional + arguments, i.e. lim and bod + + * cc-mode.el (c-adaptive-block-open): obsolete + + (c-offsets-alist-default) (c-electric-brace): added substatement-open + syntactic symbol + + (c-hanging-braces-alist): added ability to hang substatement-open + braces. + + (c-style-alist): changed defaults of block-open to substatement-open + + * cc-mode.el (c-safe): + use Dan LaLiberte's version impl. workaround for an FSF + 19.22 bug + +Tue Apr 19 15:15:41 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-mode-map): put c-macro-expand on C-c C-e + + * cc-mode.el: + (c-mode-map) (c-common-init): put in code to conform to Lucid 19.10's + popup menu convention of using mode-popup-menu variable + +Fri Apr 15 23:09:59 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-indent-defun): handle buffer-read-only errors better + + * cc-mode.el (c-lineup-math): also lines up multi-line equal signs + + * cc-mode.el (c-guess-basic-semantics): + replaced calculation of literal which must + have gotten accidentally removed some time ago. + + * cc-mode.el (c-1bit-il): + removed since it appears to be identical to c-in-literal, + and thus obsolete. + + * cc-mode.el (c-search-uplist-for-classkey): + programmatically ignore the `class' + keyword inside template arg lists + + (c-enclosing-brace) (c-narrow-out-enclosing-class): new helper + functions + + (c-guess-basic-semantics): fixed recognition of 'defun-open CASE 4A.4, + CASE 13.A, 'block-close CASE 13.B, 'defun-block-intro CASE 14.E + +Thu Apr 14 18:42:00 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-parse-state): + record containing paren, but not balanced paren sexps + + * cc-mode.el (c-guess-basic-semantics): + fixed a regression problem in recognizing + the difference between an inline-close and a nested class-close + + * cc-mode.el: (c-parse-state) (c-guess-basic-semantics) + (c-search-uplist-for-classkey): massive rewrite of all parsing + components. c-parse-state now uncovers the brace nesting level of the + construct from (bod 2) to point and the other two defuns use this + information to make scooting around brace levels much quicker and more + accurate. + +Thu Apr 7 14:34:28 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-electric-brace): + can now specify `hanginess' on close braces + +Thu Mar 31 15:10:09 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * Public release: 3.304 + + * cc-mode.el (c-search-uplist-for-classkey): + class relpos should be at the 'boi of + where c-class-key gives us a match. This is because its too hard to + make c-class-key match the typedef keyword on: + + typedef struct Foo + { + + so its easier to make this fix instead. + +Fri Mar 25 20:34:18 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + (c-forward-syntactic-ws) (c-backward-syntactic-ws): minor speed ups + achieved by calling forward-comment with a huge number so we don't + have to return to the lisp loop after just 1 comment. + + * cc-mode.el (c-search-uplist-for-classkey): + added another speedup where syntactic + whitespace is skipped before doing a re-search-forward. This requires + however that the buffer be narrowed during the r-s-f because of the + definition of c-class-key which matches \\` or empty-string-at-bod. + It would be better to use \\`\\|\\= to match empty-string-at-point, + but that's not defined for v18, and doesn't seem to work anyway, at + least in Lemacs. + + (c-search-uplist-for-classkey): after finding a match for c-class-key, + skip non-semicolons up to brace point. If a semi is found, we're + looking at a forward declaration, not a class definition. + +Thu Mar 24 18:43:38 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): do not limit calls to + c-search-uplist-for-classkey to just c++-mode since even in C we can + have nested structs and unions. + + (c-search-uplist-for-classkey): now returns a vector instead of a + cons cell + + (c-guess-basic-semantics): modifications for new c-s-u-f-c return + value + + * cc-mode.el: + (c-inside-bracelist-p) (c-guess-basic-semantics): when looking for an + enum brace-list, c-beginning-of-statement could leave us at point-min, + which could contain an intervening comment, so you need to call + c-forward-syntactic-ws. + +Wed Mar 23 23:22:37 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-search-uplist-for-classkey): + another fix for infinite loops that + can occur when indenting inside the second of multiple nested classes. + This should also speed things up by further limiting the region being + searched. + +Tue Mar 22 23:12:58 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-mark-function): + worked around call to backward-paragraph, which + didn't work and wasn't the right semantics anyway. Movement should be + by beginning-/end-of-defun. + + * cc-mode.el (c-indent-exp): + restructure the unwind-protect call to ensure that the + `end' marker is always removed on any error condition. + + (c-indent-exp): find any open brace that occurs after point, ignoring + lexical whitespace, including newlines. + + * cc-mode.el (c-inside-bracelist-p): + in the first goto-char, goto containing-sexp, + not 1- c-s, otherwise, it will not properly recognize bracelists with + comments on the end of the line. The following + c-beginning-of-statement will properly consume any preceding + whitespace. + +Mon Mar 21 22:01:25 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-search-uplist-for-classkey): + must handle nil return value from + scan-lists. + + * cc-mode.el (c-search-uplist-for-classkey): + fix problem of infinite loops when + there are balanced expressions between (bod 2) and the indent-point + that aren't picked up by bod because they don't match + defun-prompt-regexp. We skip over this noise with scan-lists. + + * cc-mode-18.el: + don't hack c-emacs18-common-hook onto c-mode-common-hook anymore. tell + users to put it on their c-mode-common-hook themselves. + + * cc-mode.el (c-search-uplist-for-classkey): end-of-defun can fail + +Fri Mar 18 21:38:31 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-search-uplist-for-classkey): + new performance tuned version. Here + are some numbers: hitting tab at the end of an 11k function, with an + 8k function just before it was giving me 2.637sec for + c-indent-command, and 1.784sec for c-s-u-f-c alone. Now I'm getting + 0.972sec for c-i-c and 0.180sec for c-s-u-f-c. An order of magnitude + improvement in c-s-u-f-c. These are un-bc'd times. Other bottlenecks + must exist in c-i-c... + + * cc-mode.el: + added an eval-when-compile to pick up the reporter-* symbols when + byte-compiling. + +Thu Mar 17 20:56:04 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-electric-colon): + do scope-operator clean up immediately after + self-insert-command so that subsequent indentation and hanging + calculations will be performed correctly + +Tue Mar 15 23:29:16 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-search-uplist-for-classkey): + adjust for the fact that c-class-key + now match 1 character before the `c' in "class". goto-char 1+ foundp + to get to the proper character starting the class definition. + + * cc-mode.el (c-read-offset): new helper function for c-set-offset + + (c-set-offset): sanity check OFFSET argument both interactively and + non-interactively. This seems to trip up many novices. + + * cc-mode.el (c++-mode-map): + fixed binding for c-scope-operator. It is now on C-c : + +Fri Mar 11 23:45:51 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode-18.el (c-emacs18-il): applied patch contributed by + SAKAI Kiyotaka(ksakai@mtl.t.u-tokyo.ac.jp) to fix infinite loop bug. + + * cc-mode.el (c-fill-paragraph): removed last 2 c-mode.el dependencies + + * cc-mode.el (c-guess-basic-semantics): + CASE 8C: after moving to placeholder, which + is bos, move over any conditional statments if looking at + c-conditional-key. Otherwise the following code indents incorrectly: + + main() + { + while (cin >> float) + cout << float + << float; // This should not be this far over but beneath << + } + + * cc-mode.el (c-indent-exp): + put an unwind-protect around the sanity checks so that + point is restored on error + + * cc-mode.el (c-class-key): another fix to recognize keyword + `class' at beginning-of-buffer. + + (c-guess-basic-semantics): if class opening brace is not the last + non-whitespace on a line, the narrow-to-region narrowing out of + enclosing class will not have the proper begin point. Make sure the + region does not contain the class opening brace. + + * cc-mode.el (c-indent-region): + fixed error signal when indenting region not + containing balanced sexp. e.g. at the top level: + + int i, + j, + k; + + * cc-mode.el (c-class-key): + another fix to recognize nested class but not the word + 'class' in a template declaration + +Thu Mar 10 23:32:37 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-beginning-of-statement-1): + sped up about 8x by removing an + unnecessary (I think) call to c-backward-syntactic-ws and a duplicate + call to c-in-literal. By using elp, I think these were the real time + hogs in c-b-o-s-1 which was the biggest hog in + c-guess-basic-semantics. + +Wed Mar 9 22:15:26 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-lineup-arglist): + added a (beginning-of-line) call before the + (backward-up-list 1) call in the special case for arglist-intro and + arglist-cont-nonempty. Without this, indentation would be different + when point was at the beginning and end of line. E.g.: + + main() + { + if ((BuddyRec* buf = (BuddyRec*)(bufs[message_bufs++] + = ::new unsigned char[MessageBufSize])) + == 0) { + } + } + + + On the "== 0) {" line. + + * cc-mode.el (c-indent-exp): + try to be smarter about finding the beginning of the + balanced expression to indent. Gives results closer to old + indent-c-exp behavior. + + * cc-mode.el (c-submit-bug-report): + moved the require of reporter to after the + y-or-n-p question. Shortened the package name so it will fit on the + Subject line better. + +Mon Mar 7 17:39:45 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-skip-conditional): + new function. factorized duplicate code + + (c-guess-basic-semantics): fixed statement-cont relpos calculation in + a continued statement following an else clause. CASE 8A and 8D changed + to use c-skip-conditional. + +Mon Feb 28 18:23:36 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-conditional-key): + not sufficient to wrap conditional keywords in + \\<...\\> since this will false hit a keyword followed by an + underscore, which technically isn't a keyword. An example is + "do_table" which incorrectly gets marked as a `do' keyword. + +Fri Feb 25 23:01:45 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + swapped CASE 7A and 7B so that we properly + indentify a brace-list-close of an empty brace list. + + * cc-mode.el (c-style-alist): + added the "Ellemtel" style which implements the + coding style defined in "Programming in C++, Rules and + Recommendations, Erik Nyquist and Mats Henricson, Ellemtel, ftp from + euagate.eua.ericsson.se". + + * cc-mode.el: (c-point) (c-indent-defun): only check the value of + defun-prompt-regexp if it is boundp (so v18 doesn't break) + +Thu Feb 24 23:34:08 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-electric-brace): + fixed bug in temporary newline insertion when + auto-newline is off. If a temp newline was not inserted, don't try to + delete it later on. + + * cc-mode.el (c-set-offset): + changed the minibuffer prompt. "Langelem" => + "Syntactic symbol", and put in a brief message so that people won't + quote the symbol (as some novices have been doing). + + * cc-mode.el (c-guess-basic-semantics): + CASE 4B.1, check for member init colon + preceding point even after doing a forward-char -1. Need to skip over + constructor parameter list that span multiple lines, with the member + init colon hanging on the last of those line. + + CASE 4D.1. added a backward-sexp call to handle member-init-cont's + which are paren-lists broken across multiple lines. + + * cc-mode.el (c-inhibit-startup-warnings-p): + new variable, used in c-emacs-features + + (c-emacs-features): rewrote feature extraction logic to be based on + version numbers. This more closely reflects the current state of + affairs of the main Emacs flavors. There is sanity checking and + warning messages built-in too, to help inform the user if there are + known problems. + +Mon Feb 21 18:13:53 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + swap case 4A.2 and 4A.3 so that brace-lists + are checked before inline-open's, otherwise enums inside of classes + are not recognized properly. + + * cc-mode.el (c-backslashify-current-line): + use kill-region instead of kill-line so + we don't have to use the kill-lines-magic hack. + + * cc-mode.el (c-beginning-of-statement-1): + do not register last-begin when looking + at a case/default label, otherwise statement-cont lines after a case + label will not be associated with the correct beginning-of-statement + +Fri Feb 18 16:13:27 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-lineup-arglist): + must handle arglist-intro lines just like + arglist-cont-nonempty lines in the calculation of containing-sexp in + the let* statement. + + (c-lineup-arglist): do not hard-code offset to 2 if at the end, we are + still looking at the eol. I don't know why that was there... + + * cc-mode.el (c-guess-basic-semantics): + CASE 4I, topmost-intro-cont's relpos must + be the boi of the beginning-of-statement, otherwise multiple t-i-c + lines get marching indentation. + +Thu Feb 17 23:53:16 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-set-style): + changed the sense of the optional argument. Now, style + changes modify the global variables by default, except when a non-nil + second argument is given. Only then are buffer-local versions of the + variables made. + + * cc-mode.el (c-lineup-arglist): + fixed calculation of containing-sexp for the + following code: + + main() + { + if( someFunction(someArg, + anotherArg) && + someOtherFunction(someArg, + anotherArg)) + doThis(); + } + + * cc-mode.el (c-class-key): + fixed class recognizing regexp so that it doesn't + falsely match the word `class' in a template function declaration, + e.g.: + + template + int A::foo( + + * cc-mode.el (c-mode-map): + moved c-indent-defun to C-c C-q. This should be its + final resting place + + (c-lineup-math): new optional custom indent function, not used by + default. + + * cc-mode.el (c-mode-map): + moved c-indent-defun from C-M-x to C-c C-i. RMS says + C-M-x is reserved. + +Wed Feb 16 23:06:15 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-mode-syntax-table): + change : back to default (. == punctuation) + syntax class since c-label-key is busted when its (_ == symbol) + + * cc-mode.el (c-lineup-runin-statements): + new lineup function for people who hang + the first statement after the open brace. + + (c-offsets-alist-default): added comment about alternative indentation + style for `statement' + +Mon Feb 14 15:53:30 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-point): + when defun-prompt-regexp is non-nil, b-o-d doesn't leave us + at the brace, so we need to skip it as noise. + + * cc-mode.el (c-indent-defun): if defun-prompt-regexp is non-nil, + beginning-of-defun won't leave us at the open brace, so we must skip + over defun-prompt-regexp... its noise. + +Fri Feb 11 20:49:19 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + CASE 14.C, when looking for a ?: construct, + and checking for not looking at a :: scope operator, make sure we do + this comparison at indent-point, instead of the first non-blank line + in the block + + * cc-mode.el (c-guess-basic-semantics): + CASE 8C: if first stream-op is on a + separate line (i.e. not on the `cout' line), it should be indented + like a statement-cont, not a stream-op. Relpos in this case is boi of + the first preceding non-syntactic-ws line + + * cc-mode.el: (c-backward-to-start-of-if) (c-backward-to-start-of-do) + (c-guess-basic-semantics): It is not enough to search test for + looking-at "keyword\\b" since this will not catch "keyword_thing", + which is a valid symbol and not a keyword. There is no equivalent of + \\b that matches at the end of a word-or-symbol string. For now, I + changed the looking-at's to "keyword\\b[^_]" which seems to work. + There are probably instances of "keyword\\>" that are broken too, but + we'll hit them as they occur, since I'm not sure they are broken. + +Thu Feb 10 23:30:11 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-populate-syntax-table): + only put c-mode/c++-mode common syntax + entries into syntax table. + + (c++-mode-syntax-table): colon (:) gets symbol class + + * cc-mode.el: + (c-mode-hook) (c++-mode-hook) (c-mode-common-hook): added defvars for + completeness. + +Wed Feb 9 17:48:21 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * Public release: 3.229 + + * cc-mode.el (c-electric-braces): + when calculating the initial semantics of the + open brace, we only need to insert a temporary newline if there is + non-whitespace preceding the brace, on the same line. + + * cc-mode.el (c-guess-basic-semantics): + CASE 4I, don't add `inclass' semantics to + the list since the relpos already has any inclass offset added in. + Otherwise we get inclass offsets added twice. + + * cc-mode.el (c-guess-basic-semantics): + fixed small problem introduced in version + 3.235. when skipping lexical whitespace, we must skip [ \t\n]. + newline wasn't getting skipped. + +Tue Feb 8 22:05:48 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + (c-offsets-alist) (c-offsets-alist-default): added `friend' syntactic + symbol for recognition of C++ friend declarations. Default offset is + 0. + + (c-guess-basic-semantics): recognize C++ friend declarations, and add + `friend' syntactic symbols as a modifier. + + * cc-mode.el (c-guess-basic-semantics): + when narrowing out enclosing class, and + calculating start of region to narrow to, do not skip all syntactic + ws, just lexical whitespace (change c-forward-syntactic-ws call to + skip-chars-forward). Otherwise, you could skip into the middle of a C + comment block and not figure out that what you're looking at is a `c' + syntactic symbol. + + * cc-mode.el: + (c-offsets-alist) (c-offsets-alist-default) (c-guess-basic-semantics): + added defun-block-intro syntactic symbol which controls indentation + for the first line in a top-level defun, analogous to + statement-block-intro. (CASE 14.E) + + * cc-mode.el (c-indent-defun): + catch any errors that occur in c-indent-exp and make + sure point is restored and the temporary mark is destroyed. + + * cc-mode.el: (c-untame-characters) (c-backscan-limit) (c-tame-insert) + (c-tame-comments) (c-emacs18-fsws) (c-emacs18-bsws) (c-emacs18-il): + moved these defuns and vars to cc-mode-18.el file. + + (c-mode-map): do not install Emacs 18-only bindings + + (c-populate-syntax-table): do not install Emacs 18-only syntax table + entries + + (c-insert-and-tame): renamed to c-insert-special-chars and make this + call only self-insert-command. Don't worry about Emacs 18 + compatibility. + + (c-mark-function) (c-common-init): Don't worry about Emacs 18 + compatibility. + + (c-emacs19-accurate-fsws): renamed to c-forward-syntactic-ws. Don't + worry about Emacs 18 compatibility. + + (c-emacs19-accurate-bsws): renamed to c-backward-syntactic-ws. Don't + worry about Emacs 18 compatibility. + + (c-8bit-il): renamed to c-in-literal. Don't worry about Emacs 18 + compatibility. + + (c-submit-bug-report): remove reporting of c-backscan-limit and + c-untame-characters since these are for Emacs 18 only. + +Wed Feb 2 00:00:40 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-lineup-arglist): + add kludge for arglist-cont-nonempty to get + correct indentation. + + (c-guess-basic-semantics): CASE 5D: arglist-cont-nonempty's relpos + needs to be boi of containing-sexp paren. this is good for + offset, + but bad for c-lineup-arglist, so add the kludge described above. + +Tue Feb 1 22:14:35 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-inside-bracelist-p): + enum keyword could be preceded by a typedef + keyword + + * cc-mode.el (c-comment-region): + removed as obsolete, use comment-region instead. + Put the new comment-region function in, but commented out. + + * cc-mode.el (c-default-macroize-column): + changed to c-backslash-column. Default + value changed to 48 from 78. This is merged from c-mode.el + + (c-macroize-region): changed to c-backslash-region for c-mode.el merge. + +Mon Jan 31 22:57:05 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + CASE 8B.3: instead of try-block-open, which + is now gone, put statement-cont, block-open on semantics list. + Eventually I may call a recognition hook, and/or exceptions probably + fall through to here. + + * cc-mode.el (c-guess-basic-semantics): + CASE 5E. go to beginning of statement + before looking getting relpos, so that we properly pick up nested + argument lists. + + * cc-mode.el (c-common-init): + better setting up of Lucid menubar (use mode-name as + menu bar title) + + (c-popup-menu): use mode-name in menu title + + * cc-mode.el (c-keep-region-active): + shouldn't check for interactive-p in tests + + (c-submit-bug-report): don't keep region active. + + * cc-mode.el (c-keep-region-active): no-op for FSF 19 + + (c-set-style) (c-beginning-of-statement) (c-end-of-statement) + (c-up-conditional) (c-backward-conditional) (c-forward-conditional) + (c-popup-menu): added a call to c-keep-region-active + + (c-tame-comments) (c-indent-command) (c-indent-exp) (c-indent-defun) + (c-indent-region) (c-macroize-region) (c-comment-region): removed call + to c-keep-region-active + +Sun Jan 30 20:22:09 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-mode-map): + remapped c-toggle-hungry-state to C-c C-d so it would + not interfer with standard C-c C-h key prefix help mapping + +Fri Jan 28 22:16:29 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-switch-label-key): + fixed what can occur between the `case' keyword + and the colon. Its any amount of whitespace, followed by a single, + non-whitespace character, followed by any number of other characters. + +Thu Jan 27 21:15:57 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-fill-paragraph): + much better for C++ style comments. 1. does not + munge up font-lock regions by inserting/deleting the intended + fill-prefix. 2. does not assume that leading whitespace before // is + spaces, *but* fill-prefix must be consistent for every line in the + region. + + * cc-mode.el (c-mode-menu): moved this higher up in file + + * cc-mode.el (c-end-of-statement): simple paren mismatch in call to + c-beginning-of-statement + + * cc-mode.el (c-guess-basic-semantics): + CASE 2, skip over any preceding blank lines + that can occur before the comment. This fixes comment indentation for + the second and following paragraphs in a multi-paragraph C block + comment region with no leading stars. + + (c-lineup-C-comment): don't assume relpos is at the beginning of the + line (even though it usually is). + + * cc-mode.el (c-switch-label-key): + simplify description of what can follow a 'case' tag + + * cc-mode.el: Use copy-alist instead of c-copy-sequence + + * cc-mode.el (c-common-init): + fix the way c-mode-menu is added to the Lucid menubar + so existing menubars aren't clobbered + + * cc-mode.el (c-copy-sequence): + workaround for FSF 19.22 bug in copy-sequence + +Wed Jan 26 22:38:20 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-lineup-comment): renamed from c-indent-for-comment + + (c-lineup-comment): call c-comment-indent when a comment-only line's + indentation is at or to the right of comment-column. + + (c-guess-basic-semantics): when a comment-only line's indentation is + at or to the right of comment-column, only 'comment-intro is on the + semantics list since the comment does not indent relative to a + non-comment line would get indented. + + * cc-mode.el (c-lineup-arglist): + now correctly handles arglist-close langelems + (i.e. closing parens in an arglist) + + * cc-mode.el (c-offsets-alist-default): + new constant containing unchanging default + settings for langelems + + (c-offsets-alist): value is set as a distinct copy of + c-offsets-alist-default. + + (c-set-style): if 'c-offsets-alist is found in style, first reset the + value of this variable to c-offses-alist-default, then change only + those langelems that differ. + + * cc-mode.el (c-style-alist): + changed defconst to defvar. removed comments from + c-mode merge + + * cc-mode.el (c-indent-region): minor format change + + * cc-mode.el (c-indent-region): + merged in RMS's latest c-indent-region. Added a + skip of blank lines before the current line is indented. Recalculate + beginning-of-defun lim inside of top-level while loop so that + back-parsing is further restricted properly, speeding indentation + calculation. + +Tue Jan 25 18:01:01 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-fill-paragraph): small fix to RMS's paren level typo + + * cc-mode.el (c-fill-paragraph): + fixed (hopefully) obvious parenthesis level typo + + * cc-mode.el (c-fill-paragraph): added RMS's new C++ aware version + + (c-mode-map): put back the binding of M-q to c-fill-paragraph + +Mon Jan 24 22:52:53 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-update-modeline): typo: use c-hungry-delete-key + + * cc-mode.el (c-auto-hungry-string): minor-mode-alist variable + + (c-common-init): auto-hungry designation string happens on + minor-mode-alist now + + (c-update-modeline): sets the c-auto-hungry-string + + * cc-mode.el (c-electric-semi&comma): + only re-indent line when c-auto-newline is non-nil + + * cc-mode.el (c-mode-menu): + new Lucid menu variable for popup and menubar + + (c-popup-menu): command for popping up a menu in Lemacs + + (c-mode-map): FSF 19's menu initialization stuff is moved to here. Add + binding for Lemacs to put c-popup-menu on button 3. + + (c-common-init): put c-mode-menu on buffer-local menubar for Lucid + +Fri Jan 21 22:36:03 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + (c-up-block) (c-down-block): removed. backward-up-list and down-list + do the job already + + * cc-mode.el: (cc-mode.el) comment improvements + + (c-mode-map): a few merges from lemacs, but commented out for now. + + (c-insert-brackets) (c-insert-braces): taken from lemacs, but + commented out for now + + (cc-mode.el): menus added from FSF emacs. Still need menus for + lemacs. + +Fri Jan 14 18:59:57 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-mode.el): fixed typo on make-obsolete-variable + + * cc-mode.el (cc-mode.el): added all make-variable-obsolete calls + +Thu Jan 13 23:25:57 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + CASE 8A substatement. relpos is boi of + placeholder + + * cc-mode.el (c-beginning-of-statement-1): + skip back over syntactic ws before + checking bobp in while condition + +Wed Jan 12 14:24:11 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-mode.el): only v19 has the make-obsolete calls + + * cc-mode.el (c-guess-basic-semantics): + CASE 8B.3 now returns a try-block-open, but + exceptions aren't yet fully supported. + + * cc-mode.el (c-beginning-of-statement): + when in a comment, or looking at the + beginning of a comment, only call forward-sentence if not called + interactively. Thus programmatically, this function always goes back + to the real beginning-of-statement. + + * cc-mode.el (cc-mode.el): changes to comments at top of file + + * cc-mode.el: + (c-common-init) (c-style-name) (c-set-style): removed c-style-name, + and no longer put style name on minor mode list + + * cc-mode.el: + (c-set-style) (c-style-alist): vastly verbosified docstrings + +Tue Jan 11 23:50:45 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-offsets-alist): vastly verbosified docstring. + + (cc-mode.el): LANGELEM in docstrings are changed to "syntactic element + symbols" for clarity (?!) + + * cc-mode.el: (c-electric-colon) (c-offsets-alist) (c-macroize-region) + (c-block-comments-indent-p) (c-untame-characters) + (c-toggle-auto-state) (c-toggle-hungry-state) (c-macroize-region): + minor docstring mods + + * cc-mode.el (c-electric-colon): minor docstring mod + + (c-submit-bug-report): removed c-auto-hungry-initial-state from + reported var list + + * cc-mode.el (c-offsets-alist): + improve the docstrings for brace-list-* langelems + + * cc-mode.el (c-auto-hungry-initial-state): + obsolete variable, use c-auto-newline + and c-hungry-delete-key variables instead + + (c-mode) (c++-mode): run-hooks is now the last thing + + (c-set-auto-hungry-state) (c-make-region-active): removed + + (c-keep-region-active): is now a defun + + (c-update-modeline) (c-calculate-state): added + + (c-toggle-auto-state) (c-toggle-hungry-state) + (c-toggle-auto-hungry-state): simplified vastly. also, docstrings now + explain what the features do. + + * cc-mode.el (cc-mode.el): + added an fset of c++-beginning-of-defun for lemacs 19.9 + lossage + + * cc-mode.el (c-cleanup-list): + improved docstring, when do clean ups take place? + + * cc-mode.el (c-cleanup-list): minor docstring typo fix + + * cc-mode.el (cc-mode.el): changed FSFmacs to FSF Emacs + + * cc-mode.el: added my name to 1993 and 1994 copyrights + +Mon Jan 10 22:10:11 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-set-offset): + conversion of offset to a number in the interactive + list glom section was missing negative numbers due to the leading + minus sign + + * cc-mode.el (c-beginning-of-statement-1): + on error, skip backwards over +!~ in + addition to other chars skipped + +Sat Jan 8 03:20:49 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-electric-pound): + fixed after-functionality positioning when point + is at bolp before # is installed + + * cc-mode.el (c-guess-basic-semantics): + CASE 13, inline-close relpos should be boi + of the beginning-of-statement relpos + + * cc-mode.el (c-beginning-of-statement-1): + only do the skip-chars-backwards in the + failure of the condition-case statement. also, add the `-' character + to the list of skippage + +Fri Jan 7 23:27:20 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-beginning-of-statement-1): + do not let backward scanning stop inside + a literal. use c-in-literal to stop this, which really catches only + preprocs + + * cc-mode.el (c-guess-basic-semantics): + CASE 13, block-close relpos should be boi + of relpos to catch "} else {" constructs + + * cc-mode.el: (c-forward-conditional) (c-indent-region) + (c-beginning-of-inheritance-list) (c-backward-to-start-of-do) + (c-backward-to-start-of-if): removed unused let-bound variables as per + output of byte compiler + + * cc-mode.el: better messages about the necessary makunbounds + +Thu Jan 6 18:52:51 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-beginning-of-statement-1): recognize "else if" clauses + + (c-guess-basic-semantics): CASE 8A recognizes "else if" clauses + +Mon Jan 3 23:01:58 1994 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: upped the copyright notice date + + * cc-mode.el (c-beginning-of-statement-1): + before calculating last-begin, skip over + any bogus characters like *&:. for the following situations: + + if(::foo(), + if(.0123, + if(&blatz, + if(*bar, + + * cc-mode.el (c-guess-basic-semantics): + CASE 8A. do and else clauses aren't + followed by a paren list, so we should only skip forward over 1 sexp + in those cases. + +Wed Dec 29 18:06:12 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-lineup-multi-inher): + skip syntactic ws if there is only a comment + on the end of the line containing the opening colon + + * cc-mode.el (c-guess-basic-semantics): CASE 5C, don't check for + c-conditional-statement, since only "for" can have multiple + substatements + + * cc-mode.el (c-guess-basic-semantics): + CASE 8: added colon to list of characters + that don't continue a statement, all other cases will be caught later + on (I hope). + + * cc-mode.el (c-guess-basic-semantics): + rewrote and re-arranged CASE 5 subcases to + correctly identifiy for-list substatements, etc. looks like + paren-lists now work pretty well. + +Tue Dec 28 16:36:06 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + fixed CASE 5C to use new semantics for + c-beginning-of-statement. + + * cc-mode.el (c-beginning-of-statement-1): + make sure searching stops correctly at + conditional statements (if/while,...etc) so that substatements are + properly recognized + + * cc-mode.el (c-beginning-of-statement): + make sure we're left at or after lim + + * cc-mode.el: (c-electric-brace) (c-electric-slash) (c-electric-star) + (c-electric-semi&comma) (c-electric-colon): let-bind + c-echo-semantic-information-p to nil to shut up information printing + in inappropriate places + + * cc-mode.el (c-guess-basic-semantics): + fixes to CASE 8 for new semantics of + c-beginning-of-statement. Added a test of placeholder != + containing-sexp in top-level test. CASE 8D, progn => save-excursion + so correct statement start can be found + + * cc-mode.el: + (c-beginning-of-statement) (c-end-of-statement): minor clean up. + removed my old c-beginning-of-statement -- we'll go with FSF's and fix + it as need bee + +Mon Dec 27 23:25:17 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + (c-beginning-of-statement) (c-end-of-statement): add another optional + argument, lim + + (c-guess-basic-semantics): corrected to use new arg list for the above + + * cc-mode.el: + (c-beginning-of-statement) (c-end-of-statement): check for argument == + nil (optional arg not supplied) + + * cc-mode.el: + (c-beginning-of-statement) (c-end-of-statement): make arg optional + + * cc-mode.el (c-beginning-of-statement, et al): + try using BOCM's version to see if + it works any better + + * cc-mode.el (c-set-style): put a space in front of c-style name + + (c-common-init): only hack on c-style-name once! + + * cc-mode.el: provide cc-mode, not c-mode + + * cc-mode.el (c-style-name): new variable, buffer local + + (c-common-init): hack on c-style-name to the minor-mode alist + + (c-set-style): set c-style-name variable for minor-mode + + * cc-mode.el (c-conditional-key): added "switch" + + (c-guess-basic-semantics): renumbered CASE 8 subcases, no substantive + changes. + + (c-guess-basic-semantics): added dummy CASE 8B.3 to generate an error. + I don't know what constructs fall through this case. + + * cc-mode.el (c-symbol-key): + put this back in and fixed all the other -key's to use it + + * cc-mode.el (c-set-auto-hungry-state): + small typo in check for force-mode-line-update + + * cc-mode.el: use force-mode-line-update where appropriate + + * cc-mode.el: added autoload directives + +Wed Dec 22 20:52:32 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-inside-bracelist-p): + fixed a bug when no spaces were between the = + char and open brace in an aggregate list + + * cc-mode.el (c-switch-label-key): fixed to recognize negative numbers + + * cc-mode.el: + (c-forward-into-nomenclature) (c-backward-into-nomenclature): new + commands, but as yet unbound + + * cc-mode.el (c-guess-basic-semantics): + CASE 7C: look for block-open modifier + +Tue Dec 21 22:55:21 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + CASE 7 improved but nested brace-lists are + still not perfect. Do I need to add another langelem??? blech. + + * cc-mode.el (c-inside-bracelist-p): + new function to calculate whether we're inside + a brace list or not + + (c-guess-basic-semantics): use c-inside-bracelist-p where appropriate + + * cc-mode.el (c-guess-basic-semantics): + CASE 7B's (brace-list-close) relpos is not + boi of bo-stmt, instead its boi of containing-sexp + + * cc-mode.el (c-offsets-alist): + added brace-list-close, brace-list-intro, + brace-list-entry + + (c-guess-basic-semantics): added logic to recognize brace-list-open + new langelems + + * cc-mode.el (c-hanging-braces-alist): + docstring addition: brace-list-open + + (c-offsets-alist): added brace-list-open + + (c-electric-brace): added logic to hang brace-list-open's + + (c-guess-basic-semantics): added logic to recognize brace-list-open's + + * cc-mode.el (c-mode-map): removed binding to undefined c-match-paren + + * cc-mode.el (c-semantics): new variable + + (c-indent-via-language-element): use globally advertised c-semantics + variable now. + + (c-offsets-alist): better docstring, describes c-semantics + + * cc-mode.el (c-adaptive-block-open): + new function, but block-open doesn't use it + by default yet + + (c-guess-basic-semantics): moved M2 (block-open) test into body of + defun instead of at the end -- to many special case tests + +Mon Dec 20 17:55:38 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-indent-command): + guarantee that c-tab-always-indent == nil has the + same semantics as in BOCM + + * cc-mode.el (cc-mode.el): pulled in bocm's beginning-of-statement, + end-of-statement and related defuns, but I still need to make a pass + through them. + + (c-up-conditional) (c-backward-conditional) (c-forward-conditional): + yanked in verbatim from c-mode.el + + (c-backslash-region): fset from c-macroize-region. also, we're + leaving c-backslash-column commented out. use + c-default-macroize-column instead. + + * cc-mode.el (c-fill-paragraph): removed, use filladapt instead + + (c-comment-indent): adopted from c-mode.el, but fixed to handle C++ + comments + + * cc-mode.el (c-mode.el): + moved some defuns and defmacros around. no substantive changes + + * cc-mode.el (c-symbol-key): obsolete, use \\s_ syntax class instead + + (c-protection-key): new defconst + + (c-case-statement-key): renamed to c-switch-label-key + + * cc-mode.el (c-lineup-streamop): + search for stream operator, be careful of + singular less than, greater than symbol. + +Fri Dec 17 21:42:27 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed semantics for c-macroize-region and c-comment-region + + * cc-mode.el (c-guess-basic-semantics): + don't put block-open on semantics list if + other brace open symbols are already there + +Thu Dec 16 20:49:34 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-emacs-features): minor docstring change + + * cc-mode.el (c-set-offset): + new optional add-p arg. when non-nil, require-match on + completion is inhibited and new langelem symbols can be added to the + c-offsets-alist. + + (c-guess-basic-semantics): CASE 7C has been extended to properly + recognize conditional's substatements. CASE 7D now handles continued + statements. CASE 7A now recognizes only func local class opening + braces, which means 7C + M2 will catch substatement block-opens. + + (c-offsets-alist): added substatement langelem + + * cc-mode.el (c-strict-semantics-p): + default value to nil for debugging purposes + + (c-guess-basic-semantics): block-open langelem is now a relpos-less + langelem because it is really a modifier on the basic langelem of the + line. Specifically: Case M2 added; CASE 7A.2 now places just a + statement-cont langelem on semantics; CASE 13.B is completely removed. + + (c-offsets-alist): block-open default offset is now 0. + +Mon Dec 13 15:29:26 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + now it does the the test for c++-mode to + save a potential funcall in c-mode. + + (c-search-uplist-for-class): fixed bug where c-in-literal test was + testing end-point of parse-partial-sexp, not the classkey search begin + point. + +Thu Dec 9 19:02:25 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-mode-map): fixed FSF call to set-keymap-parent + + * cc-mode.el (c++-mode-map): + JWZ contributed a better way to share keymaps for v18 + using nconc + + (c-populate-map): obsolete, move all define-keys into c-mode-map if + statement + + * cc-mode.el (c-emacs-features): + for Emacs 19's, add a flavor member to distinguish + between FSF19 and Lucid19. + + (c++-mode-map): for Emacs 19's, inherit c++-mode-map from c-mode-map. + Handle FSF/Lucid properly and handle GNU18 the hard way. + +Wed Dec 8 22:43:02 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-down-block): + changed call of c-beginning-of-block to c-up-block + + * cc-mode.el: + (c-populate-map) (c-populate-syntax-table): new funcs to consolatate + setting these structures + + (c-mode-map) (c++-mode-map): get as close as we can with BOCM's + mappings, but there are still some inconsistencies I need to clean up + +Tue Dec 7 23:52:29 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-set-style): added functionality + + (c-macro-expand): added autoload + + (documentation and docstrings): updated many places + + (c-set-offset): better interactive spec + + (c-fill-paragraph): stolen from c-mode, but not looked at yet + + (cc-mode.el): added fset compatibility with c-mode + + NOTE: THERE ARE STILL SOME FUNCTIONS I HAVEN'T MOVED HERE YET. + +Mon Dec 6 15:46:30 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c-guess-basic-semantics): + CASE 5D is only a statement-cont if the + beginning-of-statement is not bound by continued-sexp + + * cc-mode.el: fixed a coupble of cc-emacs-features to c-emacs-features + +Fri Dec 3 23:05:29 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-mode.el): + changed all symbols from cc- to c-, except + where both c- and c++- are needed: + c++-mode-abbrev-table, c++-mode-map, c++-mode-syntax-table, + + (c-mode-common-hook): new common hook name + + (c-mode-map): don't add c-scope-operator. + +Thu Dec 2 00:59:34 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-guess-basic-semantics): + CASE 7B, its possible that the line that + placeholder points to does not contain the first streamop. This can + be the case if the streamop line follows an `if' clause. + +Wed Dec 1 23:35:44 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-macroize-region): + simplified so begin/end semantics are identical + to cc-comment-region. + + (cc-backslashify-current-line): do not (forward-char -1) if eol == + bol. Also, must let-bind kill-lines-magic to nil so that blank line, + with only a \ on it will not consume the newline character + +Mon Nov 29 22:50:30 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-indent-region): + only generate an error on non-open paren/brace + when shutup-p is nil + + * cc-mode.el: + (cc-uncomment-region) (cc-comment-region): combined into 1 function, + bound to C-c C-c and behavior analogous to cc-macroize-region. + + (cc-up-block) (cc-down-block): new commands, bound to C-c C-u and C-c + C-d respectively. + + * cc-mode.el (cc-indent-exp): + don't indent line with cc-indent-via-language-element + if line is blank + + * cc-mode.el (cc-electric-brace): + use (boundp 'blink-paren-function) as emacs + version test, not cc-emacs-features. The latter breaks on Emacs18's + with the syntax patch + + * cc-mode.el (cc-guess-basic-semantics): + fixed the comment-intro regexp to ignore + newlines. (spaces and tabs only) + +Fri Nov 26 19:01:34 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-search-uplist-for-classkey): + fixed two small bugs. first, the cdr + of foundp should be cc-point boi to catch any template prefix on the + class key (remember we're searching backwards now -- maybe we should + search forward, eh?). Also, we have to set donep to (not foundp) so + that the search ends when we haven't found any classkey + + * cc-mode.el (cc-guess-basic-semantics): + CASE 13.D make sure we're not looking at a + globally scoped function call + + * cc-mode.el (cc-guess-basic-semantics): + arglist-close should relpos boi of + containing-sexp + + (cc-change-semantic-symbol-offset): fixed setqcdr typo + + (cc-offsets-alist): arglist-close default is now + + + * cc-mode.el (cc-beginning-of-statement): + fix problem when crossing a paren level + (i.e. the cc-safe forward-sexp call fails). just move back a space + and keep going. + + (cc-guess-basic-semantics): expand CASE 5C test and CASE 5E relpos + calculation + +Wed Nov 24 22:54:31 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-safe): + added this macro back in -- it seems to be useful + + (cc-beginning-of-statement): really improved this a lot. we only go + back a sexp if we aren't already at the beginning of indentation. + This is now a more generally useful function since it seems to do the + right thing under all circumstances. + + (cc-guess-basic-semantics): lots of changes to use the new cc-b-o-s + function. All known indentations after hanging braces are now fixed. + This includes case 4D.5, CASE 7, CASE 12, and CASE 13.F. Are there + others? + + * cc-mode.el (cc-offsets-alist): added knr-argdecl offset + + (cc-change-semantic-symbol-offset): allow addition of new langelem + symbols with universal arg + + (cc-guess-basic-semantics): added recognition of subsequent + knr-argdecl langelems in cc-c-mode only + + * cc-mode.el (cc-electric-brace): + in brace-else-brace cleanup, I forgot to insert + the new "} else {" string after deleting the old string! + + * cc-mode.el: + (cc-back-block) (cc-safe-uplist) (cc-safe-downlist): obsolete + + (cc-search-uplist-for-classkey): completely rewritten for speed. it + now uses re-search-backwards limited to two bod's back. Orders of + magnitude faster when operating towards the end of a large file. In + fact exec time is not buffer size dependent anymore (but like + everything else, it is bod dependent of course). + + (cc-guess-basic-semantics): fixed cases 4, 7, and 12 to work with the + new cc-search-uplist-for-classkey + +Tue Nov 23 22:41:41 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-guess-basic-semantics): + fixed case 4F. if a class-close is found, + it should indent relative to the class declaration, not the opening + brace (i.e. the cdr of inclass-p, not the car) + + * cc-mode.el (cc-guess-basic-semantics): + fix CASE 12's determination of the type of + langelem that a brace closes. + + * cc-mode.el (cc-c++-mode-syntax-table): + switched A/B comment styles as per Paul + Smith's FSFmacs patch + + (cc-1bit-il): switched A/B comment styles as per Paul Smith's FSFmacs + patch + + * cc-mode.el (cc-search-uplist-for-classkey): + only search when in a C++ buffer. C + buffers have no enclosing class! + + * cc-mode.el (cc-electric-pound): + oops, forgot to prefix-numeric-value arg on the + self-insert-command + + * cc-mode.el (cc-mark-function): + must funcall the second call to push-mark since + v18 only accepts 2 arguments, not the 3 of v19. + + (cc-electric-brace): fix the blink-paren-function/-hook mismatch for + v18 vs. v19. + + (cc-point): added the (,@ nil) form as a workaround for v18's + backquote bug. Doesn't seem to hurt us for v19 so I left it in for + everyone. + +Mon Nov 22 23:29:19 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-guess-basic-semantics): + CASE 12, always return boi of the line + that containing-sexp is on, not just for block-close langelem + + * cc-mode.el (cc-search-uplist-for-classkey): + make backward searching slightly more + efficient by stopping when char under search-start is a close brace + + * cc-mode.el (cc-label-key): + new constant, change all concat'd label regexps to use + this new constant + + (cc-guess-basic-semantics): fix case 13.D to not accidentally code a + statement that follows a label as a ?: construct + + * cc-mode.el (cc-indent-command): + fixed behavior when cc-tab-always-indent was nil. + should now be like old behavior (CASE 1) + + * cc-mode.el (cc-emacs-features): improve documentation + + * cc-mode.el (cc-point): + retain quoted symbol semantics on argument but don't use + dangerous `eval' to get an eq ready symbol + + * cc-mode.el (cc-indent-exp): + better error messages so people don't get as confused + + * cc-mode.el (cc-beginning-of-statement): + much more robust movement across balanced + expressions now correctly finds the beginning of statements for very + complex forloops and more. We now no longer assume that expressions + begin and end on a single line. + + (cc-guess-basic-semantics): CASE 5C is expanded to correctly locate + multi-line mathematical paren groupings. Also, CASE 5E now returns + boi at the beginning-of-statement for any arglist-cont. + + * cc-mode.el: + (cc-electric-brace) (cc-electric-slash) (cc-electric-star) + (cc-electric-semi&comma) (cc-electric-colon) + (cc-change-semantic-symbol-offset): changed docstrings to more + accurately describe defuns' behavior + + * cc-mode.el (cc-indent-exp): + calculate bod before doing the forward-sexp since + unindented open parens in col0 lower down will mess this calculation + up. + +Sat Nov 20 21:53:29 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-submit-bug-report): typo on cc-hanging-colons-alist + + * cc-mode.el: + (cc-keep-region-active) (cc-make-region-active): split this into a + macro (the former) and a defun (the latter). This way we can check + for interactivity as expected, but still cut down on the number of bc + warnings. + + * cc-mode.el: + (cc-setup-comment-indent-variable) (cc-keep-region-active): make these + defuns so that the .elc file won't be editor version specific. The + trade off is that the byte compiler will complain + + * cc-mode.el (cc-lineup-C-comments): + limit re-search-forward to eol, not eol-1... + why did we do this? + + * cc-mode.el: + (cc-electric-brace) (cc-electric-semi&comma) (cc-electric-colon): + re-indent the line even if cc-auto-newline is nil, just don't add any + newlines + + * cc-mode.el (cc-offsets-alist): + multi-line strings should be shoved against the + left side margin + + * cc-mode.el (cc-setup-comment-indent-variable): + new macro to cut down on byte + compiler warnings + + * cc-mode.el (cc-case-statement-key): + should now recognize character constants as + arguments to case statement + + * cc-mode.el (cc-keep-region-active): + support for FSFmacs and don't lay down calls + to variables that don't exist + + (cc-submit-bug-report): variable typos + + * cc-mode.el: + fixed order of macro expansions. defmacro's must appear before their + first use -- this is probably why cc-point was busted in compiled code + +Fri Nov 19 18:44:54 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-guess-basic-semantics): + added some minimal recognition of template + continuation lines. Probably not so great. + + (cc-guess-basic-semantics): fixed top-level decl continutation lines + + (cc-guess-basic-semantics): fixed ?: constructs + + * cc-mode.el: + (cc-c++-mode) (cc-c-mode): setq'ing of comment-start/-end must happen + *after* cc-common-init for those values to retain their proper settings + + (cc-indent-exp): add optional SHUTUP-P argument to suppress + operational messages. + + (c++-indent-exp): removed this commented out function. I think the + byte-compiled, simplified cc-indent-exp is fast enough! + + (cc-indent-region): stolen from c-mode and fixed. + + (cc-beginning-of-inheritance): backscanning must stop when we're + looking at a cc-class-key + + (cc-guess-basic-semantics): inher-intro and inher-cont should not have + inclass langelem added since their relpos offsets already contain any + inclass offset + +Thu Nov 18 23:06:37 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (cc-change-semantic-symbol-offset): new command + + * cc-mode.el (cc-guess-basic-semantics): + added recognition of 'block-open braces + following a full statement (yup they are legal) + + * cc-mode.el (cc-lineup-C-comments): added to support old + cc-C-block-comments-indent-p behavior + + * cc-mode.el: + removed the multi-line preprocessor stuff. its just too much of a + hack right now + + * cc-mode.el: some limited support for multi-line macros and such + +Wed Nov 17 23:29:41 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed all byte-compiler warnings. did a pass through the comments and + docstrings. macro-ized a few more defuns + + * cc-mode.el (cc-indent-exp): + a slow, but moderately useful interrim solution. + + * cc-mode.el (cc-point): + another small fix to the macro to get byte compilation to work + + * cc-mode.el (cc-point): + small fix to macro expansion. must eval position so that + 'sym idiom still works + + * cc-mode.el: + added cc-keep-region-active to all appropriate interactive defuns + + * cc-mode.el (cc-point): + made this a macro so things should be much quicker when + byte compiled + + * cc-mode.el (cc-electric-brace): + insert any after-brace newlines after all + cleanups have taken place + + * cc-mode.el (cc-electric-colon): + semantic information can only be accurately + retrieved on the line with colon for label, case-label, and + access-key. member-init-intro and inher-intro must be gathered from + the following line. + + * cc-mode.el: (cc-electric-start) (cc-electric-slash): use + cc-indent-via-language-element instead of cc-indent-line + +Tue Nov 16 23:04:59 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-electric-colon): deleted + + * cc-mode.el (cc-electric-brace): + inhibit blinking any close paren until we've done + all our magic, then just call blink-paren-function manually + + * cc-mode.el (cc-guess-basic-semantics): CASE 4 was missing a call to + cc-backward-syntactic-ws which broke arglist indentations + + * cc-mode.el (cc-beginning-of-statement): + catch multi-line function calls by going + backward over balanced () sexps + + * cc-mode.el: had to add all the lineup functions from c++-syntax.el + + * cc-mode.el: continued if/while/do/else/for statements now work again + + * cc-mode.el: 1. a good shot at cc-electric-colon + 2. added cc-scope-operator bound onto C-c C-; + + * cc-mode.el: + everything is rewritten and tested except c++-electric-colon and + c++-indent-exp + +Thu Nov 11 21:24:06 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: got rid of glaring byte-compiler reported problems. + + * cc-mode.el: + The bulk of the rename work has been done. The entire mode has been + renamed CC-Mode. The file has been renamed cc-mode.el, and all + symbols have changed from c++- to cc-. In addition, all + known remaining c-mode dependencies have been eliminated. + + There is still much work to be done. + +Tue Nov 9 22:26:06 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: rough attempt at syntactic analysis. more to come + +Mon Nov 1 03:25:12 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-search-uplist-for-classkey): + restore point if no enclosing class + is found + +Sun Oct 31 19:14:59 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + (c++-narrow-out-enclosing-class) (c++-search-uplist-for-classkey): new + defuns + + (c++-point): added 'boe and 'eoe positions + +Fri Oct 29 22:42:35 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + totally screwed up indentation. we're going to have to back out the + last few mods. URG! + + * cc-mode.el (c++-indent-exp): + special case of looking at ?{, should not add + c-indent-level since this is only for C statements wrt containing + block and not block opening paren + + * cc-mode.el (c++-calculate-indent): + undid split from previous revision. now case + 3A always returns 0. Any additional top-level brace offset gets + applied in c++-indent-line and c++-indent-exp (although the later does + not yet work). + + * cc-mode.el (c++-calculate-indent): + needed to split case 3A into 2 parts since + bobp does not get the same indent as a top-level opening paren + +Wed Oct 27 14:28:16 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-common-init): + don't set the auto-hungry state here since the + mode hook has not been run yet. + + (c++-mode) (c++-c-mode): set the auto-hungry state for the buffer + after the mode hook has been run + +Wed Oct 20 18:46:53 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-mode-map): + do NOT define C-m and C-j, so as to retain the + standard default settings for these keybindings + +Mon Oct 11 16:32:02 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-calculate-indent): + in CASE 3C, when checking for hanging member + init colon, but not scope operator, we didin't check for double colons + when looking at the preceding-char. Now look at char before point and + char 2 before point. If both are colons, we're looking at a scope + operator. + +Fri Oct 1 13:21:00 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-common-init): + changed the test for comment-indent-function to + checking for boundp of the variable instead of c++-emacs-features + since Emacs 18 with syntax patches is (8bit v19) but does not have the + variable bound. + +Wed Sep 29 21:08:29 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-backward-to-start-of-if): + better error message for else with no if + + * cc-mode.el (c++-calculate-indent): + test case 3H, when taking the current-column, + must subtract out the inclass-shift so it doesn't get added twice. + inclass-shift is implicit in current-column. + +Tue Sep 28 23:11:04 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-mode-syntax-table): don't be as harsh on FSF + + * cc-mode.el: (c++-cleanup-list) (c++-hanging-member-init-colon) + (c++-auto-hungry-initial-state) (c++-auto-hungry-toggle) (c++-mode): + use the terminology "valid" instead of "legal" to define acceptable + values as per RMS's conventions. + + * cc-mode.el (c++-c-mode): improve the docstring re: running the hook + + * cc-mode.el (c++-indent-exp): + use c++-cont-indent to calculate continued statement + indentation amount. remove large part of hackery here so lets watch + and see if anything got broken, but I think c++-c-i should do the + trick for all constructs + + * cc-mode.el (c++-indent-defun): + better, quicker implementation of this defun + + * cc-mode.el (c++-electric-pound): + better implementation of previous patch + + * cc-mode.el (c++-electric-pound): + only align pound to left column if there isn't + one already there. This lets people enter ## as cpp concat command + + * cc-mode.el (c++-electric-semi): + renamed c++-electric-semi&comma to implement }, + and }; cleanups + + (c++-cleanup-list): added list-close-comma to allow cleanups of }, + constructs. + + * cc-mode.el: cleaned up some comments + + * cc-mode.el (c++-common-init): + new function to provide one entry point for all + common initializations of the mode. + + (c++-mode) (c++-c-mode): use c++-common-init to do the common stuff, + then do mode specific stuff. + + * cc-mode.el (c++-calculate-indent): + complete fix for proper indentation of base + classes in a multiple inheritance declaration. + + (c++-baseclass-key): new constant defining regexp for base class defs + + * cc-mode.el: partial fix for multi-inher lines + +Mon Sep 27 19:15:51 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-backward-to-start-of-if): + give a more informative message if an + unbalanced if/else was found + + * cc-mode.el (c++-compound-offset): + fixed a bug when looking at "typedef enum", + this wasn't registering as an enum start. + + (c++-indent-exp): fixed indentation of comma separated compound + statements by using the function c++-compound-offset to calculate + offset instead of just using the variable c-continued-statement-offset + + * cc-mode.el (c++-mode): + compatibility with old style comment-indent-hook and new + style comment-indent-function + + * cc-mode.el: + (c++-indent-line) (c++-calculate-indent): improved calculate in + let-body for open-paren and top-open-paren values, using car-safe and + cdr-safe + + (c++-indent-line): fix typo bug when looking at open brace. + + (c++-indent-line): apply TOPLEVEL c-brace-offset when brace is at top + level wrt class, or real top level. + + * cc-mode.el (c-brace-offset): moved here from c-mode.el + + (c++-mode): for vars c-brace-offset and c++-block-close-brace-offset, + both can now take list values. describe these in the mode's + docstring. + + (c++-indent-exp) (c++-indent-line) (c++-calculate-indent): when + looking at an open brace, apply c-brace-offset depending on + top-level-ness of the opening brace. + +Fri Sep 24 22:05:21 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-indent-exp): + when inside a class definition, if we are looking at + an open brace, we apply c-continued-brace-offset instead of just zero. + this allows users to indent the opening brace of an inline function + body. + + * cc-mode.el (c++-calculate-indent): + when inside a class definition, if we are + looking at an open brace, we apply c-continued-brace-offset instead of + just zero. this allows users to indent the opening brace of an inline + function body. + + * cc-mode.el (c++-calculate-indent): + removed the commented out text which used to + test for null state. we never hit null state from c++-parse-state + anymore. + + * cc-mode.el (c++-emacs19-accurate-bsws): + new function which skips syntactic + whitespace w/o treating cpp macros as comments syntactically. + + (c++-emacs18-bsws): renamed from c++-backwards-syntactic-ws + + (c++-lemacs-pre19-8-bsws): renamed from c++-backwards-syntactic-ws-1 + + (c++-emacs18-il): renamed from c++-in-literal + + (c++-8bit-il): renamed from c++-in-literal-8-bit + + (c++-1bit-il): renamed from c++-in-literal-1-bit + + Changed the way compatibility is fset into the function symbols + c++-backward-syntactic-ws and c++-in-literal. + +Tue Aug 10 16:44:26 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: minor cosmetic comment typo + +Thu Jul 29 00:18:00 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: consensus was to nuke c++-insert-header + +Mon Jul 12 20:37:27 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-mode.el): updated the comments at the top of the file + + * cc-mode.el (c++-calculate-indent): + removed test for null state during initial + parse from beginning-of-defun to indent-point. this is obsolete now. + +Fri Jul 2 22:42:03 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-mode-map): removed bindings to obsolete functions + c++-beginning-of-defun and c++-end-of-defun. + + (c++-electric-terminator) (c++-in-literal) (c++-in-literal-8-bit) + (c++-in-literal-1-bit) (c++-point) (c++-indent-defun): changed all + references of obsolete functions c++-beginning-of-defun and + c++-end-of-defun to beginning-of-defun and end-of-defun respectively. + + * cc-mode.el: + (c++-match-header-strongly) (c++-defun-header-strong-struct-equivs) + (c++-defun-header-strong) (c++-defun-header-weak) + (c++-beginning-of-defun) (c++-end-of-defun): removed as obsolete. + there are better and cheaper ways of accomplishing the same + functionality. + + * cc-mode.el (c++-electric-brace): + I missed a few calls to c++-indent-line. Added + bod argument to remaining few. + + * cc-mode.el (c++-calculate-indent): + removed logic dealing with (null state) and + placed an error call there in anticipation of removal of header strong + matching stuff. I want to be sure there's no way to get to this code + + (c++-electric-brace): added bod argument to calls to c++-indent-line + so the correct bod is found, not the newly created one with the just + inserted open brace. + + * cc-mode.el: + (c++-indent-command) (c++-tab-always-indent) (c++-hanging-braces) + (c++-mode): changed the not-nil-or-t language to read "other than nil + or t" + +Thu Jul 1 17:40:53 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el (c++-backward-to-start-of-if): + changed c++-backward-sexp call to + backward-sexp now that parse-sexp-ignore-comments is handled correctly. + +Wed Jun 30 17:03:00 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + (c++-forward-sexp) (c++-backward-sexp): removed because these are obsoleted by the correct implementation for setting parse-sexp-ignore-comments. (c++-mode): improved idiom for setting up local vars + +Mon Jun 28 15:47:13 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + (c++-cleanup-list) (c++-mode) (c++-fast-backward-syntactic-ws-1) + (c++-calculate-indent) (c++-in-literal) (c++-in-literal-8-bit) + (c++-in-literal-1-bit) (c++-at-top-level-p) + (c++-backward-to-start-of-do) (c++-backward-to-start-of-if) + (c++-uncomment-region): install RMS's suggested doc string fixes based + on last public release. + +Wed Jun 23 13:58:52 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + hacking on syntax entry must be mode specific in -ws functions. ie in + c++-c-mode, hack c++-c-mode-syntax-table and for c++-mode hack only + c++-mode-syntax-table. + +Mon Jun 21 21:40:15 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + should not skip-chars-backward in ws-2, let forward-comment handle that + +Fri Jun 18 21:31:24 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + another refinement to addition offset given to open brace lines in + c++-indent-exp. Check for not at top level wrt class before adding + c-indent-level. + + * cc-mode.el: another fix to c++-indent-exp for member init lists + + * cc-mode.el: + fixed c++-indent-exp when comments follow a continued statement + + * cc-mode.el: a fix to c++-indent-exp where c-brace-offset is < 0 + + * cc-mode.el: + fixed some comment spelling errors which were fixed (but *not* + reported!) by FSF + + * cc-mode.el: + fixed a problem where default_answer("boof: glorp"); was being + incorrectly matched to a default: statement + +Thu Jun 17 21:52:21 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + update language to accurately reflect state of Lemacsen and FSFmacsen + +Wed Jun 16 22:27:29 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed indentation when base class declaration is on a separate line + then the derived class intro header. + + * cc-mode.el: + 1. cleaned up the way closing block braces are adjusted in + c++-indent-line. + + 2. also extended c++-block-close-brace-offset to allow list value so + the following style can be easily supported: + + foo(a) + { + if(a) + { + asasdfsdf; + } + } + + Previously, there was no way to adjust the closing brace into column + zero. + +Tue Jun 15 22:04:43 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + use c-continued-statement-offset instead of c-indent-level to indent + comma separated arg decl lists + + * cc-mode.el: bind C-m to newline-and-indent + + * cc-mode.el: + much simplification on c++-fast-backward-syntactic-ws-2 to work with + new forward-comment semantics + + * cc-mode.el: + don't skip up past compound statement if we're in a member init list + + * cc-mode.el: fixed a bug in the translation of CASE 3 to cond stmt + + * cc-mode.el: + 1. cleaned up the spaghetti if's in CASE3 of c++-calculate-indent, by + converting all if's to a single cond statement -- I *hope* I got it + right! + + 2. Added indentation, via c-indent-level of multi-line, + comma-separated, compound statements/declarations, with correction + for enum and static array inits. + y + +Mon Jun 14 21:54:38 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + merged in submitted patch to fix a possible bug which rears its ugly + head in FSFmacs19. I haven't verified it so the fix only happens in FSFmacs + +Thu Jun 3 22:42:44 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: try to conform to GNU cosmetic style + +Tue Jun 1 14:58:00 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + better to make a copy of the syntax table so we don't screw up text + mode's syntax table! + +Fri May 28 22:20:57 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed the bug in c++-electric-brace where entering an open brace while + point is at bol and c++-auto-newline is nil did not indent the brace. + +Tue May 25 18:37:21 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: some cosmetic differences to c++-emacs-features + +Mon May 24 23:23:05 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: take out bogus defun c++-emacs-features + + * cc-mode.el: + be really really smart about figuring out c++-emacs-features + + * cc-mode.el: + we must use a different c++-in-literal for GNU19's 1-bit solution + +Wed May 19 14:19:20 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: better c++-emacs-features deciphering + +Tue May 18 15:13:39 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: no c++-mode-maintainer + +Fri May 14 22:05:02 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + can't yet make c++-indent-exp work in weird situation (see bug reports) + + * cc-mode.el: + make sure we check for default: in the same place we check for case: + labels in CASE 4 of c++-calculate-indent + +Tue May 11 21:41:13 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: a little better documentation + + * cc-mode.el: + fixed the compat cond when setting c++-backward-syntactic-ws + + * cc-mode.el: fixed the string-match call in c++-emacs-features + +Mon May 10 18:20:42 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: check for forward-comment first + + * cc-mode.el: fixed syntax errors in previous mod + + * cc-mode.el: attempt to port between all known flavors of emacsen + +Thu Apr 22 21:16:15 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + ask user if they want to submit a bug report before actually doing it + + * cc-mode.el: + quick fix for when the ? part of a ?: construct is a negative number + +Wed Apr 21 19:53:29 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: use new interface to reporter.el + +Mon Apr 19 20:41:48 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: uuencode when sending to ftpmail + + * cc-mode.el: c++-mailer is obsolete now + + * cc-mode.el: + modify c++-submit-bug-report to use reporter package, and require it. + + * cc-mode.el: updated some documentation about getting c++-mode + +Fri Apr 16 15:36:39 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + in c++-indent-exp, during the logic which evaluates special + adjustments in the line's indentation, the sequential ifs should be a + cond statement since the conditions should be mutually exclusive + + * cc-mode.el: updated mail-server (getting the mode) comments + +Fri Apr 2 15:35:10 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + c++-backward-to-start-of-if wasn't taking into account "if" clauses in + intervening comments. Needed to add a c++-backward-syntactic-ws + +Thu Apr 1 23:08:37 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + cleaned up (I hope) all docstrings related to auto-hungry features + + * cc-mode.el: + modified c++-class-key to recognize typedef in addition to extern + + * cc-mode.el: + fixed c++-electric-star handling of stars inside C block comments but + not part of comment line head (i.e. stars embedded inside C block + comment lines not at 'boi, don't re-indent line) + +Thu Mar 18 18:49:42 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fix infinite loop in c++-fast... in the following situation + \n + #define x \ + -----------^ + hit return here + + * cc-mode.el: + wrap temporary binding of # to comment syntax in c++-fast-... in an + unwind-protect to ensure that it gets reset on any exit + +Thu Mar 11 15:36:26 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed indentation of block comments after first /* line in c++-indent-exp + +Wed Mar 10 18:50:29 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: c++-in-literal-quick wasn't checking for inside a string + +Fri Mar 5 20:00:17 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed regexps for case labels... I hope + +Thu Mar 4 23:00:30 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: updated copyright date + + * cc-mode.el: c++-c-mode uses c-mode-abbrev-table + + * cc-mode.el: + in c++-fast-backward-syntactic-ws, check for lim=(point) + 2. extended c++-class-key to include optional "extern" keyword + + * cc-mode.el: 1. extended c++-class-key to handle template definitions + 2. made MI-regexp in c++-calculate-indent into the global constant + c++-inher-key so it doesn't need to be concat'd every entry into + the loop. + + * cc-mode.el: fixed small infinite loop introduced in previous patch + + * cc-mode.el: + fixed c++-indent-exp when a multi-line C block comment caused + calculation of state to be wrong. Now, when calculating line-end, we + first check to see of eol is in a C comment, and if so, we scan + forward until we find the end of the block comment. + + this algorithm might break if there is code on the same line, but + after the closing */ of a comment. this is to bizarre to support + + * cc-mode.el: + no longer rely on # being of syntax class comment for really patched + emacses, except for convenience when in + c++-fast-backward-syntactic-ws. Also, in this method, go into a loop + checking for cpp directives since its possible that a directive has a + comment on the end of the line: + + #include /* opening a block comment here + * which isn't closed until here + */ + + Finally, fix c++-in-literal-quick to handle new syntax class of # + +Mon Mar 1 23:32:40 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + no longer rely on # being of syntax class for really patched emacses + + * cc-mode.el: + c++-macroize-region will now take any prefix arg instead of just a + negative arg. + +Tue Feb 16 20:30:37 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: don't use _ as word constituent, instead fix regexps + + * cc-mode.el: + give _ word constituent syntax class so indentation of case_ and like + symbols will work properly. forward-word will gobble underscores in + symbols so that's the trade off for taking the easy way out. + +Fri Feb 12 16:40:35 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + c++-backward-to-start-of-if was necessitated because backward-sexp + call was bombing out in new syntax, on single quote in preceding C++ + comment line. use c++-backward-sexp to properly handle this and + change all references of c-backward... to c++-backward. + +Thu Feb 11 18:33:50 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + should only bind parse-sexp-ignore-comments to t if c++-is-really-fixed-p + +Sat Feb 6 00:04:45 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + in c++-comment-indent, if previous line contains a comment only line + that is to the left of comment-column, indent the line to + comment-column + +Fri Feb 5 23:41:34 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed K&R C arg decl with keyword struct in line + + * cc-mode.el: + fixed c++-indent-command to follow documentation. previous the + following situation was broken: c++-tab-always-indent == nil and: + + ... + { + foo; + ^------- point was here + + * cc-mode.el: + use Ken Laprade's patch for format vs symbol-name print of + c++-special-indent-hook + + * cc-mode.el: + check for (not (c++-in-parens-p)) when deciding whether we're looking + at a continuation line or not to avoid bad indentation of continued + lines such as: + + if( !tnode->expanded_p() && + docobj->hasChild_p() && + docobj->tocLevel() < xmaxTocDepth ) + + * cc-mode.el: fixed anchor of comment only lines in c++-indent-exp + + * cc-mode.el: + anchor comment only lines to (current-column) if the comment is at, or + to the right of, comment-column. + + * cc-mode.el: + c++-continued-member-init-offset works for line with just single colon + line, where member inits follow on subsequent lines: + + ff::ff () + : + xxx (0), + yyy (0) + { + + * cc-mode.el: + don't add c-continued-statement-offset if looking at a class's opening + brace + + * cc-mode.el: fixed c++-indent-exp wrt stream ops + + * cc-mode.el: fixed another small problem with nested class indentation + + * cc-mode.el: + another fix for nested class indentation when looking at the line + after an access specifier. we needed to substract one level of + indentation + +Tue Feb 2 21:27:52 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: modifications to better indent nested classes + +Fri Jan 29 22:31:07 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + in c++-forward/backward-sexp, only let bind parse-sexp-ignore-comments + to t if emacs is fixed (not really fixed) + +Wed Jan 27 22:48:56 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + some previous fix (don't know when) broke MI continuation line + indentation. This fixes that problem by making sure we're not looking + at MI-regexp + + * cc-mode.el: commented out bogus part + + * cc-mode.el: commented out bogus top level continuation indentations + +Mon Jan 25 23:34:52 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed minor bug with c++-submit-bug-report which manifests + only on unpatched emacses + + * cc-mode.el: fixed small bug in c++-submit-bug-report manifesting + in unpatched emacses + +Thu Jan 21 23:38:34 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + c++-indent-exp must let-bind parse-sexp-ignore-comments to t for the + whole duration + + * cc-mode.el: + hack for c++-indent-sexp continued statement offsets... are there + repercussions??? + + * cc-mode.el: fixed c++-cont-indent free variable + + * cc-mode.el: partial fix of continuation lines at top level + +Wed Jan 20 23:39:40 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: 1. remove infinite loop from c++-in-literal + 2. get rid of messages + + note that c++-in-literal-quick is broken wrt to old emacs patches + +Wed Jan 13 22:57:51 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + c++-end-of-defun needed to let-bind parse-sexp-ignore-comments to t + + * cc-mode.el: better c++-in-literal-quick + + * cc-mode.el: 1. cosmetic cleanups of code + 2. a pass through c++-mode docstring and all variables + + * cc-mode.el: another hack on the comments at the top of the file + + * cc-mode.el: a documentation pass + + * cc-mode.el: changed name of c++-backward-over-syntactic-ws to just + c++-backward-syntactic-ws to more closely resemble new lemacs builtin + function name. + + * cc-mode.el: fixed c++-syntax-mode-table to work with patched lemacs + +Sat Jan 9 05:08:25 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: put # back as a comment-style + + * cc-mode.el: comment about new bc and backward-syntactic-ws + + * cc-mode.el: better syntax specifications for new patched lemacs + +Thu Jan 7 22:22:53 1993 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + added c++-backward-sexp and c++-forward-sexp which are bound to M-C-f + and M-C-b and work better than their non-c++-mode counterparts since + they let-bind parse-sexp-ignore-comments to t. + +Thu Dec 31 22:17:36 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + use the really, really, up-to-date syntax patch for Lemacs 19 + +Tue Dec 29 01:22:19 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: removed extraneous commented out code + + * cc-mode.el: need to ensure that c-mode is loaded in + + * cc-mode.el: + fixed a problem inside member init lists, where the first member (on + the colon line) has its args continued + + * cc-mode.el: + fix bug when indenting a line at level zero which begins at the + beginning of buffer + +Wed Dec 23 23:20:05 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fix for c++-indent-exp so that it properly indents c block comments + +Fri Dec 18 16:15:12 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: greater improvements on c++-b-o-w-s performance + +Thu Dec 17 23:29:18 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + another run at optimizing c++-backward-over-syntactic-ws based on + information gleaned from calc.el experience + + * cc-mode.el: + c++-backward-over-syntactic uses beginning-of-defun instead of + point-min as minimum distance to scan back + +Wed Dec 16 21:52:41 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + check for brace insertion at not-quite-end-of-line (ie eol, ignoring + any trailing ws) + + * cc-mode.el: allow c++-backscan-limit to be nil + +Fri Dec 11 16:26:05 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + in electric terminator, don't just check for eolp to determine if + terminator should electrify. also look for hanging whitespace which + may look like eolp, even though it isn't: + + fooo();......\n + ^------^ + undiscovered ws---| + +Thu Dec 10 22:59:25 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + simple fix in calculate indent so forward-char 1 at end of buffer + won't throw an error + +Wed Dec 9 17:55:17 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + error in default value for c++-untame-characters. needed to negate the + check for c++-emacs-is-fixed-p + + * cc-mode.el: + fixed problems in electric-(star|slash) when inserting as first + character in a buffer. + + * cc-mode.el: + don't treat double-colon as member init when member defun is split + across two lines at the scope operator. eg: + + HereIsAReallyLongClassName + ::HereIsAReallyLongClassName( const WithALongConstructorArgument& ) + : andItsFirstMemberInit( 7 ) + {} + + * cc-mode.el: added some thanks to the documentation + +Tue Dec 8 23:57:27 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + better c++-submit-bug-report that works with all known mailers + +Mon Dec 7 16:26:51 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed calculation of multiple member-inits where double colons can + appear inside initing parens + + * cc-mode.el: improved documentation for c++-special-indent-hook + +Sat Dec 5 02:52:04 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: handled member init lists with first embedded colon + + foo() : foo, foo, + foo, foo, + ^--- this should probably be indented to + ^--- here (under colon) + + but that's really hard and of minimal use. + + * cc-mode.el: + finally figured out that "questionable member init" indentation + section. It occurs when you have the following style: + + foo(...) : + foo(9), blat(10), + clob(3) + + Note the colon hanging on the previous line. Steve Vinoski is correct, + we should not subtract a level of indentation from the shift since + inclass-shift takes care of it. + + * cc-mode.el: + seems like a fix for some close parens not getting outdented when + c++-paren-as-block-close-p is t. DOES ANYTHING ELSE BREAK???? + +Fri Dec 4 22:11:27 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed continued expression in a simple if statement where there is a + comment between the if and the simple statement. + +Thu Dec 3 23:38:27 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: cleaned up some documentation + + * cc-mode.el: fixed c++-indent-exp for stream operators + +Tue Dec 1 18:01:45 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + c++-backward-over-syntactic-ws should always be given a backlimit in + c++-calculate-indent. + + * cc-mode.el: + in previous fix for c++-c-i, it is possible that containing-sexp is + nil, so use (goto-char (or containing-sexp bod)) + + * cc-mode.el: + enhancements to c++-calculate-indent so that it doesn't assume that + class opening brace starts in column zero. + + * cc-mode.el: + c++-submit-bug-report now reports whether emacs is patched + +Mon Nov 30 23:39:13 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed K&R C arg decl indentations + + * cc-mode.el: cosmetic changes + + * cc-mode.el: removed old c++-bosw which was too slow anyway + +Fri Nov 27 20:18:12 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed comment indentation for new c++-comment-only-line-offset + semantics, and also simplified electric-star and electric-slash. They + no longer call c++-electric-terminator. + +Fri Nov 13 22:42:04 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: some documentation improvements + + * cc-mode.el: + fixed erroneous newline insertion on member init colons when + c++-auto-newline is off. + + * cc-mode.el: fixed buggy regexp which would fail on this situation: + + int foo( // foo + int arg1, // arg1 + int arg2 + + last line gets indented wrong because of the spaces b/w the foo( and + the comment + + * cc-mode.el: 1. alphabetized varlist in c++-dump-state + 2. improved portability of c++-submit-bug-report for mailers other + than vm. + + * cc-mode.el: + use comment-start-skip instead of hard-coded comment regexp + + * cc-mode.el: + 1. added c++-emacs-is-fixed-p to check for a patched emacs + 2. automatically set c++-untame-characters to nil if patched + + * cc-mode.el: + fixed comment-line indent calculation. now c++-calculate-indent does + no comment-line calculations, its all handled in c++-indent-line and + c++-indent-sexp + + * cc-mode.el: slight documentation fixup + + * cc-mode.el: + vastly improved c++-comment-only-line-offset to provide ability to + determine column-zero offsets + + * cc-mode.el: attempt to speed up c++-backward-over-syntactic-ws + +Thu Nov 12 16:45:30 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + 1. some experimental performance enhancements (not working really great) + 2. in c++-at-top-level-p, check for null containing-sexp before in-parens + +Tue Nov 3 20:46:19 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + removed the variable c++-class-member-indent and replaced all + occurances with c-indent-level. it caused very bad things when + c-indent-level != c++-class-member-indent + + * cc-mode.el: c++-match-paren must set parse-sexp-ignore-comments to t + +Fri Oct 2 22:31:14 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + perhaps optimization on skipping backwards over c++ literal comment + +Tue Sep 29 00:19:22 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: replaced code accidently removed during last bug fix + +Mon Sep 28 22:44:51 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed default[ \t]*: indentation bug + + * cc-mode.el: + continuation indentation problem should now work correctly. + c++-in-function-p search from containing-sexp or point + + * cc-mode.el: + added c++-in-function-p defun to be used when checking if we're in a + function. Continuations inside a function + + * cc-mode.el: fixed the LCD Archive Entry syntax + + * cc-mode.el: removed c++-fill-C-comment, function is unused anywhere + +Tue Sep 1 21:02:17 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: 1. compatibility code for loading into a patched emacs + 2. also a *slightly* improved c++-backward-over-syntactic-ws. This + function needs a drastic overhaul -- I bet its the main performance + pig now that emacs is patched. + +Fri Aug 28 22:07:39 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: final cleansing before posting + +Thu Aug 27 16:41:30 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: added GNU copyright info + + * cc-mode.el: standard header and many comment changes + +Wed Aug 26 23:40:46 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: cleaned up documentation + + * cc-mode.el: yet again, better documentation about untame characters + + * cc-mode.el: better documentation on c++-untame-characters + + * cc-mode.el: + added some documentation to the front of the file to describe untame + characters + + * cc-mode.el: + default value for c++-untame-characters is now just single tick, the + most troublesome character + +Thu Aug 20 19:29:00 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + only check for inside template spec if looking at c++-class-key + + * cc-mode.el: + attempted to address keyword "class" appearing inside a template + specification: + + template + Foo& Bar::doit( void ){}; + + template + Foo& Bar::doit( void ){}; + +Tue Aug 11 14:06:02 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: updated docstring for c++-at-top-level-p + +Mon Aug 10 22:19:52 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: c++-c-mode's mode-name is "C" + + * cc-mode.el: style 1-3 is default for c++-C-block-comments-indent-p + +Thu Aug 6 19:47:36 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed auto-indenting of C block comment style 3 + +Wed Aug 5 21:25:39 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: another patch to docstring + + * cc-mode.el: another docstring change + + * cc-mode.el: qualify doc string change of previous revision + + * cc-mode.el: + improved (hopefully) the docstring for var c++-untame-characters + + * cc-mode.el: more optimizations by passing bod to c++-at-top-level-p + + * cc-mode.el: parameterized c++-class-key and c++-access-key + the first is class\|struct\|union + the second is public\|protected\|private + + * cc-mode.el: + fixed (c++-at-top-level-p t) so it won't get fooled by struct declarations. + + * cc-mode.el: + fixed c++-at-top-level-p so it won't get fooled by struct declarations + +Tue Aug 4 20:59:29 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed docstring for c++-tab-always-indent + +Wed Jul 29 14:50:46 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + this branch combines C and C++ modes for inclusion into emacs 19 + +Tue Jul 28 19:28:29 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed documentation for c++-C-block-comments-indent-p + +Mon Jul 27 15:13:36 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed indentation of member init list after a multiline member init call + +Thu Jul 23 19:59:45 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed c++-electric-pound when inserting # at beginning of buffer + + * cc-mode.el: simple fix for *some* sequence continuation lines + +Wed Jul 22 13:28:54 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed (c++-at-top-level-p t) so it wouldn't return non-nil if keyword + class appears in arglist + + * cc-mode.el: + added to c++-calculate-indent a check if we're at the bobp + +Tue Jul 21 21:59:27 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + new function c++-calculate-c-indent-within-comment used instead of + calculate-c-indent-within-comment (from c-mode). Supports 4 styles of + C block comments. + + Also, new variable c++-C-block-comments-indent-p to control which + style(s) to use. + + * cc-mode.el: + fixed c++-indent-exp to handle public/private/protected with friends + + * cc-mode.el: fixed indentation for the following style: + + class foo { + friend class bar; + public: + foo(); + private: + }; + +Mon Jul 20 20:22:58 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + 1. added c++-paren-as-block-close-p to control whether a closing paren is + treated as a closing brace. + + 2. also added c++-block-close-brace-offset to bug list of variables + + * cc-mode.el: added a c++-c-mode-syntax-table + NOTE: patch in previous version DOES work + + * cc-mode.el: rewrite of c++-at-top-level-p for c mode (doesn't work) + +Fri Jul 17 20:14:30 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + change syntax table entry to support lemacs 19 syntax table extension + WARNING: this may change + +Thu Jul 16 19:35:21 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed comment-only lines in c++-indent-exp + + * cc-mode.el: + patch to c++-indent-exp to make it work consistently with manual + tabbing + + * cc-mode.el: + better c++-(un)comment-region functions as supplied by enami + +Wed Jul 15 18:07:13 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + C mode entry point, including a properly working c++-(un)comment-region + + * cc-mode.el: + use c++-backward-over-syntactic-ws in another appropriate location in + c++-calculate-indent + +Tue Jul 14 21:33:04 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: implemented Brian Kennedy's patches for { if style + seems to be clean now + + * cc-mode.el: regexp to correctly pickup '\\' character constant + + * cc-mode.el: + new regexp to match even number of backslashes followed by a quote for + c++-in-literal matching of string terminators + +Mon Jul 13 18:25:21 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + better fix to c++-at-top-level-p for limiting backsearching of + class/struct + + * cc-mode.el: another patch to c++-at-top-level-p, but now slower + + * cc-mode.el: + Igor Metz's patch to fix c++-uncomment-region for Emacs 19 + derivatives since zap-to-char now works differently + +Fri Jul 10 22:02:26 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + in c++-fill-C-comment, its cleaner to use let-bind fill-prefix itself + instead of saving its value and later restoring it. + + * cc-mode.el: + c++-at-top-level-p never returns non-nil if inside the parens of an + arg decl list for a function. Also cleaned up c++-at-top-level-p's + docstring for new functionality + + * cc-mode.el: 1. added usage notes to top of file + 2. another fix for indentation of member init lists in nested classes + + * cc-mode.el: fixed member init continuation lines + + * cc-mode.el: + fixed emtpy-defun-braces cleanup when at top level wrt enclosing class + + * cc-mode.el: fixed nested class member init list indentation + +Thu Jul 9 21:54:08 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + added c++-class-member-indent to varlist in bug submission + + * cc-mode.el: nested classes! + added a variable c++-class-member-indent to handle indentation of + class members relative to their enclosing class + + * cc-mode.el: + new c++-at-top-level-p function for nested class definitions (does not + work though) + + * cc-mode.el: + optimized by changing all references to c++-in-comment-p and + c++-in-open-string-p to use memq and c++-in-literal. This should + overall reduce the number of calls to c++-in-literal, a time consuming + defun. + + * cc-mode.el: + c++-electric-star will now re-indent the line when typed as the first + character on a line of a C block style comment continuation + + * cc-mode.el: + fix to c++-at-top-level-p to ignore struct/class declarations inside a + defun which are not definitions: + + void foo() + { + struct blah; + + // we are not now (c++-at-top-level-p t) + + The function is still not perfect so we really need to rethink this + algorithm. + + * cc-mode.el: + collapse all c++-point-* commands into a single c++-point command with + an argument + +Wed Jul 8 19:40:14 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed parse-start setq in c++-calculate-indent + +Tue Jul 7 22:03:41 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: pasing => parsing + + * cc-mode.el: grammer -> grammar in comment + + * cc-mode.el: + implemented c++-backward-over-syntactic-ws with help of Tor Lillqvist + and replaced all occurances of + c++-backward-over-cpp-directives and c++-skip-backward-to-noncomment. + +Mon Jul 6 21:25:17 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + colon and semi-colon are no longer electric inside of literals + + * cc-mode.el: it is possible that c++-beginning-of-defun with + c++-match-header-strong equal to nil will incorrectly find the + beginning of defun. if this happens, c++-parse-state will return a + null state so we can check for this and then let* bind + c++-match-header-strongly to t. Then we re-calculate the beginning of + the c++ defun. + + Seems to work around the (char-after ...) bug + + * cc-mode.el: swap back to another use of c++-parse-state + + * cc-mode.el: + 1. don't inherit syntax table from c-mode. Initialize completely from + in this file + 2. wrote c++-parse-state to centralize parsing of syntactic context + +Tue Jun 30 21:39:23 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed a bug in brace-else-brace cleanup where insertion of new + (non-else) brace could possibly go way back to clean up old else brace + constructs. + + * cc-mode.el: + use new c++-cleanup-list to replace c++-cleanup-brace-else-brace-p and + c++-cleanup-empty-defun-braces-p, and to implement new cleanup on + close semi. + + * cc-mode.el: + fixed c++-electric-pound behavior for # directives in a level of + nesting for alignleft behavior + + * cc-mode.el: + c++-cleanup-empty-defun-braces-p only for defun braces (not for empty + if braces for example) + + * cc-mode.el: + only do the extra c++-indent-line in c++-electric-brace if hanging + braces is turned off + +Wed Jun 24 20:07:00 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + added a c++-indent-line in the c++-electric-brace to fix non-hanging + brace error message. + + * cc-mode.el: + added function c++-skip-backwards-over-cpp-directives for improved + indentation around # lines. + +Tue Jun 23 19:35:27 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed stream op positioning when first >> or << is on the next + continued line of the statement. + + * cc-mode.el: + hacking the mode line should only occur in c++-mode defun, when the + mode line is a list, otherwise, if people use the obsolete string-only + form, their mode line will be made invalid. + + * cc-mode.el: + fixed indentation of lines not at top level, which follow preprocessor + directive lines. + +Fri Jun 19 21:46:58 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed bug when access specifier line has a comment at the end of it + + * cc-mode.el: simplified all point-marks to use (point-marker) + +Thu Jun 18 15:10:04 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed c++-electric-pound by using insert-before-markers + + * cc-mode.el: 1. added c++-electric-pound command and bound it to # + 2. also added c++-electric-pound-behavior to control how # behaves. + Currently only supported behavior is alignleft, but eventually I + will support nested behavior as well. + 3. changed the way c++-electric-delete and c++-insert-command work on + # lines. delete is never hungry in the whitespace b/w # and + directive, and tab only inserts in this area as well. + + * cc-mode.el: + added c++-delete-function variable and made c++-electric-delete use + this variable + +Wed Jun 17 22:29:12 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + added c++-special-indent-hook and bug reporting of this variable + + * cc-mode.el: support for lining up >> and << + + * cc-mode.el: + added c++-matching-paren as contrib'd by Gnanasekaran Swaminathan + +Mon Jun 15 21:07:29 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed c++-indent-command when looking at a blank line and + c++-tab-always-indent is nil + + * cc-mode.el: + another fix to c++-indent-command for c++-tab-always-indent == nil + + * cc-mode.el: + made c++-indent-command behavior when c++-tab-always-indent is nil + consistent with documentation + +Thu Jun 11 22:44:47 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + added a test to see if c++-auto-newline actually inserts the newline + doing the auto-fill + +Wed Jun 10 19:10:31 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed indentation of first member function after an access specifier + inside a class definition + +Tue Jun 9 22:45:24 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + c++-submit-bug-report uses pop-to-buffer instead of switch-buffer + + * cc-mode.el: refined regexp patch in previous fix + + * cc-mode.el: + fixed c++-calculate-indent int the situation where we're looking at + the line after a class declaration, but we're not inheriting. see the + lines after: + ;; else first check to see if its a + ;; multiple inheritance continuation line + + the regexp should match optional inheritance syntax. + + * cc-mode.el: + small fix to c++-at-top-level for checking if at top wrt a containing + class definition. (previous fix didn't work) + + * cc-mode.el: + 1. fixed small bug in c++-at-top-level-p for nested in class checking + 2. fixed bug in indentation of continued arg lists in class nested + function declarations + +Mon Jun 8 21:50:48 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: removed extra define-key of DEL in c++-mode-map init + + * cc-mode.el: fixed friend offset in c++-indent-exp + + * cc-mode.el: + indent by c++-friend-offset for all friends, not just class friends + + * cc-mode.el: fixed scan-lists failure in c++-at-top-level-p + + * cc-mode.el: fixed bogus colon entry "premature sexp end" bug + + * cc-mode.el: much preliminary work for inline code proper formatting + + * cc-mode.el: fixed double colon cleanup inside defun level + + * cc-mode.el: added variable c++-cleanup-empty-defun-braces-p + + * cc-mode.el: default value for c++-comment-only-line-offset is now 0 + + * cc-mode.el: fixed c++-electric-delete's consuming of [] characters + + * cc-mode.el: c++-cleanup-brace-else-brace-p is now nil by default + + * cc-mode.el: + fixed c++-hanging-member-init-colon for all known situations + +Fri Jun 5 21:13:54 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: reorganized the major sections of code + +Tue Jun 2 15:18:25 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: more optimizations using c++-beginning-of-defun + +Mon Jun 1 22:24:52 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: interrim speedups + + * cc-mode.el: + another patch to c++-in-literal for checking for null strings. I think + I've got it this time... + + * cc-mode.el: + fixed the regexp for matching the closing double quote of a string + +Thu May 28 22:24:09 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: added a (provide ...) to the end of the file + + * cc-mode.el: changed c++-brace-}-else-{-p to c++-brace-else-brace-p + + * cc-mode.el: fixed hanging base classes for multiple inheritance + + * cc-mode.el: + completely rewrote c++-backward-to-noncomment to use c++-in-literal + function. + + * cc-mode.el: + replace all beginning-of-defun calls with c++-beginning-of-defun which + more correctly find the true beginning of a c++ definition + + * cc-mode.el: + fixed c++-in-literal for the case where "" appears as a string + + * cc-mode.el: + fixed bug in c++-calculate-indent when class line is first line in + file. also there may be no space between the class name and colon. + + * cc-mode.el: + fixed c++-backward-to-noncomment bug when looking at # lines + + * cc-mode.el: + fixed indentation of top-level construct immediately preceeded by a + c-block comment + +Wed May 27 23:30:43 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + complete replacement for c++-in-open-string-p and c++-in-comment-p + +Tue May 26 22:25:39 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: added Warner Losh's addition of c++-relative-offset-p + + * cc-mode.el: + patched c++-backward-to-start-of-do to ignore do/while constructs in + comments + + * cc-mode.el: yet another patch to c++-in-comment-p + +Fri May 22 18:09:04 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + added c++-access-specifier-offset for extra indentation for public, + protected, and private keyword lines + +Thu May 21 19:18:31 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: cosmetic changes + +Wed May 20 22:53:43 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed typo with c++-always-arglist-indent-p + + * cc-mode.el: + mode-line-format is now not completely overridden, but instead, the + c++-isms are tacked onto the format after the mode-name symbol (if it + exists). + + * cc-mode.el: installed Terry Glanfield's patch to c++-indent-exp + + * cc-mode.el: documented c++-always-arglist-indent, changed the name to + c++-always-arglist-indent-p and added to bug report list. + + * cc-mode.el: + installed Milo Chan's patch for addition of c++-always-arglist-indent + + * cc-mode.el: + small patch to fix whitespace only line before top-level construct + + * cc-mode.el: + rewrote c++-tame-comments to look at a list of characters to tame. + Also removed c++-tame-comments-p and replaced it with + c++-tame-characters + + * cc-mode.el: equivalenced class and struct keyword syntacticly + +Tue May 19 19:34:16 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed multiple inheritance continuation indentation + + * cc-mode.el: fixed indentation for member init lists when colon hangs + + * cc-mode.el: + 1. c++-electric-colon is made smarter so that it only adds newlines + after a colong when absolutely necessary + + 2. extended semantics of c++-hanging-member-init-colon + + * cc-mode.el: fixed small bug in constness fix of 2.55 + +Mon May 18 21:55:14 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed top level enum constructs + + * cc-mode.el: fixed indentation when inputing after a const function + + * cc-mode.el: handle default: lines exactly line case: lines + +Thu May 14 21:37:53 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: updated info at top of file re, bug reports + + * cc-mode.el: + fixed continued statements inside a simple for/if style loop + + * cc-mode.el: fixed member-init bug introduced in v2.47 + +Wed May 13 20:45:33 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: yet another patch to c++-in-comment-p + + * cc-mode.el: + added interactive command c++-version and bound it to C-c C-v + +Tue May 12 21:37:20 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: another patch to c++-in-comment-p + + * cc-mode.el: + fixed c++-calculate-indent to ignore parens and such which occur in + comment regions during the initial iterative parse of the defun. + + * cc-mode.el: + in c++-in-comment-p, it was necessary to set ?/ temporarily to ". 14" + class so that c++ style comments wouldn't affect parse-partial-sexp + + * cc-mode.el: + tab does not insert a C style comment block continuation line when + point is on or before the first non-whitespace character on the line. + +Mon May 11 22:28:30 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: added variable c++-tame-comments-p + + * cc-mode.el: + fixed c++-in-comment-p to handle special case of C style block comments + + * cc-mode.el: added some documentation to c++-mode + + * cc-mode.el: + C-c C-b is the accepted standard for c++-submit-bug-report + +Fri May 8 20:47:38 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + 1. cleaned up all the intro information at the top of the file + 2. added c++-submit-bug-report function and related variables. + + * cc-mode.el: fixed mailing list info + + * cc-mode.el: added information about c++-mode-victims mailing list. + + * cc-mode.el: + fixed c++-tame-comments. now we tame all string and parenthesis class + characters. + + * cc-mode.el: + changed syntax of single quote back to string class and added + c++-electric-tick and c++-tame-ticks defuns to handle backslashifying + single quotes in comment areas. + +Thu May 7 20:03:32 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + added fix by Reed Hastings so that c++-indent-exp + can properly terminate when // style comments are found within the + function. + + * cc-mode.el: + c++-calculate-indent should now not re-indent comment-only lines which + begin in comment-column + + * cc-mode.el: + fixed c++-electric-terminator insertion when auto-newline fills a long + line due to auto-fill being on. + + * cc-mode.el: + comment only lines which continue previous line's comment field would + probably be indented in comment-column so those comments which begin + in comment-column don't indent + +Wed May 6 17:29:16 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + handle comment-only lines which continue from the previous line. + +Mon May 4 23:33:51 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + added a few of Hallvard's speedups (but not the c++-auto-newline one) + + * cc-mode.el: changed all functions to conform to c++- style + + * cc-mode.el: + changed the variable c-tab-always-indent to c++-tab-always-indent and + extended this variable's functionality. + + * cc-mode.el: forgot to remove the debug statement + + * cc-mode.el: simplified c++-cleanup-}-else-{-p + +Sat May 2 18:12:21 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: changed c++-cleanup-}-else-{ to c++-cleanup-}-else-{-p + +Fri May 1 21:09:09 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + beginnings of } else { cleanup, but not completely bugless yet + + * cc-mode.el: + fixed indent-c++-exp. when setting this-indent as max of different + values, max it with 0 not 1, otherwise some things won't ever end up + in column zero. + + * cc-mode.el: + I think I've extended calculate-c++-indent to properly handle + switch/case statements (at least the style that I use). + +Thu Apr 30 22:21:51 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: added c++-backward-to-start-of-do, which is analogous to + c-backward-to-start-of-if and finds the corresponding preceding do for + a do/while statement. made the necessary changes to + calculate-c++-indent to handle nested do's + + * cc-mode.el: + this version will now handle continued statements with no compound + statements on ifs, elses, fors, dos, and whiles. + + * cc-mode.el: add tab-width to the list of variables to dump... + +Wed Apr 29 22:23:25 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + simplification of auto-hungry functions and mode-line updates with + much thanks to Hallvard Furuseth. + + * cc-mode.el: + copied c++-in-parens-p from c-mode's c-inside-parens-p. this is so we + can play with trying to work around emacs' bogus syntax bugs. we'll + see if the new behavior is any better + + * cc-mode.el: + eliminate infinite loop bug in c++-indent-defun by using a marker. + this is necessary since c++-indent-line could change the location of + the marker and just saving its buffer position is not sufficient. + + * cc-mode.el: + close parens act like close braces by indenting to c-indent-level + plus value of c++-block-close-brace-offset. + + * cc-mode.el: + fixed infinite loop problem in c++-indent-defun which was caused by + substituting forward-line for next-line. + + * cc-mode.el: some changes to calculate-c++-indent defun + 1. fixed unbalanced paren problem (emacs bug) in comment by adding a + paren to the j.peck hack comment (probably should eventually clean + up these comments) + + 2. applied Doug Moore's (dougm@cs.rice.edu) patch to fix continued + function declarations of the form: + + int foo( int i, + int j ); + ^---- next line should only indent to here + + 3. cleaned up some comment sections + + * cc-mode.el: + added the variable c++-block-close-brace-offset for modifying the + offset of close braces for non-top level blocks (i.e. braces which + don't close a function). + + * cc-mode.el: + removed c++-delete-is-hungry-in-literals-p. Delete key is now, + *never* hungry inside literals. + +Tue Apr 28 22:38:35 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed free variable problems in indent-c++-exp + 1. innerloop-done was let'ed as inner-loop-done. changed all + innerloop-done's to inner-loop-done in body of defun + + 2. last-depth wasn't let'ed + + * cc-mode.el: + added c++-delete-is-hungry-in-literals-p to control whether + hungry-delete consumes whitespace even in literals. + + * cc-mode.el: + whoops, parse-start was a free variable in c++-at-top-level-p. I just + added the local binding to the let statement in that defun. + + * cc-mode.el: + changed c++-hanging-braces-p to c++-hanging-braces. this variable can + now control whether hanging braces happen always, never, or only on + non-top level open braces. + + * cc-mode.el: fixed comment-only line related bugs: + + 1. comment-only lines not in the first column, but at the top level + were inserting all tab characters. + + 2. fixed #1, but this caused non-comment top-level lines which follow + indented top-level comment-only lines to indent, which they + shouldn't do. + + I think this fixes all repercussions of comment-only lines. + + * cc-mode.el: + replaced all next-line's with forward-line's since next-line is really + a user level function (and may be overloaded by the user). + +Mon Apr 27 16:03:29 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed enum entry bug reported by Rolf Schreiber by patching + c++-backward-to-noncomment. it is possible that (max (point-bol) lim) + is greater than point, which chokes the search-backward call. I now + have a test for sblim being less than or equal to point. + +Fri Apr 24 22:02:47 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + 1. added documentation in c++-mode for auto-hungry states and related + variables. + 2. removed duplicated setq's in c++-mode buffer-local-variable setups + + * cc-mode.el: more header doc information + +Wed Apr 22 22:30:31 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: final clean up before posting + + * cc-mode.el: bumping to baseline rev number 2.0 + +Thu Apr 16 17:05:40 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: added LCD Archive Entry and new file header format + +Wed Apr 15 19:44:38 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed column zero comment-only line indentation problem when inside a + containing-sexp. + + * cc-mode.el: needed to add a trailing newline for proper unsharing + +Tue Apr 14 18:12:22 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: Bumping + + * cc-mode.el: added bug reporting information + +Fri Apr 10 17:48:46 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: cleaned up c++-mode doc string + + * cc-mode.el: + 1. updated mode documentation string for c++-mode to include new + variables. + + 2. changed c++-auto-hungry-toggle-p to c++-auto-hungry-toggle since it + is not a binary valued variable. + + * cc-mode.el: + changed ' syntax back to string quote instead of punctuation + +Thu Apr 9 22:26:00 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: added a (goto-char (point-min)) in c++-dump-state + + * cc-mode.el: added c++-dump-state function for bug reporting + +Tue Mar 31 23:38:56 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: lots of toggling options, plus individual toggling for + hungry-delete-key and auto-newline states. + + * cc-mode.el: added organization + +Fri Mar 27 23:19:32 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: major renovation on auto/hungry toggling + +Thu Mar 26 23:43:09 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + use better mode-line formatting instead of hacking mode-name + +Fri Mar 20 20:38:29 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + made buffer-local c++-auto-newline and c++-hungry-delete-key-p + +Thu Mar 19 19:16:14 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + bound c++-toggle-auto-newline function to C-cC-t and compacted info + mode name + + * cc-mode.el: + use better mode-line updating than (redraw-display) in c++-toggle-auto-newline + +Wed Mar 18 19:52:14 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: fixed display of c++-toggle-auto-newline + +Tue Mar 17 21:01:05 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: test for c++-hungry-delete-key-p (typo) + +Mon Mar 16 22:14:18 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: added c++-hungry-delete-key-p + + * cc-mode.el: handles auto newline for member init list + + * cc-mode.el: replaced within-c++-string w/ c++-in-open-string-p + + * cc-mode.el: lots of fixes for: + 1. column zero comments don't indent + 2. made electric chars comment & open-string safe + 3. made electric brace w/auto-fill work + 4. made calculate-c++-indent work for while( foo ) style + 5. added c++-hanging-braces-p for no auto-newline on left braces + +Sat Mar 14 07:01:14 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: + fixed double-colon and various other problems with c-auto-newline + also changed c-auto-newline to c++-auto-newline + + * cc-mode.el: fixed c-auto-newline for double colons and }; syntax + + * cc-mode.el: fixed autoindent of comments for hanging arithmetic + +Fri Mar 13 23:47:34 1992 Barry A. Warsaw, ITB (warsaw@anthem) + + * cc-mode.el: better documentation for electric-c++-slash + + * cc-mode.el: + fixed c++-indent-line to work with electric-c++-slash and bind "/" to it + + * cc-mode.el: added c++-comment-only-line-offset + + * cc-mode.el: Initial revision + + +Local Variables: +add-log-mailing-address: "bug-cc-mode@gnu.org" +End: diff --git a/site-lisp/cc-mode/5.32.3/MANIFEST b/site-lisp/cc-mode/5.32.3/MANIFEST new file mode 100644 index 0000000..8a9b5d1 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/MANIFEST @@ -0,0 +1,43 @@ +Manifest for CC Mode 5.31 + +You should have received the following files in this distribution: + + MANIFEST: This file. + + README: Quick intro into how to get CC Mode up and running. + + NEWS: A list of the user visible changes in each version. + + COPYING: The copyright license under which this package is + released. + + cc-align.el, cc-awk.el, cc-cmds.el, cc-defs.el, cc-engine.el, + cc-fonts.el, cc-guess.el, cc-langs.el, cc-menus.el, cc-mode.el, + cc-styles.el, cc-subword.el, cc-vars.el: The source code. + + cc-compat.el: Helps ease the transition from c-mode.el (BOCM) to + the new indentation engine. This is provided for your convenience + only, and is unguaranteed and unsupported. + + cc-fix.el: (previously named cc-mode-19.el). Detects and corrects + bugs in various older (X)Emacs versions. + + cc-lobotomy.el: Performance vs. accuracy trade-offs. May not + work, yadda, yadda. + + cc-bytecomp.el: Contains helpers used during byte compiling to + ensure that there's no mixup with earler versions of CC Mode which + might be loaded. + + cc-mode.texi: The latest CC Mode Texinfo manual. + + ANNOUNCEMENT: Release announcement as it appeared on various + forums. + +Note that of the above files, the following are distributed with Emacs +and XEmacs: + + cc-align.el, cc-awk.el, cc-bytecomp.el, cc-cmds.el, cc-compat.el, + cc-defs.el, cc-engine.el, cc-fonts.el, cc-guess.el, cc-langs.el, + cc-menus.el, cc-mode.el, cc-styles.el, cc-subword.el, cc-vars.el, + cc-mode.texi diff --git a/site-lisp/cc-mode/5.32.3/NEWS b/site-lisp/cc-mode/5.32.3/NEWS new file mode 100644 index 0000000..4734158 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/NEWS @@ -0,0 +1,1094 @@ +CC Mode NEWS -- user visible changes. -*- outline -*- + +* Changes in 5.32 + +This version contains few, but big, new features, and significant internal +improvements. + +** CC Mode is now licensed under the GPL version 3 or any later version. + +** Emacs 21 is no longer supported, +although CC Mode might well still work with it. The minimum versions +supported are Emacs 22 and XEmacs 21.4. + +** It is now possible for CC Mode to "guess" an existing buffer's style. +This style can then be used in other buffers. Contributed by Masatake YAMATO, +after original code by Barry Warsaw. + +** Java Mode has been enhanced to support Java 5.0 (Tiger) and Java 6 (Mustang). +Contributed by Nathaniel Flath. + +** c-beginning-of-defun and c-end-of-defun now respect nested scopes. +Thus C-M-a will, by default, go to the beginning of the immediate function, +not the top level. + +** "Macros with semicolons" can be registered, for correct indentation. +Where such a macro ends a line (no semicolon), the next statement is no longer +parsed as a statement continuation. + +** Many bugs have been fixed, font locking has become more accurate, angle +brackets are better handled, and sluggish code has been optimised. + +* Changes in 5.31 + +This version contains only a few new visible features, but significant +internal improvements. + +** Emacs 19.34 and XEmacs 19.15 are no longer supported. +The minimum versions required are now Emacs 20.4 or XEmacs 21.4. + +** The CC Mode manual has been extensively revised. +The information about using CC Mode has been separated from the larger +and more difficult chapters about configuration. + +*** There are now two variants of the manual - for GNU Emacs and XEmacs. +The only difference between them is where some cross references point +(e.g. GNU Emacs Manual vs. XEmacs Manual). The default variant is for +GNU. To build an XEmacs version, you must define the texinfo symbol +"XEMACS". See README and cc-mode.texi. + +** Changes in Key Sequences +*** c-toggle-auto-hungry-state is no longer bound to C-c C-t. + +*** c-toggle-hungry-state is no longer bound to C-c C-d. +This binding has been taken over by c-hungry-delete-forwards. + +*** c-toggle-auto-state (C-c C-t) has been renamed to c-toggle-auto-newline. +c-toggle-auto-state remains as an alias. + +*** c-hungry-backspace has been renamed to c-hungry-delete-backwards. +c-hungry-backspace remains as an alias. + +*** c-hungry-delete-backwards and c-hungry-delete-forwards +now have permanent key bindings, respectively C-c C-DEL (or C-c DEL, for +the benefit of TTYs) and C-c C-d (or C-c C- or C-c ). +These commands delete entire blocks of whitespace with a single +key-sequence. [N.B. "DEL" is the key.] + +*** The new command c-toggle-electric-mode is bound to C-c C-l. + +*** The new command c-subword-mode is bound to C-c C-w. + +** C-c C-s (`c-show-syntactic-information') now highlights the anchor +position(s). + +** The new GtkDoc Doc Comment style has become the default for C Mode. +Contributed by Masatake YAMATO. + +** New Minor Modes +*** Electric Minor Mode toggles the electric action of non-alphabetic keys. +The new command c-toggle-electric-mode is bound to C-c C-l. Turning the +mode off can be helpful for editing chaotically indented code and for +users new to CC Mode, who sometimes find electric indentation +disconcerting. Its current state is displayed in the mode line with an +'l', e.g. "C/al". + +*** Subword Minor Mode makes Emacs recognize word boundaries at upper case +letters in StudlyCapsIdentifiers. You enable this feature by C-c C-w. It can +also be used in non-CC Mode buffers. :-) Contributed by Masatake YAMATO. +Subword Minor Mode doesn't (yet?) work in Emacs 20.n. + +** New clean-ups + +*** `comment-close-slash'. +With this clean-up, a block (i.e. c-style) comment can be terminated by +typing a slash at the start of a line. + +*** `c-one-liner-defun' +This clean-up compresses a short enough defun (for example, an AWK +pattern/action pair) onto a single line. "Short enough" is configurable. + +** AWK support +AWK Mode is now better integrated into CC Mode as a whole. In detail: + +*** Comment and line-breaking commands now work for AWK. + +*** M-a and M-e (c-beginning/end-of-statement) now work for AWK. + +*** "awk" style, Auto-newline insertion, special AWK initialization hook. +A new style, "awk" has been introduced, and this is now the default +style for AWK code. With its introduction, Auto-newline insertion can +be used freely for AWK code, and there is no longer a need for the +special initialization function in the AWK Mode hook. + +*** The standard Line-up functions still haven't been adapted for AWK. +Some of these may work serendipitously. There shouldn't be any problems +writing custom indentation functions for AWK mode. + +*** AWK Font Locking still hasn't been fully integrated into CC Mode. +There is just a single level of font locking in AWK mode. + +* Changes in 5.30 + +There is a lot of change in this version, so it's considered experimental. It is however fairly well tested already since the developers have an extensive test suite to ensure correct syntactic analysis and font locking. + +** Font lock support. +CC Mode now provides font lock support for all its languages. This +supersedes the font lock patterns that have been in the core font lock +package for C, C++, Java and Objective-C. Like indentation, font +locking is done in a uniform way across all languages (except the new +AWK mode - see below). That means that the new font locking will be +different from the old patterns in various details for most languages. + +The main goal of the font locking in CC Mode is accuracy, to provide a +dependable aid in recognizing the various constructs. Some, like +strings and comments, are easy to recognize while others, like +declarations and types, can be very tricky. CC Mode can go to great +lengths to recognize declarations and casts correctly, especially when +the types aren't recognized by standard patterns. This is a fairly +demanding analysis which can be slow on older hardware, and it can +therefore be disabled by choosing a lower decoration level with the +variable font-lock-maximum-decoration. + +Note that the most demanding font lock level has been tuned with lazy +fontification in mind, i.e. there should be a support mode that waits +with the fontification until the text is actually shown +(e.g. Just-in-time Lock mode, which is the default in Emacs 21, or +Lazy Lock mode). Fontifying a file with several thousand lines in one +go can take the better part of a minute even on a fast system. + +*** The (c|c++|objc|java|idl|pike)-font-lock-extra-types variables +are now used by CC Mode to recognize identifiers that are certain to +be types. (They are also used in cases that aren't related to font +locking.) At the maximum decoration level, types are often recognized +properly anyway, so these variables should be fairly restrictive and +not contain patterns for uncertain types. + +*** Support for documentation comments. +There is a "plugin" system to fontify documentation comments like +Javadoc and the markup within them. It's independent of the host +language, so it's possible to e.g. turn on Javadoc font locking in C +buffers. See the variable c-doc-comment-style for details. + +Currently two kinds of doc comment styles are recognized: Suns Javadoc +and Autodoc which is used in Pike. This is by no means a complete +list of the most common tools; if your doc comment extractor of choice +is missing then please drop a note to bug-cc-mode@gnu.org. + +*** Better handling of C++ templates. +As a side effect of the more accurate font locking, C++ templates are +now handled much better. The angle brackets that delimit them are +given parenthesis syntax so that they can be navigated like other +parens. + +This also improves indentation of templates, although there still is +work to be done in that area. E.g. it's required that multiline +template clauses are written in full and then refontified to be +recognized, and the indentation of nested templates is a bit odd and +not as configurable as it ought to be. + +*** Improved handling of Objective-C and CORBA IDL. +Especially the support for Objective-C and IDL has gotten an overhaul. +The special "@" declarations in Objective-C are handled correctly. +All the keywords used in CORBA IDL, PSDL, and CIDL are recognized and +handled correctly, also wrt indentation. + +** Support for the AWK language. +Support for the AWK language has been introduced. The implementation is +based around GNU AWK version 3.1, but it should work pretty well with +any AWK. As yet, not all features of CC Mode have been adapted for AWK. +Here is a summary: + +*** Indentation Engine +The CC Mode indentation engine fully supports AWK mode. + +AWK mode handles code formatted in the conventional AWK fashion: `{'s +which start actions, user-defined functions, or compound statements are +placed on the same line as the associated construct; the matching `}'s +are normally placed under the start of the respective pattern, function +definition, or structured statement. + +The predefined indentation functions haven't yet been adapted for AWK +mode, though some of them may work serendipitously. There shouldn't be +any problems writing custom indentation functions for AWK mode. + +The command C-c C-q (c-indent-defun) hasn't yet been adapted for AWK, +though in practice it works properly nearly all the time. Should it +fail, explicitly set the region around the function (using C-u C-SPC: +C-M-h probably won't work either) then do C-M-\ (indent-region). + +*** Font Locking +There is a single level of font locking in AWK mode, rather than the +three distinct levels the other modes have. There are several +idiosyncrasies in AWK mode's font-locking due to the peculiarities of +the AWK language itself. + +*** Comment Commands +M-; (indent-for-comment) works fine. None of the other CC Mode +comment formatting commands have yet been adapted for AWK mode. + +*** Movement Commands +Most of the movement commands work in AWK mode. The most important +exceptions are M-a (c-beginning-of-statement) and M-e +(c-end-of-statement) which haven't yet been adapted. + +The notion of "defun" has been augmented to include AWK pattern-action +pairs. C-M-a (c-awk-beginning-of-defun) and C-M-e (c-awk-end-of-defun) +recognise these pattern-action pairs, as well as user defined +functions. + +*** Auto-newline Insertion and Clean-ups +Auto-newline insertion hasn't yet been adapted for AWK. Some of +the clean-ups can actually convert good AWK code into syntactically +invalid code. These features are best disabled in AWK buffers. + +** New syntactic symbols in IDL mode. +The top level constructs "module" and "composition" (from CIDL) are +now handled like "namespace" in C++: They are given syntactic symbols +module-open, module-close, inmodule, composition-open, +composition-close, and incomposition. + +** New lineup function c-lineup-string-cont. +This lineup function lines up a continued string under the one it +continues. E.g: + +result = prefix + "A message " + "string."; <- c-lineup-string-cont + +** New functions to do hungry delete without enabling hungry delete mode. +The functions c-hungry-backspace and c-hungry-delete-forward can be +bound to keys to get this feature without toggling a mode. +Contributed by Kevin Ryde. + +** Better control over require-final-newline. +The variable that controls how to handle a final newline when the +buffer is saved, require-final-newline, is now customizable on a +per-mode basis through c-require-final-newline. The default is to set +it to t only in languages that mandate a final newline in source files +(C, C++ and Objective-C). + +** Format change for syntactic context elements. +The elements in the syntactic context returned by c-guess-basic-syntax +and stored in c-syntactic-context has been changed somewhat to allow +attaching more information. They are now lists instead of single cons +cells. E.g. a line that previously had the syntactic analysis + +((inclass . 11) (topmost-intro . 13)) + +is now analysed as + +((inclass 11) (topmost-intro 13)) + +In some cases there are more than one position given for a syntactic +symbol. + +This change might affect code that call c-guess-basic-syntax directly, +and custom lineup functions if they use c-syntactic-context. However, +the argument given to lineup functions is still a single cons cell +with nil or an integer in the cdr. + +** API changes for derived modes. +There have been extensive changes "under the hood" which can affect +derived mode writers. Some of these changes are likely to cause +incompatibilities with existing derived modes, but on the other hand +care has now been taken to make it possible to extend and modify CC +Mode with less risk of such problems in the future. + +*** New language variable system. +See the comment blurb near the top of cc-langs.el. + +*** New initialization functions. +The initialization procedure has been split up into more functions to +give better control: c-basic-common-init, c-font-lock-init, and +c-init-language-vars. + +** Compiled byte code is now (X)Emacs version specific. +Previously byte compiled versions of CC Mode could be shared between +major (X)Emacs versions to some extent. That is no longer the case +since macros are now used extensively to adapt to (X)Emacs specific +features without sacrificing performance. + +* Changes in 5.29 + +Note: This was an unfinished interim release that was never publicly +announced. + +** Changes in analysis of nested syntactic constructs. +The syntactic analysis engine has better handling of cases where +several syntactic constructs appear nested on the same line. They are +now handled as if each construct started on a line of its own. + +This means that CC Mode now indents some cases differently, and +although it's more consistent there might be cases where the old way +gave results that's more to one's liking. So if you find a situation +where you think that the indentation has become worse, please report +it to bug-cc-mode@gnu.org. + +*** New syntactic symbol substatement-label. +This symbol is used when a label is inserted between a statement and +its substatement. E.g: + + if (x) + x_is_true: + do_stuff(); + +** Better handling of multiline macros. + +*** Syntactic indentation inside macros. +The contents of multiline #define's are now analyzed and indented +syntactically just like other code. This can be disabled by the new +variable c-syntactic-indentation-in-macros. A new syntactic symbol +cpp-define-intro has been added to control the initial indentation +inside #define's. + +*** New lineup function c-lineup-cpp-define. +Now used by default to line up macro continuation lines. The behavior +of this function closely mimics the indentation one gets if the macro +is indented while the line continuation backslashes are temporarily +removed. If syntactic indentation in macros is turned off, it works +much line c-lineup-dont-change, which was used earlier, but handles +empty lines within the macro better. + +*** Automatically inserted newlines continues the macro if used within one. +This applies to the newlines inserted by the auto-newline mode, and to +c-context-line-break and c-context-open-line. + +*** Better alignment of line continuation backslashes. +c-backslash-region tries to adapt to surrounding backslashes. New +variable c-backslash-max-column which put a limit on how far out +backslashes can be moved. + +*** Automatic alignment of line continuation backslashes. +This is controlled by the new variable c-auto-align-backslashes. It +affects c-context-line-break, c-context-open-line and newlines +inserted in auto-newline mode. + +*** Line indentation works better inside macros. +Regardless whether syntactic indentation and syntactic indentation +inside macros are enabled or not, line indentation now ignores the +line continuation backslashes. This is most noticeable when syntactic +indentation is turned off and there are empty lines (save for the +backslash) in the macro. + +** indent-for-comment is more customizable. +The behavior of M-; (indent-for-comment) is now configurable through +the variable c-indent-comment-alist. The indentation behavior is +based on the preceding code on the line, e.g. to get two spaces after +#else and #endif but indentation to comment-column in most other cases +(something which was hardcoded earlier). + +** New function c-context-open-line. +It's the open-line equivalent of c-context-line-break. + +** New lineup functions + +*** c-lineup-cascaded-calls +Lines up series of calls separated by "->" or ".". + +*** c-lineup-knr-region-comment +Gives (what most people think is) better indentation of comments in +the "K&R region" between the function header and its body. + +*** c-lineup-gcc-asm-reg +Provides better indentation inside asm blocks. Contributed by Kevin +Ryde. + +*** c-lineup-argcont +Lines up continued function arguments after the preceding comma. +Contributed by Kevin Ryde. + +** Better caching of the syntactic context. +CC Mode caches the positions of the opening parentheses (of any kind) +of the lists surrounding the point. Those positions are used in many +places as anchor points for various searches. The cache is now +improved so that it can be reused to a large extent when the point is +moved. The less it moves, the less needs to be recalculated. + +The effect is that CC Mode should be fast most of the time even when +opening parens are hung (i.e. aren't in column zero). It's typically +only the first time after the point is moved far down in a complex +file that it'll take noticeable time to find out the syntactic +context. + +** Statements are recognized in a more robust way. +Statements are recognized most of the time even when they occur in an +"invalid" context, e.g. in a function argument. In practice that can +happen when macros are involved. + +** Improved the way c-indent-exp chooses the block to indent. +It now indents the block for the closest sexp following the point +whose closing paren ends on a different line. This means that the +point doesn't have to be immediately before the block to indent. +Also, only the block and the closing line is indented; the current +line is left untouched. + +** Added toggle for syntactic indentation. +The function c-toggle-syntactic-indentation can be used to toggle +syntactic indentation. + +* Changes in 5.28 + +** The hardcoded switch to "java" style in Java mode is gone. +CC Mode used to automatically set the style to "java" when Java mode +is entered. This has now been removed since it caused too much +confusion. + +However, to keep backward compatibility to a certain extent, the +default value for c-default-style now specifies the "java" style for +java-mode, but "gnu" for all other modes (as before). So you won't +notice the change if you haven't touched that variable. + +** New cleanups, space-before-funcall and compact-empty-funcall. +Two new cleanups have been added to c-cleanup-list: + +space-before-funcall causes a space to be inserted before the opening +parenthesis of a function call, which gives the style "foo (bar)". + +compact-empty-funcall causes any space before a function call opening +parenthesis to be removed if there are no arguments to the function. +It's typically useful together with space-before-funcall to get the +style "foo (bar)" and "foo()". + +** Some keywords now automatically trigger reindentation. +Keywords like "else", "while", "catch" and "finally" have been made +"electric" to make them reindent automatically when they continue an +earlier statement. An example: + +for (i = 0; i < 17; i++) + if (a[i]) + res += a[i]->offset; +else + +Here, the "else" should be indented like the preceding "if", since it +continues that statement. CC Mode will automatically reindent it after +the "else" has been typed in full, since it's not until then it's +possible to decide whether it's a new statement or a continuation of +the preceding "if". + +CC Mode uses Abbrev mode to achieve this, which is therefore turned on +by default. + +** M-a and M-e now moves by sentence in multiline strings. +Previously these two keys only moved by sentence in comments, which +meant that sentence movement didn't work in strings containing +documentation or other natural language text. + +The reason it's only activated in multiline strings (i.e. strings that +contain a newline, even when escaped by a '\') is to avoid stopping in +the short strings that often reside inside statements. Multiline +strings almost always contain text in a natural language, as opposed +to other strings that typically contain format specifications, +commands, etc. Also, it's not that bothersome that M-a and M-e misses +sentences in single line strings, since they're short anyway. + +** Support for autodoc comments in Pike mode. +Autodoc comments for Pike are used to extract documentation from the +source, like Javadoc in Java. Pike mode now recognize this markup in +comment prefixes and paragraph starts. + +** The comment prefix regexps on c-comment-prefix may be mode specific. +When c-comment-prefix is an association list, it specifies the comment +line prefix on a per-mode basis, like c-default-style does. This +change came about to support the special autodoc comment prefix in +Pike mode only. + +** Better handling of syntactic errors. +The recovery after unbalanced parens earlier in the buffer has been +improved; CC Mode now reports them by dinging and giving a message +stating the offending line, but still recovers and indent the +following lines in a sane way (most of the time). An "else" with no +matching "if" is handled similarly. If an error is discovered while +indenting a region, the whole region is still indented and the error +is reported afterwards. + +** Lineup functions may now return absolute columns. +A lineup function can give an absolute column to indent the line to by +returning a vector with the desired column as the first element. + +** More robust and warning-free byte compilation. +Although this is strictly not a user visible change (well, depending +on the view of a user), it's still worth mentioning that CC Mode now +can be compiled in the standard ways without causing trouble. Some +code have also been moved between the subpackages to enhance the +modularity somewhat. Thanks to Martin Buchholz for doing the +groundwork. + +* Changes in 5.27 + +Note: This is mostly a bugfix release. The features labeled +experimental in 5.26 remain and are now considered permanent. + +** c-style-variables-are-local-p now defaults to t. +This is an incompatible change that has been made to make the behavior +of the style system wrt global variable settings less confusing for +non-advanced users. If you know what this variable does you might +want to set it to nil in your .emacs, otherwise you probably don't +have to bother. + +Defaulting c-style-variables-are-local-p to t avoids the confusing +situation that occurs when a user sets some style variables globally +and edit both a Java and a non-Java file in the same Emacs session. +If the style variables aren't buffer local in this case, loading of +the second file will cause the default style (either "gnu" or "java" +by default) to override the global settings made by the user. + +* Changes in 5.26 + +Note: This release contains changes that might not be compatible with +current user setups (although it's believed that these +incompatibilities will only show up in very uncommon circumstances). +However, since the impact is uncertain, these changes may be rolled +back depending on user feedback. Therefore there's no forward +compatibility guarantee wrt the new features introduced in this +release. + +** New initialization procedure for the style system. +When the initial style for a buffer is determined by CC Mode (from the +variable c-default-style), the global values of style variables now +take precedence over the values specified by the chosen style. This +is different from the old behavior: previously, the style-specific +settings would override the global settings. This change makes it +possible to do simple configuration in the intuitive way with +Customize or with setq lines in one's .emacs file. + +By default, the global value of every style variable is the new +special symbol set-from-style, which causes the value to be taken from +the style system. This means that in effect, only an explicit setting +of a style variable will cause the "overriding" behavior described +above. + +Also note that global settings override style-specific settings *only* +when the initial style of a buffer is chosen by a CC Mode major mode +function. When a style is chosen in other ways --- for example, by a +call like (c-set-style "gnu") in a hook, or via M-x c-set-style --- +then the style-specific values take precedence over any global style +values. In Lisp terms, global values override style-specific values +only when the new second argument to c-set-style is non-nil; see the +function documentation for more info. + +The purpose of these changes is to make it easier for users, +especially novice users, to do simple customizations with Customize or +with setq in their .emacs files. On the other hand, the new system is +intended to be compatible with advanced users' customizations as well, +such as those that choose styles in hooks or whatnot. This new system +is believed to be almost entirely compatible with current +configurations, in spite of the changed precedence between style and +global variable settings when a buffer's default style is set. + +(Thanks to Eric Eide for clarifying this explanation a bit.) + +*** c-offsets-alist is now a customizable variable. +This became possible as a result of the new initialization behavior. + +This variable is treated slightly differently from the other style +variables; instead of using the symbol set-from-style, it will be +completed with the syntactic symbols it doesn't already contain when +the style is first initialized. This means it now defaults to the +empty list to make all syntactic elements get their values from the +style system. + +*** Compatibility variable to restore the old behavior. +In case your configuration doesn't work with this change, you can set +c-old-style-variable-behavior to non-nil to get the old behavior back +as far as possible. + +** Improvements to line breaking and text filling. +CC Mode now handles this more intelligently and seamlessly wrt the +surrounding code, especially inside comments. For details see the new +chapter about this in the manual. + +*** New variable to recognize comment line prefix decorations. +The variable c-comment-prefix-regexp has been added to properly +recognize the line prefix in both block and line comments. It's +primarily used to initialize the various paragraph recognition and +adaptive filling variables that the text handling functions uses. + +*** New variable c-block-comment-prefix. +This is a generalization of the now obsolete variable +c-comment-continuation-stars to handle arbitrary strings. + +*** CC Mode now uses adaptive fill mode. +This to make it adapt better to the paragraph style inside comments. + +It's also possible to use other adaptive filling packages inside CC +Mode, notably Kyle E. Jones' Filladapt mode (http://wonderworks.com/). +A new convenience function c-setup-filladapt sets up Filladapt for use +inside CC Mode. + +Note though that the 2.12 version of Filladapt lacks a feature that +causes it to work suboptimally when c-comment-prefix-regexp can match +the empty string (which it commonly does). A patch for that is +available from the CC Mode web site (http://www.python.org/emacs/ +cc-mode/). + +*** It's now possible to selectively turn off auto filling. +The variable c-ignore-auto-fill is used to ignore auto fill mode in +specific contexts, e.g. in preprocessor directives and in string +literals. + +*** New context sensitive line break function c-context-line-break. +It works like newline-and-indent in normal code, and adapts the line +prefix according to the comment style when used inside comments. If +you're normally using newline-and-indent, you might want to switch to +this function. + +*** c-hanging-comment-starter-p and c-hanging-comment-ender-p are obsolete. +The new comment handling code no longer consults these two variables. +It instead detects how the "hangingness" of the comment delimiters +look like currently and simply keeps them that way. + +** Fixes to IDL mode. +It now does a better job in recognizing only the constructs relevant +to IDL. E.g. it no longer matches "class" as the beginning of a +struct block, but it does match the CORBA 2.3 "valuetype" keyword. +Thanks to Eric Eide. + +** Improvements to the Whitesmith style. +It now keeps the style consistently on all levels and both when +opening braces hangs and when they don't. + +*** New lineup function c-lineup-whitesmith-in-block. + +** New lineup functions c-lineup-template-args and c-indent-multi-line-block. +See their docstrings for details. c-lineup-template-args does a +better job of tracking the brackets used as parens in C++ templates, +and is used by default to line up continued template arguments. + +** c-lineup-comment now preserves alignment with a comment on the +previous line. It used to instead preserve comments that started in +the column specified by comment-column. + +** c-lineup-C-comments handles "free form" text comments. +In comments with a long delimiter line at the start, the indentation +is kept unchanged for lines that start with an empty comment line +prefix. This is intended for the type of large block comments that +contain documentation with its own formatting. In these you normally +don't want CC Mode to change the indentation. + +** The `c' syntactic symbol is now relative to the comment start +instead of the previous line, to make integers usable as lineup +arguments. + +** All lineup functions have gotten docstrings. + +** More preprocessor directive movement functions. +c-down-conditional does the reverse of c-up-conditional. +c-up-conditional-with-else and c-down-conditional-with-else are +variants of these that also stops at "#else" lines (suggested by Don +Provan). + +** Minor improvements to many movement functions in tricky situations. + +* Changes in 5.25 + +This is a bug fix release only. + +* Changes in 5.24 + +Note: See also changes in 5.23 to get the complete list of additions +since the last public release. + +** c-default-style can now take an association list that maps major +modes to style names. When this variable is an alist, Java mode no +longer hardcodes a setting to "java" style. See the variable's +docstring for details. + +** It's now possible to put a list as the offset on a syntactic +symbol. The list is evaluated recursively until a non-nil offset is +found. This is useful to combine several lineup functions to act in a +prioritized order on a single line. However, none of the supplied +lineup functions use this feature currently. + +** New syntactic symbol catch-clause, which is used on the "catch" and +"finally" lines in try-catch constructs in C++ and Java. + +** New cleanup brace-catch-brace on c-cleanup-list, which does for +"catch" lines what brace-elseif-brace does for "else if" lines. + +** The braces of Java anonymous inner classes are treated separately +from the braces of other classes in auto-newline mode. Two new +symbols inexpr-class-open and inexpr-class-close may be used on +c-hanging-braces-alist to control the automatic newlines used for +anonymous classes. + +** bug-cc-mode@gnu.org is now the primary bug reporting address. +This is an alias for cc-mode-help@python.org. + +* Changes in 5.23 + +Note: Due to the extensive changes, this version was a beta test +release that was never publicly announced. + +** Support for the Pike language added, along with new Pike specific +syntactic symbols: inlambda, lambda-intro-cont + +** Support for Java anonymous classes via new syntactic symbol +inexpr-class. New syntactic symbol inexpr-statement for Pike +support and gcc-style statements inside expressions. New lineup +function c-lineup-inexpr-stat. + +** New syntactic symbol brace-entry-open which is used in brace lists +(i.e. static initializers) when a list entry starts with an open +brace. These used to be recognized as brace-list-entry's. +c-electric-brace also recognizes brace-entry-open braces +(brace-list-entry's can no longer be electrified). + +** New command c-indent-line-or-region, not bound by default. + +** Improvements to M-C-h (c-mark-function). + +** `#' is only electric when typed in the indentation of a line. + +** Parentheses are now electric (via the new command c-electric-paren) +for auto-reindenting lines when parens are typed. + +** In "gnu" style, inline-open offset is now set to zero. + +** Uniform handling of the inclass syntactic symbol. The indentation +associated with it is now always relative to the class opening brace. +This means that the indentation behavior has changed in some +circumstances, but only if you've put anything besides 0 on the +class-open syntactic symbol (none of the default styles do that). + +** c-enable-xemacs-performance-kludge-p is set to nil by default, +since for Emacs-friendly styles (i.e. where the top-level opening +brace starts in column zero) setting this variable to t can degrade +performance significantly. + +* Changes in 5.22 + +Note: There was no net release of 5.22! This version went only to the +XEmacs developers and was primarily a bug fix release. + +* Changes in 5.21 + +This is a bug fix release only. + +* Changes in 5.20 + +** Multiline macros are now handled, both as they affect indentation, +and as recognized syntax. New syntactic symbol cpp-macro-cont is +assigned to second and subsequent lines of a multiline macro +definition. + +** A new style "user" which captures all non-hook-ified +(i.e. top-level) .emacs file variable settings and customizations. +Style "cc-mode" is an alias for "user" and is deprecated. "gnu" style +is still the default however. + +** "java" style now conforms to Sun's JDK coding style. + +** New commands c-beginning-of-defun, c-end-of-defun which are not +bound by default to C-M-a and C-M-e. + +** New and improved implementations of M-a (c-beginning-of-statement) +and M-e (c-end-of-statement). + +** C++ namespace blocks are supported, with new syntactic symbols +namespace-open, namespace-close, and innamespace. + +** File local variable settings of c-file-style and c-file-offsets +makes the style variables local to that buffer only. + +** New indentation functions c-lineup-close-paren, +c-indent-one-line-block, c-lineup-dont-change. + +** Various Imenu patches (thanks to Masatake Yamato, Jan Dubois, and +Peter Pilgrim). + +** Performance improvements. Some improvements affect only Emacs or +only XEmacs (see the variable c-enable-xemacs-performance-kludge-p). + +** Improvements (hopefully!) to the way CC Mode is loaded. You should +now be able to do a (require 'cc-mode) to get the entire package +loaded properly for customization in your .emacs file. A new variable +c-initialize-on-load controls this and is set to t by default. + +* Changes in 5.19 + +** extern-lang-close relative buffer positions have changed. The used +to point to the extern's open brace, but they now point to the first +non-whitespace character on the line with the open brace. + +** c-progress-interval's semantics have changed slightly. When set to +nil, indentation proceeds silently. Previously, even when nil, the +start and end messages were printed. + +* Changes in 5.18 + +** M-a and M-e should now properly move into comments when point is +before or after a comment, and move by sentences when inside a +comment. + +** c-electric-slash should be bound in all modes now. Also, +c-expand-macro is not bound in Java or IDL modes. + +** Imenu enhancements: Objective-C support donated by Masatake (jet) +YAMATO; a fix to Java support given by Ake Stenhoff; and improvements +to C++ support given by Jan Dubois. + +* Changes in 5.17 + +** Recognition of enum declarations in K&R argdecls. + +** Changes to "python" style to more closely match Python C API coding +standards. + +** / is bound to c-electric-slash in all modes, and C-c C-e is bound +to c-expand-macro in all languages except Java and IDL. + +* Changes in 5.16 + +This is primarily a bug fix release. Users of XEmacs 19.15 and Emacs +19.34 are highly encouraged to pick up this release. + +* Changes in 5.15 + +** A new syntactic symbol: template-args-cont, used in C++ template +declarations where the argument list spans multiple lines. + +** In "java" style, c-hanging-comment-starter-p defaults to nil to +preserve Javadoc starter lines. + +** Line oriented comments (i.e. C++ style comments) are now recognized +by default in all modes, including C mode (as per the ANSI 9X C draft +standard). Thus the function c-enable-//-in-c-mode has been removed. + +** Auto-filling of comments has been improved. CC Mode will now +properly auto-fill both line and block oriented comments, and allows +you to choose the leader string on block oriented continued comments, +via the variable c-comment-continuation-stars. See the CC Mode manual +for details. + +** c-electric-slash is electric in all modes. + +** The need for c-mode-19.el is automatically detected now. You do +not need to load or require it in your .emacs file. + +* Changes in 5.14 + +** Support for CORBA's IDL language. There is now a new mode called +idl-mode, with all the expected hooks, abbreviation tables, etc. + +** In "java" style, c-hanging-comment-starter-p is set to nil by +default to preserve Javadoc comments. + +** A new hook variable: c-initialization-hook. This is called only +once an X/Emacs session, when the CC Mode package is initialized. + +* Changes in version 5 + +CC Mode version 5 was a major upgrade, as evidenced by the change in +major revision number. Here is a list of the important user visible +changes in CC Mode 5. + +** CC Mode 5 will not work with Emacs 18, and will only work with the +latest Emacs and XEmacs releases. + +** c-mode-map is no longer the base keymap for all modes. This was +incompatible with the way Emacs 19 supports menus, so now +c-mode-base-map is the base map for all modes (including c-mode-map). +If you are installing custom keybindings into c-mode-map and expecting +them to be present in all other modes, this will break. Put your +keybindings in c-mode-base-map instead. + +** The function c-electric-delete and variable c-delete-function are +handled differently now, in order to accommodate the separation of the +BackSpace and Delete keysyms. CC Mode now binds only the Delete +keysym to c-electric-delete (which runs c-delete-function), and the +BackSpace keysym to c-electric-backspace (which runs +c-backspace-function). See the CC Mode manual for details. + +** The single cc-mode.el file was simply too unwieldy so I have split +the file up. See the MANIFEST file for details. + +** Also, all user variables have been converted to Per Abrahamsen's +Custom library, and all support for older Emacsen have been ripped +out. See the release notes for details of running CC Mode 5 in your +version of Emacs. + +** All style variables are now global by default. Specifically, the +default value for c-style-variables-are-local-p is nil. The same +rules apply as before, only reversed: if you want the style variables +to be buffer local, you should set c-style-variables-are-local-p to t +before you load CC Mode. + +* Changes from 4.322 to 4.353 + +** Better control over the buffer localness of the indentation variables. + +In previous version of cc-mode the variables that control indentation +were always buffer local. This was applauded by those who edited +files in many different styles, but reviled by those who usually edit +files of only one style. + +You can now control whether these variables are buffer local or not, +by setting the variable c-style-variables-are-local-p. This variable +only has effect at the time cc-mode.el is loaded. If this variable is +non-nil, then all indentation style related variables will be made +buffer local. Otherwise, they will remain global, so that users can +actually use setq in their top-level .emacs file without having to use +a mode hook. + +Note that once the variables are made buffer local, they cannot be +made global again; they will remain buffer local for the rest of the +current Emacs session. The list of variables that are buffer +localizable are: + + c-offsets-alist + c-basic-offset + c-file-style + c-file-offsets + c-comment-only-line-offset + c-cleanup-list + c-hanging-braces-alist + c-hanging-colons-alist + c-hanging-comment-ender-p + c-backslash-column + c-label-minimum-indentation + c-special-indent-hook + c-indentation-style + +For backwards compatibility, the default value of +c-style-variables-are-local-p is non-nil, meaning the variables are +buffer local by default. This may change in the future. + +** New variable c-indentation-style which holds the current style name +of the buffer. + +** Menus are not installed when running in Infodock. + +** Improvements to the alignment of C block comments. +The variable c-block-comments-indent-p has been removed. + +I have improved the c-lineup-C-comments function, which is responsible +for lining up subsequent lines in C block comments. It should now do +the Right Thing for most comment styles that use some combination of +stars at the beginning of comment lines (including zero stars! :-). +For example, the following styles are aligned correctly by default: + +int main() +{ + /* + * + */ + + /* + ** + ** + */ + + /** + ** + ** + **/ + + /*** + *** + *** + *** + ***/ + + /** + *** + *** + **/ +} + +For this reason, the variable c-block-comments-indent-p has been +removed. + +** New indentation style python. +The blessed standard for writing Python extension modules in C. + +** New c-cleanup-list option: brace-elseif-brace + +* Changes from 4.282 to 4.322 + +** A new style linux has been added. + +**The following variables have been removed from the default cc-mode +style: + c-echo-syntactic-information-p + c-strict-syntax-p + c-tab-always-indent + c-inhibit-startup-warnings-p + +** External language declaration blocks are now handled properly. +Three new syntactic symbols have been added: + +*** extern-lang-open +The brace that opens an extern block. Hangable via +c-hanging-braces-alist. + +*** extern-lang-close +The brace that closes an extern block. Hangable via +c-hanging-braces-alist. + +*** inextern-lang +A modifier (with no relative buffer position) which is added to +topmost-intro syntax lines that occur within an extern block. See the +texinfo manual for details. + +** New variable: c-label-minimum-indentation which defines the minimum +indentation a label can have in gnu style. This variable has no +effect in other styles. + +** c-special-indent-hook is handled slightly differently when it +appears in a style definition; the functions in the style definition +are appended to the global value of c-special-indent-hook. + +** c-style-alist is defconst'd now. +This should eliminate problems people had with Java mode. + +** Lambda expressions (anonymous functions) can now be used as custom +indentation functions. + +** Whitespace is allowed between the protection keyword (public, +private, protected) and the trailing colon in C++. + +** Java mode now recognizes the finally and synchronized keywords. + +** New lineup function: c-lineup-arglist-close-under-paren. +Try setting arglist-close to this function. + +** The variable c-recognize-knr-p is deprecated. +Now by default, c-mode will always recognize K&R argument declarations +with no performance penalty. cc-mode has adopted BOCM's approach +which assumes that argdecls will always be indented at least one +space, while the function headers they are associated with will not be +indented at all. If your programming style differs from this, you may +have trouble. You should remove any setting of this variable from +your cc-mode configurations! + +** New variable c-insert-tab-function, normally just inserts a tab +character when indicated by c-tab-always-indent and indent-tabs-mode. +You could set this to run tab-to-tab-stop instead. + +** C-s C-s (c-show-syntactic-information) now takes an optional +universal argument, which inserts the analysis into the buffer on the +current line, as a comment. + +** c-mark-function has been moved to C-c C-m. + +** In addition, I have made a change to the way braces which are given +inline-open syntax are handled. + +In the following sample: + + 1: class Outer + 2: { + 3: void a_function( int a ) + 4: { + 5: do_something( a ); + 6: } + 7: class Inner + 8: { + 9: void b_function( int b ) + 10: { + 11: do_something( b ); + 12: } + 13: } + 14: } + +cc-mode 4.282 would have analyzed line 4 as ((inline-open . 1)), and +line 10 as ((inline-open . 87)). So the fact that this brace opened +an inclass-inline method which should be given extra indentation, was +implicit in the syntactic symbol. + +Some people have argued that the inclass modifier should be added to +the analysis of such lines. This release implements this change so +that line 4 is now analyzed as ((inclass . 1) (inline-open)) and line +10 as ((inclass . 87) (inline-open)). The inline-open symbol has no +relative buffer position so that braces in nested classes would not be +indented too much. diff --git a/site-lisp/cc-mode/5.32.3/README b/site-lisp/cc-mode/5.32.3/README new file mode 100644 index 0000000..e4acd6a --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/README @@ -0,0 +1,105 @@ +README for CC Mode 5.32 +Current maintainer : Alan Mackenzie +Contact address : bug-cc-mode@gnu.org + +INTRODUCTION + + The canonical web location for all knowledge CC Mode is: + + + + Please read the cc-mode.texi manual for details on using CC Mode. + This is available on-line from: + + + + As of this writing (August 2011), CC Mode currently works + out of the box with XEmacs versions 21.4 and later, and with Emacs + versions 22 and later. (It might well still work with some earlier + versions and will very likely work with later versions too, when + they become available.) + +MORE INFORMATION + + Check out the CC Mode web site for the latest information, + updates, tips, installation and compatibility notes, etc. on using + CC Mode. The installation instructions given below are an excerpt + of the on-line instructions. If you have problems installing CC + Mode, please check out the URL above before submitting a bug + report. Thanks! + + The MANIFEST file contains a description of all the files you + should have gotten with this distribution. + +MANUALS + + Preformatted versions of the manual in DVI, PostScript, and Info, + are all available at the CC Mode web page. The Info manual has + two variants, one for GNU Emacs, the other for XEmacs - the only + differences between them are the targets of some cross references + within the manual. + + To build the manual yourself, you will need Texinfo 4.7 or later. + Simply type: + + % makeinfo cc-mode.texi # For GNU Emacs + or + % makeinfo -DXEMACS cc-mode.texi # For XEmacs + + To make the DVI version, type: + + % texi2dvi cc-mode.texi + +INSTALLATION + + Here is a quick guide for installing CC Mode. For the latest + information on installing CC Mode, please see the CC Mode web site + given above. + + If you're using XEmacs, make sure you've got the "advice" package + installed. + + Byte Compiling + + It is highly recommended that you byte-compile CC Mode for + performance reasons. Running CC Mode non-byte-compiled is not + supported. + + You can compile CC Mode in the same way as any other package. To + compile it from a running (X)Emacs session: + + M-0 M-x byte-recompile-directory RET /path/to/cc-mode RET + + To compile CC Mode from the shell: + + % cd /path/to/cc-mode + % $(EMACS) -batch -no-site-file -q -f batch-byte-compile cc-*.el + + where $(EMACS) is either emacs or xemacs depending on the flavor + you use. Note that the byte compiled files from one version of + (X)Emacs are likely not to work on a different version - compile + them fresh when you upgrade your (X)Emacs version. + + Installing + + Put the compiled files somewhere (X)Emacs will find them, i.e. in + some path that's in the load-path variable. You must make sure + they are found before any CC Mode files which are distributed with + (X)Emacs. A directory has higher precendence than all directories + after it in the load-path list. + + To test that you have things set up correctly, visit a C file and + then type: + + M-x c-version RET + => Using CC Mode version 5.XX + + where XX is the correct minor revision number. + + Compatibility Issues + + CC Mode should work fine with most versions of Emacs and XEmacs + which aren't ancient (see the introduction above). + + For more details about interactions with different packages, see + the CC Mode web page. diff --git a/site-lisp/cc-mode/5.32.3/cc-align.el b/site-lisp/cc-mode/5.32.3/cc-align.el new file mode 100644 index 0000000..dcad7b8 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-align.el @@ -0,0 +1,1349 @@ +;;; cc-align.el --- custom indentation functions for CC Mode + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2004- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 22-Apr-1997 (split from cc-mode.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-engine) + + +;; Standard line-up functions +;; +;; See the section "Custom Indentation Functions" in the manual for +;; details on the calling convention. + +(defun c-lineup-topmost-intro-cont (langelem) + "Line up declaration continuation lines zero or one indentation step. +For lines in the \"header\" of a definition, zero is used. For other +lines, `c-basic-offset' is added to the indentation. E.g: + +int +neg (int i) <- c-lineup-topmost-intro-cont +{ + return -i; +} + +struct +larch <- c-lineup-topmost-intro-cont +{ + double height; +} + the_larch, <- c-lineup-topmost-intro-cont + another_larch; <- c-lineup-topmost-intro-cont +<--> c-basic-offset + +struct larch +the_larch, <- c-lineup-topmost-intro-cont + another_larch; <- c-lineup-topmost-intro-cont + +\(This function is mainly provided to mimic the behavior of CC Mode +5.28 and earlier where this case wasn't handled consistently so that +these lines could be analyzed as either topmost-intro-cont or +statement-cont.) + +Works with: topmost-intro-cont." + (save-excursion + (beginning-of-line) + (c-backward-syntactic-ws (c-langelem-pos langelem)) + (if (and (memq (char-before) '(?} ?,)) + (not (and c-overloadable-operators-regexp + (c-after-special-operator-id)))) + c-basic-offset))) + +(defun c-lineup-gnu-DEFUN-intro-cont (langelem) + "Line up the continuation lines of a DEFUN macro in the Emacs C source. +These lines are indented as though they were `knr-argdecl-intro' lines. +Return nil when we're not in such a construct. + +This function is for historical compatibility with how previous CC Modes (5.28 +and earlier) indented such lines. + +Here is an example: + +DEFUN (\"forward-char\", Fforward_char, Sforward_char, 0, 1, \"p\", + doc: /* Move point right N characters (left if N is negative). +On reaching end of buffer, stop and signal error. */) + (n) <- c-lineup-gnu-DEFUN-into-cont + Lisp_Object n; <- c-lineup-gnu-DEFUN-into-cont + +Works with: topmost-intro-cont." + (save-excursion + (let (case-fold-search) + (goto-char (c-langelem-pos langelem)) + (if (looking-at "\\") + (c-calc-offset '(knr-argdecl-intro)))))) + +(defun c-block-in-arglist-dwim (arglist-start) + ;; This function implements the DWIM to avoid far indentation of + ;; brace block constructs in arguments in `c-lineup-arglist' etc. + ;; Return non-nil if a brace block construct is detected within the + ;; arglist starting at ARGLIST-START. + + (or + ;; Check if the syntactic context contains any of the symbols for + ;; in-expression constructs. This can both save the work that we + ;; have to do below, and it also detect the brace list constructs + ;; that `c-looking-at-inexpr-block' currently misses (they are + ;; recognized by `c-inside-bracelist-p' instead). + (assq 'inexpr-class c-syntactic-context) + (assq 'inexpr-statement c-syntactic-context) + (assq 'inlambda c-syntactic-context) + + (save-restriction + ;; Search for open braces from the arglist start to the end of the + ;; line. + (narrow-to-region arglist-start (c-point 'eol arglist-start)) + + (goto-char arglist-start) + (while (and (c-syntactic-re-search-forward "{" nil t) + (progn + (backward-char) + (or + ;; Ignore starts of special brace lists. + (and c-special-brace-lists + (save-restriction + (widen) + (c-looking-at-special-brace-list))) + ;; Ignore complete blocks. + (c-safe (c-forward-sexp) t)))) + (forward-char)) + + (looking-at "{")) + + (let (containing-sexp) + (goto-char arglist-start) + ;; `c-syntactic-eol' always matches somewhere on the line. + (re-search-forward c-syntactic-eol) + (goto-char (match-beginning 0)) + (c-forward-syntactic-ws) + (setq containing-sexp (c-most-enclosing-brace (c-parse-state))) + (c-looking-at-inexpr-block + (c-safe-position (or containing-sexp (point)) c-state-cache) + containing-sexp)))) + +(defun c-lineup-arglist (langelem) + "Line up the current argument line under the first argument. + +As a special case, if the indented line is inside a brace block +construct, the indentation is `c-basic-offset' only. This is intended +as a \"DWIM\" measure in cases like macros that contains statement +blocks, e.g: + +A_VERY_LONG_MACRO_NAME ({ + some (code, with + long, lines * in[it]); + }); +<--> c-basic-offset + +This is motivated partly because it's more in line with how code +blocks are handled, and partly since it approximates the behavior of +earlier CC Mode versions, which due to inaccurate analysis tended to +indent such cases this way. + +Works with: arglist-cont-nonempty, arglist-close." + (save-excursion + (let ((indent-pos (point))) + + (if (c-block-in-arglist-dwim (c-langelem-2nd-pos c-syntactic-element)) + c-basic-offset ; DWIM case. + + ;; Normal case. Indent to the token after the arglist open paren. + (goto-char (c-langelem-2nd-pos c-syntactic-element)) + (if (and c-special-brace-lists + (c-looking-at-special-brace-list)) + ;; Skip a special brace list opener like "({". + (progn (c-forward-token-2) + (forward-char)) + (forward-char)) + (let ((arglist-content-start (point))) + (c-forward-syntactic-ws) + (when (< (point) indent-pos) + (goto-char arglist-content-start) + (skip-chars-forward " \t")) + (vector (current-column))))))) + +;; Contributed by Kevin Ryde . +(defun c-lineup-argcont (elem) + "Line up a continued argument. + +foo (xyz, aaa + bbb + ccc + + ddd + eee + fff); <- c-lineup-argcont + +Only continuation lines like this are touched, nil is returned on lines +which are the start of an argument. + +Within a gcc asm block, \":\" is recognized as an argument separator, +but of course only between operand specifications, not in the expressions +for the operands. + +Works with: arglist-cont, arglist-cont-nonempty." + + (save-excursion + (beginning-of-line) + + (when (eq (car elem) 'arglist-cont-nonempty) + ;; Our argument list might not be the innermost one. If it + ;; isn't, go back to the last position in it. We do this by + ;; stepping back over open parens until we get to the open paren + ;; of our argument list. + (let ((open-paren (c-langelem-2nd-pos c-syntactic-element)) + (paren-state (c-parse-state))) + (while (not (eq (car paren-state) open-paren)) + (unless (consp (car paren-state)) ;; ignore matched braces + (goto-char (car paren-state))) + (setq paren-state (cdr paren-state))))) + + (let ((start (point)) c) + + (when (bolp) + ;; Previous line ending in a comma means we're the start of an + ;; argument. This should quickly catch most cases not for us. + ;; This case is only applicable if we're the innermost arglist. + (c-backward-syntactic-ws) + (setq c (char-before))) + + (unless (eq c ?,) + ;; In a gcc asm, ":" on the previous line means the start of an + ;; argument. And lines starting with ":" are not for us, don't + ;; want them to indent to the preceding operand. + (let ((gcc-asm (save-excursion + (goto-char start) + (c-in-gcc-asm-p)))) + (unless (and gcc-asm + (or (eq c ?:) + (save-excursion + (goto-char start) + (looking-at "[ \t]*:")))) + + (c-lineup-argcont-scan (if gcc-asm ?:)) + (vector (current-column)))))))) + +(defun c-lineup-argcont-scan (&optional other-match) + ;; Find the start of an argument, for `c-lineup-argcont'. + (when (zerop (c-backward-token-2 1 t)) + (let ((c (char-after))) + (if (or (eq c ?,) (eq c other-match)) + (progn + (forward-char) + (c-forward-syntactic-ws)) + (c-lineup-argcont-scan other-match))))) + +(defun c-lineup-arglist-intro-after-paren (langelem) + "Line up a line to just after the open paren of the surrounding paren +or brace block. + +Works with: defun-block-intro, brace-list-intro, +statement-block-intro, statement-case-intro, arglist-intro." + (save-excursion + (beginning-of-line) + (backward-up-list 1) + (skip-chars-forward " \t" (c-point 'eol)) + (vector (1+ (current-column))))) + +(defun c-lineup-arglist-close-under-paren (langelem) + "Line up a line under the enclosing open paren. +Normally used to line up a closing paren in the same column as its +corresponding open paren, but can also be used with arglist-cont and +arglist-cont-nonempty to line up all lines inside a parenthesis under +the open paren. + +As a special case, if a brace block construct starts at the same line +as the open parenthesis of the argument list, the indentation is +`c-basic-offset' only. See `c-lineup-arglist' for further discussion +of this \"DWIM\" measure. + +Works with: Almost all symbols, but are typically most useful on +arglist-close, brace-list-close, arglist-cont and arglist-cont-nonempty." + (save-excursion + (if (memq (c-langelem-sym langelem) + '(arglist-cont-nonempty arglist-close)) + (goto-char (c-langelem-2nd-pos c-syntactic-element)) + (beginning-of-line) + (c-go-up-list-backward)) + + (if (save-excursion (c-block-in-arglist-dwim (point))) + c-basic-offset ; DWIM case. + + ;; Normal case. Indent to the arglist open paren. + (let (special-list) + (if (and c-special-brace-lists + (setq special-list (c-looking-at-special-brace-list))) + ;; Cope if we're in the middle of a special brace list + ;; opener like "({". + (goto-char (car (car special-list)))) + (vector (current-column)))))) + +(defun c-lineup-arglist-operators (langelem) + "Line up lines starting with an infix operator under the open paren. +Return nil on lines that don't start with an operator, to leave those +cases to other line-up functions. Example: + +if ( x < 10 + || at_limit (x, <- c-lineup-arglist-operators + list) <- c-lineup-arglist-operators returns nil + ) + +Since this function doesn't do anything for lines without an infix +operator you typically want to use it together with some other line-up +settings, e.g. as follows \(the arglist-close setting is just a +suggestion to get a consistent style): + +\(c-set-offset 'arglist-cont '(c-lineup-arglist-operators 0)) +\(c-set-offset 'arglist-cont-nonempty '(c-lineup-arglist-operators + c-lineup-arglist)) +\(c-set-offset 'arglist-close '(c-lineup-arglist-close-under-paren)) + +Works with: arglist-cont, arglist-cont-nonempty." + (save-excursion + (back-to-indentation) + (when (looking-at "[-+|&*%<>=]\\|\\(/[^/*]\\)") + ;; '-' can be both an infix and a prefix operator, but I'm lazy now.. + (c-lineup-arglist-close-under-paren langelem)))) + +(defun c-lineup-close-paren (langelem) + "Line up the closing paren under its corresponding open paren if the +open paren is followed by code. If the open paren ends its line, no +indentation is added. E.g: + +main (int, main ( + char ** int, char ** + ) <-> ) <- c-lineup-close-paren + +As a special case, if a brace block construct starts at the same line +as the open parenthesis of the argument list, the indentation is +`c-basic-offset' instead of the open paren column. See +`c-lineup-arglist' for further discussion of this \"DWIM\" measure. + +Works with: All *-close symbols." + (save-excursion + (if (memq (c-langelem-sym langelem) + '(arglist-cont-nonempty arglist-close)) + (goto-char (c-langelem-2nd-pos c-syntactic-element)) + (beginning-of-line) + (c-go-up-list-backward)) + + (let (special-list arglist-start) + (if (and c-special-brace-lists + (setq special-list (c-looking-at-special-brace-list))) + ;; Cope if we're in the middle of a special brace list + ;; opener like "({". + (progn + (goto-char (setq arglist-start (car (car special-list)))) + (c-forward-token-2) + (forward-char)) + (setq arglist-start (point)) + (forward-char)) + + (cond ((looking-at c-syntactic-eol) + 0) ; The arglist is "empty". + + ((c-block-in-arglist-dwim (point)) + c-basic-offset) ; DWIM case. + + (t + ;; Normal case. Indent to the arglist open paren. + (goto-char arglist-start) + (vector (current-column))))))) + +(defun c-lineup-streamop (langelem) + "Line up C++ stream operators under each other. + +Works with: stream-op." + (save-excursion + (goto-char (c-langelem-pos langelem)) + (re-search-forward "<<\\|>>" (c-point 'eol) 'move) + (goto-char (match-beginning 0)) + (vector (current-column)))) + +(defun c-lineup-multi-inher (langelem) + "Line up the classes in C++ multiple inheritance clauses and member +initializers under each other. E.g: + +class Foo: Foo::Foo (int a, int b): + public Cyphr, Cyphr (a), + public Bar <-> Bar (b) <- c-lineup-multi-inher + +class Foo Foo::Foo (int a, int b) + : public Cyphr, : Cyphr (a), + public Bar <-> Bar (b) <- c-lineup-multi-inher + +class Foo Foo::Foo (int a, int b) + : public Cyphr : Cyphr (a) + , public Bar <-> , Bar (b) <- c-lineup-multi-inher + +Works with: inher-cont, member-init-cont." + (save-excursion + (back-to-indentation) + (let* ((eol (c-point 'eol)) + (here (point)) + (char-after-ip (char-after))) + (if (c-langelem-pos langelem) + (goto-char (c-langelem-pos langelem))) + + ;; This kludge is necessary to support both inher-cont and + ;; member-init-cont, since they have different anchor positions. + (c-backward-syntactic-ws) + (when (eq (char-before) ?:) + (backward-char) + (c-backward-syntactic-ws)) + + (c-syntactic-re-search-forward ":" eol 'move) + (if (looking-at c-syntactic-eol) + (c-forward-syntactic-ws here) + (if (eq char-after-ip ?,) + (backward-char) + (skip-chars-forward " \t" eol))) + (if (< (point) here) + (vector (current-column))) + ))) + +(defun c-lineup-java-inher (langelem) + "Line up Java implements and extends declarations. +If class names follow on the same line as the implements/extends +keyword, they are lined up under each other. Otherwise, they are +indented by adding `c-basic-offset' to the column of the keyword. +E.g: + +class Foo class Foo + extends extends Cyphr, + Bar <-> Bar <- c-lineup-java-inher + <--> c-basic-offset + +Works with: inher-cont." + (save-excursion + (goto-char (c-langelem-pos langelem)) + (forward-word 1) + (if (looking-at "[ \t]*$") + c-basic-offset + (c-forward-syntactic-ws) + (vector (current-column))))) + +(defun c-lineup-java-throws (langelem) + "Line up Java throws declarations. +If exception names follow on the same line as the throws keyword, +they are lined up under each other. Otherwise, they are indented by +adding `c-basic-offset' to the column of the throws keyword. The +throws keyword itself is also indented by `c-basic-offset' from the +function declaration start if it doesn't hang. E.g: + +int foo() int foo() throws Cyphr, + throws <-> Bar, <- c-lineup-java-throws + Bar <-> Vlod <- c-lineup-java-throws +<--><--> c-basic-offset + +Works with: func-decl-cont." + (save-excursion + (let* ((lim (1- (c-point 'bol))) + (throws (catch 'done + (goto-char (c-langelem-pos langelem)) + (while (zerop (c-forward-token-2 1 t lim)) + (if (looking-at "throws\\>[^_]") + (throw 'done t)))))) + (if throws + (if (zerop (c-forward-token-2 1 nil (c-point 'eol))) + (vector (current-column)) + (back-to-indentation) + (vector (+ (current-column) c-basic-offset))) + c-basic-offset)))) + +(defun c-indent-one-line-block (langelem) + "Indent a one line block `c-basic-offset' extra. +E.g: + +if (n > 0) if (n > 0) + {m+=n; n=0;} <-> { <- c-indent-one-line-block +<--> c-basic-offset m+=n; n=0; + } + +The block may use any kind of parenthesis character. nil is returned +if the line doesn't start with a one line block, which makes the +function usable in list expressions. + +Work with: Almost all syntactic symbols, but most useful on *-open." + (save-excursion + (let ((eol (c-point 'eol))) + (back-to-indentation) + (if (and (eq (char-syntax (char-after)) ?\() + (c-safe (progn (c-forward-sexp) t)) + (<= (point) eol)) + c-basic-offset + nil)))) + +(defun c-indent-multi-line-block (langelem) + "Indent a multi line block `c-basic-offset' extra. +E.g: + +int *foo[] = { int *foo[] = { + NULL, NULL, + {17}, <-> { <- c-indent-multi-line-block + 17 + } + <--> c-basic-offset + +The block may use any kind of parenthesis character. nil is returned +if the line doesn't start with a multi line block, which makes the +function usable in list expressions. + +Work with: Almost all syntactic symbols, but most useful on *-open." + (save-excursion + (let ((eol (c-point 'eol))) + (back-to-indentation) + (if (and (eq (char-syntax (char-after)) ?\() + (or (not (c-safe (progn (c-forward-sexp) t))) + (> (point) eol))) + c-basic-offset + nil)))) + +(defun c-lineup-C-comments (langelem) + "Line up C block comment continuation lines. +Various heuristics are used to handle many of the common comment +styles. Some examples: + +/* /** /* /* text /* /** + * text * text text text ** text ** text + */ */ */ */ */ */ + +/********************************************************************* + * text + ********************************************************************/ + +/********************************************************************* + Free form text comments: + In comments with a long delimiter line at the start, the indentation + is kept unchanged for lines that start with an empty comment line + prefix. The delimiter line is whatever matches the + `comment-start-skip' regexp. +*********************************************************************/ + +The variable `c-comment-prefix-regexp' is used to recognize the +comment line prefix, e.g. the `*' that usually starts every line +inside a comment. + +Works with: The `c' syntactic symbol." + (save-excursion + (let* ((here (point)) + (prefixlen (progn (back-to-indentation) + (if (looking-at c-current-comment-prefix) + (- (match-end 0) (point)) + 0))) + (starterlen + ;; Get the length of the comment starter, not including + ;; the first '/'. We check if the comment prefix matched + ;; on the current line matches the starter or if it + ;; matches comment-start-skip, and choose whichever is + ;; longest. + (max (save-excursion + (goto-char (1+ (c-langelem-pos langelem))) + (if (and (match-string 0) + (looking-at (regexp-quote (match-string 0)))) + (- (match-end 0) (match-beginning 0)) + 0)) + (save-excursion + (goto-char (c-langelem-pos langelem)) + (looking-at comment-start-skip) + (- (or (match-end 1) + (save-excursion + (goto-char (match-end 0)) + (skip-chars-backward " \t") + (point))) + (point) + 1))))) + (if (and (> starterlen 10) (zerop prefixlen)) + ;; The comment has a long starter and the line doesn't have + ;; a nonempty comment prefix. Treat it as free form text + ;; and don't change the indentation. + (vector (current-column)) + ;; Go back to the previous non-blank line, if any. + (while + (progn + (forward-line -1) + (back-to-indentation) + (and (> (point) (c-langelem-pos langelem)) + (looking-at "[ \t]*$")))) + ;; Is the starting line the first continuation line with content? + (if (>= (c-langelem-pos langelem) (point)) + (if (zerop prefixlen) + ;; No nonempty comment prefix. Align after comment + ;; starter. + (progn + (looking-at comment-start-skip) + (goto-char (match-end 0)) + ;; The following should not be necessary, since + ;; comment-start-skip should match everything (i.e. + ;; typically whitespace) that leads up to the text. + ;;(if (looking-at "\\([ \t]+\\).+$") + ;; ;; Align with the text that hangs after the + ;; ;; comment starter. + ;; (goto-char (match-end 1))) + (vector (current-column))) + ;; How long is the comment starter? if greater than the + ;; length of the comment prefix, align left. if less + ;; than or equal, align right. this should also pick up + ;; Javadoc style comments. + (if (> starterlen prefixlen) + (progn + (goto-char (c-langelem-pos langelem)) + (vector (1+ (current-column)))) + (goto-char (+ (c-langelem-pos langelem) starterlen 1)) + (vector (- (current-column) prefixlen)))) + ;; We didn't start on the first non-blank continuation line. If the + ;; previous line has a nonempty comment prefix, align with it. + ;; Otherwise, align with the previous nonempty line, but align the + ;; comment ender with the starter. + (when (or (not (looking-at c-current-comment-prefix)) + (eq (match-beginning 0) (match-end 0))) + (goto-char here) + (back-to-indentation) + (if (looking-at (concat "\\(" c-current-comment-prefix "\\)\\*/")) + (goto-char (c-langelem-pos langelem)) + (while (and (zerop (forward-line -1)) + (looking-at "^[ \t]*$"))) + (back-to-indentation) + (if (< (point) (c-langelem-pos langelem)) + ;; Align with the comment starter rather than + ;; with the code before it. + (goto-char (c-langelem-pos langelem))))) + (vector (current-column))))))) + +(defun c-lineup-comment (langelem) + "Line up a comment start according to `c-comment-only-line-offset'. +If the comment is lined up with a comment starter on the previous +line, that alignment is preserved. + +Works with: comment-intro." + (save-excursion + (back-to-indentation) + (let ((col (current-column))) + (cond + ;; CASE 1: preserve aligned comments + ((save-excursion + (and (c-backward-single-comment) + (= col (current-column)))) + (vector col)) ; Return an absolute column. + ;; indent as specified by c-comment-only-line-offset + ((not (bolp)) + (or (car-safe c-comment-only-line-offset) + c-comment-only-line-offset)) + (t + (or (cdr-safe c-comment-only-line-offset) + (car-safe c-comment-only-line-offset) + -1000)) ;jam it against the left side + )))) + +(defun c-lineup-knr-region-comment (langelem) + "Line up a comment in the \"K&R region\" with the declaration. +That is the region between the function or class header and the +beginning of the block. E.g: + +int main() +/* This is the main function. */ <- c-lineup-knr-region-comment +{ + return 0; +} + +Return nil if called in any other situation, to be useful in list +expressions. + +Works with: comment-intro." + (when (or (assq 'topmost-intro-cont c-syntactic-context) + (assq 'func-decl-cont c-syntactic-context) + (assq 'knr-argdecl-intro c-syntactic-context) + (assq 'lambda-intro-cont c-syntactic-context)) + (save-excursion + (beginning-of-line) + (c-beginning-of-statement-1) + (vector (current-column))))) + +(defun c-lineup-runin-statements (langelem) + "Line up statements when the first statement is on the same line as +the block opening brace. E.g: + +int main() +{ puts (\"Hello world!\"); + return 0; <- c-lineup-runin-statements +} + +If there is no statement after the opening brace to align with, nil is +returned. This makes the function usable in list expressions. + +Works with: The `statement' syntactic symbol." + (if (eq (char-after (c-langelem-pos langelem)) ?{) + (save-excursion + (if (c-langelem-pos langelem) + (goto-char (c-langelem-pos langelem))) + (forward-char 1) + (skip-chars-forward " \t") + (unless (eolp) + (vector (current-column)))))) + +(defun c-lineup-assignments (langelem) + "Line up the current line after the assignment operator on the first +line in the statement. If there isn't any, return nil to allow +stacking with other line-up functions. If the current line contains +an assignment operator too, try to align it with the first one. + +Works with: topmost-intro-cont, statement-cont, arglist-cont, +arglist-cont-nonempty." + (let (startpos endpos equalp) + + (if (eq (c-langelem-sym langelem) 'arglist-cont-nonempty) + ;; If it's an arglist-cont-nonempty then we're only interested + ;; in equal signs outside it. We don't search for a "=" on + ;; the current line since that'd have a different nesting + ;; compared to the one we should align with. + (save-excursion + (save-restriction + (setq endpos (c-langelem-2nd-pos c-syntactic-element)) + (narrow-to-region (c-langelem-pos langelem) endpos) + (if (setq startpos (c-up-list-backward endpos)) + (setq startpos (1+ startpos)) + (setq startpos (c-langelem-pos langelem))))) + + (setq startpos (c-langelem-pos langelem) + endpos (point)) + + ;; Find a syntactically relevant and unnested "=" token on the + ;; current line. equalp is in that case set to the number of + ;; columns to left shift the current line to align it with the + ;; goal column. + (save-excursion + (beginning-of-line) + (when (c-syntactic-re-search-forward + c-assignment-op-regexp + (c-point 'eol) t t t) + (setq equalp (- (or (match-beginning 1) + (match-end 0)) + (c-point 'boi)))))) + + (save-excursion + (goto-char startpos) + (if (or (if (c-syntactic-re-search-forward + c-assignment-op-regexp + (min endpos (c-point 'eol)) t t t) + (progn + (goto-char (or (match-beginning 1) + (match-end 0))) + nil) + t) + (save-excursion + (c-forward-syntactic-ws (c-point 'eol)) + (eolp))) + ;; There's no equal sign on the line, or there is one but + ;; nothing follows it. + nil + + ;; calculate indentation column after equals and ws, unless + ;; our line contains an equals sign + (if (not equalp) + (progn + (skip-chars-forward " \t") + (setq equalp 0))) + + (vector (- (current-column) equalp))) + ))) + +(defun c-lineup-math (langelem) + "Like `c-lineup-assignments' but indent with `c-basic-offset' if no +assignment operator was found on the first line. I.e. this function +is the same as specifying a list (c-lineup-assignments +). It's +provided for compatibility with old configurations. + +Works with: topmost-intro-cont, statement-cont, arglist-cont, +arglist-cont-nonempty." + (or (c-lineup-assignments langelem) + c-basic-offset)) + +(defun c-lineup-cascaded-calls (langelem) + "Line up \"cascaded calls\" under each other. +If the line begins with \"->\" or \".\" and the preceding line ends +with one or more function calls preceded by the same token, then the +arrow is lined up with the first of those tokens. E.g: + +result = proc->add(17)->add(18) + ->add(19) + <- c-lineup-cascaded-calls + offset; <- c-lineup-cascaded-calls (inactive) + +In any other situation nil is returned to allow use in list +expressions. + +Works with: topmost-intro-cont, statement-cont, arglist-cont, +arglist-cont-nonempty." + + (if (and (eq (c-langelem-sym langelem) 'arglist-cont-nonempty) + (not (eq (c-langelem-2nd-pos c-syntactic-element) + (c-most-enclosing-brace (c-parse-state))))) + ;; The innermost open paren is not our one, so don't do + ;; anything. This can occur for arglist-cont-nonempty with + ;; nested arglist starts on the same line. + nil + + (save-excursion + (back-to-indentation) + (let ((operator (and (looking-at "->\\|\\.") + (regexp-quote (match-string 0)))) + (stmt-start (c-langelem-pos langelem)) col) + + (when (and operator + (looking-at operator) + (zerop (c-backward-token-2 1 t stmt-start)) + (eq (char-after) ?\() + (zerop (c-backward-token-2 2 t stmt-start)) + (looking-at operator)) + (setq col (current-column)) + + (while (and (zerop (c-backward-token-2 1 t stmt-start)) + (eq (char-after) ?\() + (zerop (c-backward-token-2 2 t stmt-start)) + (looking-at operator)) + (setq col (current-column))) + + (vector col)))))) + +(defun c-lineup-string-cont (langelem) + "Line up a continued string under the one it continues. +A continued string in this sense is where a string literal follows +directly after another one. E.g: + +result = prefix + \"A message \" + \"string.\"; <- c-lineup-string-cont + +In other situations, returns nil, to allow stacking with other +line-up functions. + +Works with: topmost-intro-cont, statement-cont, arglist-cont, +arglist-cont-nonempty." + (save-excursion + (back-to-indentation) + (and (looking-at "\\s\"") + (let ((quote (char-after)) pos) + (while (and (progn (c-backward-syntactic-ws) + (eq (char-before) quote)) + (c-safe (c-backward-sexp) t) + (/= (setq pos (point)) (c-point 'boi)))) + (when pos + (goto-char pos) + (vector (current-column))))))) + +(defun c-lineup-template-args (langelem) + "Line up template argument lines under the first argument. +To allow this function to be used in a list expression, nil is +returned if there's no template argument on the first line. + +Works with: template-args-cont." + (save-excursion + (c-with-syntax-table c++-template-syntax-table + (beginning-of-line) + (backward-up-list 1) + (if (and (eq (char-after) ?<) + (zerop (c-forward-token-2 1 nil (c-point 'eol)))) + (vector (current-column)))))) + +(defun c-lineup-ObjC-method-call (langelem) + "Line up selector args as Emacs Lisp mode does with function args: +Go to the position right after the message receiver, and if you are at +the end of the line, indent the current line c-basic-offset columns +from the opening bracket; otherwise you are looking at the first +character of the first method call argument, so line up the current +line with it. + +Works with: objc-method-call-cont." + (save-excursion + (let* ((extra (save-excursion + (back-to-indentation) + (c-backward-syntactic-ws (c-langelem-pos langelem)) + (if (eq (char-before) ?:) + (- c-basic-offset) + 0))) + (open-bracket-pos (c-langelem-pos langelem)) + (open-bracket-col (progn + (goto-char open-bracket-pos) + (current-column))) + (target-col (progn + (forward-char) + (c-forward-sexp) + (skip-chars-forward " \t") + (if (eolp) + (+ open-bracket-col c-basic-offset) + (current-column)))) + ) + (- target-col open-bracket-col extra)))) + +(defun c-lineup-ObjC-method-call-colons (langelem) + "Line up selector args as Project Builder / XCode: colons of first + selector portions on successive lines are aligned. If no decision can + be made return NIL, so that other lineup methods can be tried. This is + typically chained with `c-lineup-ObjC-method-call'. + +Works with: objc-method-call-cont." + (save-excursion + (catch 'no-idea + (let* ((method-arg-len (progn + (back-to-indentation) + (if (search-forward ":" (c-point 'eol) 'move) + (- (point) (c-point 'boi)) + ; no complete argument to indent yet + (throw 'no-idea nil)))) + + (extra (save-excursion + ; indent parameter to argument if needed + (back-to-indentation) + (c-backward-syntactic-ws (c-langelem-pos langelem)) + (if (eq ?: (char-before)) + c-objc-method-parameter-offset 0))) + + (open-bracket-col (c-langelem-col langelem)) + + (arg-ralign-colon-ofs (progn + (forward-char) ; skip over '[' + ; skip over object/class name + ; and first argument + (c-forward-sexp 2) + (if (search-forward ":" (c-point 'eol) 'move) + (- (current-column) open-bracket-col + method-arg-len extra) + ; previous arg has no param + c-objc-method-arg-unfinished-offset)))) + + (if (>= arg-ralign-colon-ofs c-objc-method-arg-min-delta-to-bracket) + (+ arg-ralign-colon-ofs extra) + (throw 'no-idea nil)))))) + +(defun c-lineup-ObjC-method-args (langelem) + "Line up the colons that separate args in a method declaration. +The colon on the current line is aligned with the one on the first +line. + +Works with: objc-method-args-cont." + (save-excursion + (let* ((here (c-point 'boi)) + (curcol (progn (goto-char here) (current-column))) + (eol (c-point 'eol)) + (relpos (c-langelem-pos langelem)) + (first-col-column (progn + (goto-char relpos) + (skip-chars-forward "^:" eol) + (and (eq (char-after) ?:) + (current-column))))) + (if (not first-col-column) + c-basic-offset + (goto-char here) + (skip-chars-forward "^:" eol) + (if (eq (char-after) ?:) + (+ curcol (- first-col-column (current-column))) + c-basic-offset))))) + +(defun c-lineup-ObjC-method-args-2 (langelem) + "Line up the colons that separate args in a method declaration. +The colon on the current line is aligned with the one on the previous +line. + +Works with: objc-method-args-cont." + (save-excursion + (let* ((here (c-point 'boi)) + (curcol (progn (goto-char here) (current-column))) + (eol (c-point 'eol)) + (relpos (c-langelem-pos langelem)) + (prev-col-column (progn + (skip-chars-backward "^:" relpos) + (and (eq (char-before) ?:) + (- (current-column) 1))))) + (if (not prev-col-column) + c-basic-offset + (goto-char here) + (skip-chars-forward "^:" eol) + (if (eq (char-after) ?:) + (+ curcol (- prev-col-column (current-column))) + c-basic-offset))))) + +(defun c-lineup-inexpr-block (langelem) + "Line up the block for constructs that use a block inside an expression, +e.g. anonymous classes in Java and lambda functions in Pike. The body +is aligned with the start of the header, e.g. with the \"new\" or +\"lambda\" keyword. Returns nil if the block isn't part of such a +construct. + +Works with: inlambda, inexpr-statement, inexpr-class." + (save-excursion + (back-to-indentation) + (let* ((paren-state (c-parse-state)) + (containing-sexp (c-most-enclosing-brace paren-state)) + (res (or (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + containing-sexp) + (and containing-sexp + (progn (goto-char containing-sexp) + (eq (char-after) ?{)) + (progn (setq containing-sexp + (c-most-enclosing-brace paren-state + (point))) + (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + containing-sexp)))))) + (when res + (goto-char (cdr res)) + (vector (current-column)))))) + +(defun c-lineup-whitesmith-in-block (langelem) + "Line up lines inside a block in Whitesmith style. +It's done in a way that works both when the opening brace hangs and +when it doesn't. E.g: + +something + { something { + foo; <-> foo; <- c-lineup-whitesmith-in-block + } } + <--> c-basic-offset + +In the first case the indentation is kept unchanged, in the +second `c-basic-offset' is added. + +Works with: defun-close, defun-block-intro, inline-close, block-close, +brace-list-close, brace-list-intro, statement-block-intro, +arglist-intro, arglist-cont-nonempty, arglist-close, and all in* +symbols, e.g. inclass and inextern-lang." + (save-excursion + (if (and (c-go-up-list-backward) + (= (point) (c-point 'boi))) + nil + c-basic-offset))) + +(defun c-lineup-after-whitesmith-blocks (langelem) + "Compensate for Whitesmith style indentation of blocks. +Due to the way CC Mode calculates anchor positions for normal lines +inside blocks, this function is necessary for those lines to get +correct Whitesmith style indentation. Consider the following +examples: + + int foo() + { +int foo() { + { a; + a; } + x; <-> x; <- c-lineup-after-whitesmith-blocks + +The fact that the line with \"x\" is preceded by a Whitesmith style +indented block in one case and not the other should not affect its +indentation. But since CC Mode in cases like this uses the +indentation of the preceding statement as anchor position, the \"x\" +would in the rightmost case be indented too much if the offset for +`statement' was set simply to zero. + +This lineup function corrects for this situation by detecting if the +anchor position is at an open paren character. In that case, it +instead indents relative to the surrounding block just like +`c-lineup-whitesmith-in-block'. + +Works with: brace-list-entry, brace-entry-open, statement, +arglist-cont." + (save-excursion + (goto-char (c-langelem-pos langelem)) + (when (looking-at "\\s\(") + (if (c-go-up-list-backward) + (let ((pos (point))) + (back-to-indentation) + (if (= pos (point)) + (vector (current-column)) + (vector (+ (current-column) c-basic-offset)))) + (vector 0))))) + +(defun c-lineup-cpp-define (langelem) + "Line up macro continuation lines according to the indentation of +the construct preceding the macro. E.g: + +v beg of preceding constr v beg of preceding constr + int dribble() { +const char msg[] = if (!running) + \"Some text.\"; error(\"Not running!\"); + +#define X(A, B) \ #define X(A, B) \ +do { \ <-> do { \ <- c-lineup-cpp-define + printf (A, B); \ printf (A, B); \ +} while (0) } while (0) + +If `c-syntactic-indentation-in-macros' is non-nil, the function +returns the relative indentation to the macro start line to allow +accumulation with other offsets. E.g. in the following cases, +cpp-define-intro is combined with the statement-block-intro that comes +from the \"do {\" that hangs on the \"#define\" line: + + int dribble() { +const char msg[] = if (!running) + \"Some text.\"; error(\"Not running!\"); + +#define X(A, B) do { \ #define X(A, B) do { \ + printf (A, B); \ <-> printf (A, B); \ <- c-lineup-cpp-define + this->refs++; \ this->refs++; \ +} while (0) <-> } while (0) <- c-lineup-cpp-define + +The relative indentation returned by `c-lineup-cpp-define' is zero and +two, respectively, in these two examples. They are then added to the +two column indentation that statement-block-intro gives in both cases +here. + +If the relative indentation is zero, then nil is returned instead. +That is useful in a list expression to specify the default indentation +on the top level. + +If `c-syntactic-indentation-in-macros' is nil then this function keeps +the current indentation, except for empty lines \(ignoring the ending +backslash) where it takes the indentation from the closest preceding +nonempty line in the macro. If there's no such line in the macro then +the indentation is taken from the construct preceding it, as described +above. + +Works with: cpp-define-intro." + (let (offset) + (if c-syntactic-indentation-in-macros + ;; Go to the macro start and do a syntactic analysis of it. + ;; Then remove the cpp-macro element it should contain and + ;; calculate the indentation it then would get. + (save-excursion + (c-beginning-of-macro) + (setq offset (- (c-get-syntactic-indentation + (delete '(cpp-macro) (c-guess-basic-syntax))) + (save-excursion + (back-to-indentation) + (current-column)))) + (if (zerop offset) + nil + offset)) + ;; Do not indent syntactically inside the macro. + (save-excursion + (let ((macro-start-line (save-excursion + (goto-char (c-query-macro-start)) + (beginning-of-line) + (point)))) + (beginning-of-line) + ;; Check every line while inside the macro. + (while (and (> (point) macro-start-line) + (looking-at "[ \t]*\\\\?$") + (= (forward-line -1) 0))) + (if (<= (point) macro-start-line) + ;; If we've stepped out of the macro we take the + ;; syntactic offset. + (setq offset (c-get-syntactic-indentation + (delete '(cpp-macro) (c-guess-basic-syntax)))) + (setq offset (current-indentation))) + (if (zerop offset) + nil + (vector offset))))))) + +;; Contributed by Kevin Ryde . +(defun c-lineup-gcc-asm-reg (elem) + "Line up a gcc asm register under one on a previous line. + + asm (\"foo %1, %0\\n\" + \"bar %0, %1\" + : \"=r\" (w), + \"=r\" (x) + : \"0\" (y), + \"1\" (z)); + +The \"x\" line is aligned to the text after the \":\" on the \"w\" line, and +similarly \"z\" under \"y\". + +This is done only in an \"asm\" or \"__asm__\" block, and only to +those lines mentioned. Anywhere else nil is returned. The usual +arrangement is to have this routine as an extra feature at the start +of arglist line-ups, e.g. + + (c-lineup-gcc-asm-reg c-lineup-arglist) + +Works with: arglist-cont, arglist-cont-nonempty." + + (let ((orig-pos (point)) + alignto) + (save-excursion + (and + c-opt-asm-stmt-key + + ;; Don't do anything if the innermost open paren isn't our one. + ;; This can occur for arglist-cont-nonempty with nested arglist + ;; starts on the same line. + (or (not (eq (car elem) 'arglist-cont-nonempty)) + (eq (c-langelem-2nd-pos c-syntactic-element) + (c-most-enclosing-brace (c-parse-state)))) + + ;; Find the ":" to align to. Look for this first so as to quickly + ;; eliminate pretty much all cases which are not for us. + (re-search-backward "^[ \t]*:[ \t]*\\(.\\)?" (cdr elem) t) + + ;; Must have something after the ":". + (setq alignto (match-beginning 1)) + + ;; Don't touch ":" lines themselves. + (progn (goto-char orig-pos) + (beginning-of-line) + (not (looking-at "^[ \t]*:"))) + + ;; Only operate in an asm statement. + (progn (goto-char orig-pos) + (c-in-gcc-asm-p)) + + (vector (progn (goto-char alignto) (current-column))))))) + +(defun c-lineup-dont-change (langelem) + "Do not change the indentation of the current line. + +Works with: Any syntactic symbol." + (save-excursion + (back-to-indentation) + (vector (current-column)))) + +(defun c-lineup-respect-col-0 (langelem) + "If the current line starts at column 0, return [0]. Otherwise return nil. + +This can be used for comments (in conjunction with, say, +`c-lineup-comment'), to keep comments already at column 0 +anchored there, but reindent other comments." + (save-excursion + (back-to-indentation) + (if (eq (current-column) 0) + [0] + nil))) + + +(defun c-snug-do-while (syntax pos) + "Dynamically calculate brace hanginess for do-while statements. +Using this function, `while' clauses that end a `do-while' block will +remain on the same line as the brace that closes that block. + +See `c-hanging-braces-alist' for how to utilize this function as an +ACTION associated with `block-close' syntax." + (save-excursion + (let (langelem) + (if (and (eq syntax 'block-close) + (setq langelem (assq 'block-close c-syntactic-context)) + (progn (goto-char (c-langelem-pos langelem)) + (if (eq (char-after) ?{) + (c-safe (c-forward-sexp -1))) + (looking-at "\\[^_]"))) + '(before) + '(before after))))) + +(defun c-snug-1line-defun-close (syntax pos) + "Determine the brace hanginess for an AWK defun-close. +If the action/function being closed is a one-liner, keep it so. Otherwise put +the closing brace on its own line." + (save-excursion + (goto-char pos) + (if (> (c-point 'bol) + (progn (up-list -1) (point))) + '(before after) + '(after)))) + +(defun c-gnu-impose-minimum () + "Imposes a minimum indentation for lines inside code blocks. +The variable `c-label-minimum-indentation' specifies the minimum +indentation amount." + + (when (and (not + ;; Don't adjust macro or comment-only lines. + (or (assq 'cpp-macro c-syntactic-context) + (assq 'comment-intro c-syntactic-context))) + (c-intersect-lists c-inside-block-syms c-syntactic-context) + (save-excursion + (back-to-indentation) + (< (current-column) c-label-minimum-indentation))) + (c-shift-line-indentation (- c-label-minimum-indentation + (current-indentation))))) + + +;; Useful for c-hanging-semi&comma-criteria + +(defun c-semi&comma-inside-parenlist () + "Controls newline insertion after semicolons in parenthesis lists. +If a comma was inserted, no determination is made. If a semicolon was +inserted inside a parenthesis list, no newline is added otherwise a +newline is added. In either case, checking is stopped. This supports +exactly the old newline insertion behavior." + ;; newline only after semicolon, but only if that semicolon is not + ;; inside a parenthesis list (e.g. a for loop statement) + (if (not (eq last-command-event ?\;)) + nil ; continue checking + (if (condition-case nil + (save-excursion + (up-list -1) + (not (eq (char-after) ?\())) + (error t)) + t + 'stop))) + +;; Suppresses newlines before non-blank lines +(defun c-semi&comma-no-newlines-before-nonblanks () + "Controls newline insertion after semicolons. +If a comma was inserted, no determination is made. If a semicolon was +inserted, and the following line is not blank, no newline is inserted. +Otherwise, no determination is made." + (save-excursion + (if (and (= last-command-event ?\;) + ;;(/= (point-max) + ;; (save-excursion (skip-syntax-forward " ") (point)) + (zerop (forward-line 1)) + (bolp) ; forward-line has funny behavior at eob. + (not (looking-at "^[ \t]*$"))) + 'stop + nil))) + +;; Suppresses new lines after semicolons in one-liners methods +(defun c-semi&comma-no-newlines-for-oneline-inliners () + "Controls newline insertion after semicolons for some one-line methods. +If a comma was inserted, no determination is made. Newlines are +suppressed in one-liners, if the line is an in-class inline function. +For other semicolon contexts, no determination is made." + (let ((syntax (c-guess-basic-syntax)) + (bol (save-excursion + (if (c-safe (up-list -1) t) + (c-point 'bol) + -1)))) + (if (and (eq last-command-event ?\;) + (eq (car (car syntax)) 'inclass) + (eq (car (car (cdr syntax))) 'topmost-intro) + (= (c-point 'bol) bol)) + 'stop + nil))) + + +(cc-provide 'cc-align) + +;;; arch-tag: 4d71ed28-bf51-4509-a148-f39669669a2e +;;; cc-align.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-awk.el b/site-lisp/cc-mode/5.32.3/cc-awk.el new file mode 100644 index 0000000..a416dea --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-awk.el @@ -0,0 +1,1100 @@ +;;; cc-awk.el --- AWK specific code within cc-mode. + +;; Copyright (C) 1988, 1994, 1996, 2000, 2001, 2002, 2003, 2004, 2005, +;; 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Author: Alan Mackenzie (originally based on awk-mode.el) +;; Maintainer: FSF +;; Keywords: AWK, cc-mode, unix, languages + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; This file contains (most of) the adaptations to cc-mode required for the +;; integration of AWK Mode. +;; It is organised thusly, the sections being separated by page breaks: +;; 1. The AWK Mode syntax table. +;; 2. Regular expressions for analysing AWK code. +;; 3. Indentation calculation stuff ("c-awk-NL-prop text-property"). +;; 4. Syntax-table property/font-locking stuff, including the +;; font-lock-keywords setting. +;; 5. The AWK Mode before/after-change-functions. +;; 6. AWK Mode specific versions of commands like beginning-of-defun. +;; The AWK Mode keymap, abbreviation table, and the mode function itself are +;; in cc-mode.el. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) + +;; Silence the byte compiler. +(cc-bytecomp-defvar font-lock-mode) ; Checked with boundp before use. +(cc-bytecomp-defvar c-new-BEG) +(cc-bytecomp-defvar c-new-END) + +;; Some functions in cc-engine that are used below. There's a cyclic +;; dependency so it can't be required here. (Perhaps some functions +;; could be moved to cc-engine to avoid it.) +(cc-bytecomp-defun c-backward-token-1) +(cc-bytecomp-defun c-beginning-of-statement-1) +(cc-bytecomp-defun c-backward-sws) + +(defvar awk-mode-syntax-table + (let ((st (make-syntax-table))) + (modify-syntax-entry ?\\ "\\" st) + (modify-syntax-entry ?\n "> " st) + (modify-syntax-entry ?\r "> " st) + (modify-syntax-entry ?\f "> " st) + (modify-syntax-entry ?\# "< " st) + ;; / can delimit regexes or be a division operator. By default we assume + ;; that it is a division sign, and fix the regexp operator cases with + ;; `font-lock-syntactic-keywords'. + (modify-syntax-entry ?/ "." st) ; ACM 2002/4/27. + (modify-syntax-entry ?* "." st) + (modify-syntax-entry ?+ "." st) + (modify-syntax-entry ?- "." st) + (modify-syntax-entry ?= "." st) + (modify-syntax-entry ?% "." st) + (modify-syntax-entry ?< "." st) + (modify-syntax-entry ?> "." st) + (modify-syntax-entry ?& "." st) + (modify-syntax-entry ?| "." st) + (modify-syntax-entry ?_ "_" st) + (modify-syntax-entry ?\' "." st) + st) + "Syntax table in use in AWK Mode buffers.") + + +;; This section defines regular expressions used in the analysis of AWK code. + +;; N.B. In the following regexps, an EOL is either \n OR \r. This is because +;; Emacs has in the past used \r to mark hidden lines in some fashion (and +;; maybe still does). + +(defconst c-awk-esc-pair-re "\\\\\\(.\\|\n\\|\r\\|\\'\\)") +;; Matches any escaped (with \) character-pair, including an escaped newline. +(defconst c-awk-non-eol-esc-pair-re "\\\\\\(.\\|\\'\\)") +;; Matches any escaped (with \) character-pair, apart from an escaped newline. +(defconst c-awk-comment-without-nl "#.*") +;; Matches an AWK comment, not including the terminating NL (if any). Note +;; that the "enclosing" (elisp) regexp must ensure the # is real. +(defconst c-awk-nl-or-eob "\\(\n\\|\r\\|\\'\\)") +;; Matches a newline, or the end of buffer. + +;; "Space" regular expressions. +(eval-and-compile + (defconst c-awk-escaped-nl "\\\\[\n\r]")) +;; Matches an escaped newline. +(eval-and-compile + (defconst c-awk-escaped-nls* (concat "\\(" c-awk-escaped-nl "\\)*"))) +;; Matches a possibly empty sequence of escaped newlines. Used in +;; awk-font-lock-keywords. +;; (defconst c-awk-escaped-nls*-with-space* +;; (concat "\\(" c-awk-escaped-nls* "\\|" "[ \t]+" "\\)*")) +;; The above RE was very slow. It's runtime was doubling with each additional +;; space :-( Reformulate it as below: +(eval-and-compile + (defconst c-awk-escaped-nls*-with-space* + (concat "\\(" c-awk-escaped-nl "\\|" "[ \t]" "\\)*"))) +;; Matches a possibly empty sequence of escaped newlines with optional +;; interspersed spaces and tabs. Used in awk-font-lock-keywords. +(defconst c-awk-blank-or-comment-line-re + (concat "[ \t]*\\(#\\|\\\\?$\\)")) +;; Matche (the tail of) a line containing at most either a comment or an +;; escaped EOL. + +;; REGEXPS FOR "HARMLESS" STRINGS/LINES. +(defconst c-awk-harmless-char-re "[^_#/\"\\\\\n\r]") +;; Matches any character but a _, #, /, ", \, or newline. N.B. _" starts a +;; localisation string in gawk 3.1 +(defconst c-awk-harmless-_ "_\\([^\"]\\|\\'\\)") +;; Matches an underline NOT followed by ". +(defconst c-awk-harmless-string*-re + (concat "\\(" c-awk-harmless-char-re "\\|" c-awk-esc-pair-re "\\|" c-awk-harmless-_ "\\)*")) +;; Matches a (possibly empty) sequence of chars without unescaped /, ", \, +;; #, or newlines. +(defconst c-awk-harmless-string*-here-re + (concat "\\=" c-awk-harmless-string*-re)) +;; Matches the (possibly empty) sequence of chars without unescaped /, ", \, +;; at point. +(defconst c-awk-harmless-line-re + (concat c-awk-harmless-string*-re + "\\(" c-awk-comment-without-nl "\\)?" c-awk-nl-or-eob)) +;; Matches (the tail of) an AWK \"logical\" line not containing an unescaped +;; " or /. "logical" means "possibly containing escaped newlines". A comment +;; is matched as part of the line even if it contains a " or a /. The End of +;; buffer is also an end of line. +(defconst c-awk-harmless-lines+-here-re + (concat "\\=\\(" c-awk-harmless-line-re "\\)+")) +;; Matches a sequence of (at least one) \"harmless-line\" at point. + + +;; REGEXPS FOR AWK STRINGS. +(defconst c-awk-string-ch-re "[^\"\\\n\r]") +;; Matches any character which can appear unescaped in a string. +(defconst c-awk-string-innards-re + (concat "\\(" c-awk-string-ch-re "\\|" c-awk-esc-pair-re "\\)*")) +;; Matches the inside of an AWK string (i.e. without the enclosing quotes). +(defconst c-awk-string-without-end-here-re + (concat "\\=_?\"" c-awk-string-innards-re)) +;; Matches an AWK string at point up to, but not including, any terminator. +;; A gawk 3.1+ string may look like _"localisable string". +(defconst c-awk-one-line-possibly-open-string-re + (concat "\"\\(" c-awk-string-ch-re "\\|" c-awk-non-eol-esc-pair-re "\\)*" + "\\(\"\\|\\\\?$\\|\\'\\)")) + +;; REGEXPS FOR AWK REGEXPS. +(defconst c-awk-regexp-normal-re "[^[/\\\n\r]") +;; Matches any AWK regexp character which doesn't require special analysis. +(defconst c-awk-escaped-newlines*-re "\\(\\\\[\n\r]\\)*") +;; Matches a (possibly empty) sequence of escaped newlines. + +;; NOTE: In what follows, "[asdf]" in a regexp will be called a "character +;; list", and "[:alpha:]" inside a character list will be known as a +;; "character class". These terms for these things vary between regexp +;; descriptions . +(defconst c-awk-regexp-char-class-re + "\\[:[a-z]+:\\]") + ;; Matches a character class spec (e.g. [:alpha:]). +(defconst c-awk-regexp-char-list-re + (concat "\\[" c-awk-escaped-newlines*-re "^?" c-awk-escaped-newlines*-re "]?" + "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-class-re + "\\|" "[^]\n\r]" "\\)*" "\\(]\\|$\\)")) +;; Matches a regexp char list, up to (but not including) EOL if the ] is +;; missing. +(defconst c-awk-regexp-one-line-possibly-open-char-list-re + (concat "\\[\\]?\\(" c-awk-non-eol-esc-pair-re "\\|" "[^]\n\r]" "\\)*" + "\\(]\\|\\\\?$\\|\\'\\)")) +;; Matches the head (or all) of a regexp char class, up to (but not +;; including) the first EOL. +(defconst c-awk-regexp-innards-re + (concat "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-list-re + "\\|" c-awk-regexp-normal-re "\\)*")) +;; Matches the inside of an AWK regexp (i.e. without the enclosing /s) +(defconst c-awk-regexp-without-end-re + (concat "/" c-awk-regexp-innards-re)) +;; Matches an AWK regexp up to, but not including, any terminating /. +(defconst c-awk-one-line-possibly-open-regexp-re + (concat "/\\(" c-awk-non-eol-esc-pair-re + "\\|" c-awk-regexp-one-line-possibly-open-char-list-re + "\\|" c-awk-regexp-normal-re "\\)*" + "\\(/\\|\\\\?$\\|\\'\\)")) +;; Matches as much of the head of an AWK regexp which fits on one line, +;; possibly all of it. + +;; REGEXPS used for scanning an AWK buffer in order to decide IF A '/' IS A +;; REGEXP OPENER OR A DIVISION SIGN. By "state" in the following is meant +;; whether a '/' at the current position would by a regexp opener or a +;; division sign. +(defconst c-awk-neutral-re +; "\\([{}@` \t]\\|\\+\\+\\|--\\|\\\\.\\)+") ; changed, 2003/6/7 + "\\([{}@` \t]\\|\\+\\+\\|--\\|\\\\.\\)") +;; A "neutral" char(pair). Doesn't change the "state" of a subsequent /. +;; This is space/tab, braces, an auto-increment/decrement operator or an +;; escaped character. Or one of the (invalid) characters @ or `. But NOT an +;; end of line (even if escaped). +(defconst c-awk-neutrals*-re + (concat "\\(" c-awk-neutral-re "\\)*")) +;; A (possibly empty) string of neutral characters (or character pairs). +(defconst c-awk-var-num-ket-re "[]\)0-9a-zA-Z_$.\x80-\xff]+") +;; Matches a char which is a constituent of a variable or number, or a ket +;; (i.e. closing bracKET), round or square. Assume that all characters \x80 to +;; \xff are "letters". +(defconst c-awk-div-sign-re + (concat c-awk-var-num-ket-re c-awk-neutrals*-re "/")) +;; Will match a piece of AWK buffer ending in / which is a division sign, in +;; a context where an immediate / would be a regexp bracket. It follows a +;; variable or number (with optional intervening "neutral" characters). This +;; will only work when there won't be a preceding " or / before the sought / +;; to foul things up. +(defconst c-awk-non-arith-op-bra-re + "[[\(&=:!><,?;'~|]") +;; Matches an openeing BRAcket ,round or square, or any operator character +;; apart from +,-,/,*,%. For the purpose at hand (detecting a / which is a +;; regexp bracket) these arith ops are unnecessary and a pain, because of "++" +;; and "--". +(defconst c-awk-regexp-sign-re + (concat c-awk-non-arith-op-bra-re c-awk-neutrals*-re "/")) +;; Will match a piece of AWK buffer ending in / which is an opening regexp +;; bracket, in a context where an immediate / would be a division sign. This +;; will only work when there won't be a preceding " or / before the sought / +;; to foul things up. + +;; REGEXPS USED FOR FINDING THE POSITION OF A "virtual semicolon" +(defconst c-awk-_-harmless-nonws-char-re "[^#/\"\\\\\n\r \t]") +;;;; NEW VERSION! (which will be restricted to the current line) +(defconst c-awk-one-line-non-syn-ws*-re + (concat "\\([ \t]*" + "\\(" c-awk-_-harmless-nonws-char-re "\\|" + c-awk-non-eol-esc-pair-re "\\|" + c-awk-one-line-possibly-open-string-re "\\|" + c-awk-one-line-possibly-open-regexp-re + "\\)" + "\\)*")) + + +;; ACM, 2002/5/29: +;; +;; The next section of code is about determining whether or not an AWK +;; statement is complete or not. We use this to indent the following line. +;; The determination is pretty straightforward in C, where a statement ends +;; with either a ; or a }. Only "while" really gives any trouble there, since +;; it might be the end of a do-while. In AWK, on the other hand, semicolons +;; are rarely used, and EOLs _usually_ act as "virtual semicolons". In +;; addition, we have the complexity of escaped EOLs. The core of this +;; analysis is in the middle of the function +;; c-awk-calculate-NL-prop-prev-line, about 130 lines lower down. +;; +;; To avoid continually repeating this expensive analysis, we "cache" its +;; result in a text-property, c-awk-NL-prop, whose value for a line is set on +;; the EOL (if any) which terminates that line. Should the property be +;; required for the very last line (which has no EOL), it is calculated as +;; required but not cached. The c-awk-NL-prop property should be thought of +;; as only really valid immediately after a buffer change, not a permanently +;; set property. (By contrast, the syntax-table text properties (set by an +;; after-change function) must be constantly updated for the mode to work +;; properly). +;; +;; This text property is also used for "syntactic whitespace" movement, this +;; being where the distinction between the values '$' and '}' is significant. +;; +;; The valid values for c-awk-NL-prop are: +;; +;; nil The property is not currently set for this line. +;; '#' There is NO statement on this line (at most a comment), and no open +;; statement from a previous line which could have been completed on this +;; line. +;; '{' There is an unfinished statement on this (or a previous) line which +;; doesn't require \s to continue onto another line, e.g. the line ends +;; with {, or the && operator, or "if (condition)". Note that even if the +;; newline is redundantly escaped, it remains a '{' line. +;; '\' There is an escaped newline at the end of this line and this '\' is +;; essential to the syntax of the program. (i.e. if it had been a +;; frivolous \, it would have been ignored and the line been given one of +;; the other property values.) +;; '$' A non-empty statement is terminated on the line by an EOL (a "virtual +;; semicolon"). This might be a content-free line terminating a statement +;; from the preceding (continued) line (which has property \). +;; '}' A statement, being the last thing (aside from ws/comments) is +;; explicitly terminated on this line by a closing brace (or sometimes a +;; semicolon). +;; +;; This set of values has been chosen so that the property's value on a line +;; is completely determined by the contents of the line and the property on +;; the previous line, EXCEPT for where a "while" might be the closing +;; statement of a do-while. + +(defun c-awk-after-if-for-while-condition-p (&optional do-lim) + ;; Are we just after the ) in "if/for/while ()"? + ;; + ;; Note that the end of the ) in a do .... while () doesn't + ;; count, since the purpose of this routine is essentially to decide + ;; whether to indent the next line. + ;; + ;; DO-LIM sets a limit on how far back we search for the "do" of a possible + ;; do-while. + ;; + ;; This function might do hidden buffer changes. + (and + (eq (char-before) ?\)) + (save-excursion + (let ((par-pos (c-safe (scan-lists (point) -1 0)))) + (when par-pos + (goto-char par-pos) ; back over "(...)" + (c-backward-token-1) ; BOB isn't a problem. + (or (looking-at "\\(if\\|for\\)\\>\\([^_]\\|$\\)") + (and (looking-at "while\\>\\([^_]\\|$\\)") ; Ensure this isn't a do-while. + (not (eq (c-beginning-of-statement-1 do-lim) + 'beginning))))))))) + +(defun c-awk-after-function-decl-param-list () + ;; Are we just after the ) in "function foo (bar)" ? + ;; + ;; This function might do hidden buffer changes. + (and (eq (char-before) ?\)) + (save-excursion + (let ((par-pos (c-safe (scan-lists (point) -1 0)))) + (when par-pos + (goto-char par-pos) ; back over "(...)" + (c-backward-token-1) ; BOB isn't a problem + (and (looking-at "[_a-zA-Z][_a-zA-Z0-9]*\\>") + (progn (c-backward-token-1) + (looking-at "func\\(tion\\)?\\>")))))))) + +;; 2002/11/8: FIXME! Check c-backward-token-1/2 for success (0 return code). +(defun c-awk-after-continue-token () +;; Are we just after a token which can be continued onto the next line without +;; a backslash? +;; +;; This function might do hidden buffer changes. + (save-excursion + (c-backward-token-1) ; FIXME 2002/10/27. What if this fails? + (if (and (looking-at "[&|]") (not (bobp))) + (backward-char)) ; c-backward-token-1 doesn't do this :-( + (looking-at "[,{?:]\\|&&\\|||\\|do\\>\\|else\\>"))) + +(defun c-awk-after-rbrace-or-statement-semicolon () + ;; Are we just after a } or a ; which closes a statement? + ;; Be careful about ;s in for loop control bits. They don't count! + ;; + ;; This function might do hidden buffer changes. + (or (eq (char-before) ?\}) + (and + (eq (char-before) ?\;) + (save-excursion + (let ((par-pos (c-safe (scan-lists (point) -1 1)))) + (when par-pos + (goto-char par-pos) ; go back to containing ( + (not (and (looking-at "(") + (c-backward-token-1) ; BOB isn't a problem + (looking-at "for\\>"))))))))) + +(defun c-awk-back-to-contentful-text-or-NL-prop () + ;; Move back to just after the first found of either (i) an EOL which has + ;; the c-awk-NL-prop text-property set; or (ii) non-ws text; or (iii) BOB. + ;; We return either the value of c-awk-NL-prop (in case (i)) or nil. + ;; Calling functions can best distinguish cases (ii) and (iii) with (bolp). + ;; + ;; Note that an escaped eol counts as whitespace here. + ;; + ;; Kludge: If c-backward-syntactic-ws gets stuck at a BOL, it is likely + ;; that the previous line contains an unterminated string (without \). In + ;; this case, assume that the previous line's c-awk-NL-prop is a $. + ;; + ;; POINT MUST BE AT THE START OF A LINE when calling this function. This + ;; is to ensure that the various backward-comment functions will work + ;; properly. + ;; + ;; This function might do hidden buffer changes. + (let ((nl-prop nil) + bol-pos bsws-pos) ; starting pos for a backward-syntactic-ws call. + (while ;; We are at a BOL here. Go back one line each iteration. + (and + (not (bobp)) + (not (setq nl-prop (c-get-char-property (1- (point)) 'c-awk-NL-prop))) + (progn (setq bol-pos (c-point 'bopl)) + (setq bsws-pos (point)) + ;; N.B. the following function will not go back past an EOL if + ;; there is an open string (without \) on the previous line. + ;; If we find such, set the c-awk-NL-prop on it, too + ;; (2004/3/29). + (c-backward-syntactic-ws bol-pos) + (or (/= (point) bsws-pos) + (progn (setq nl-prop ?\$) + (c-put-char-property (1- (point)) 'c-awk-NL-prop nl-prop) + nil))) + ;; If we had a backslash at EOL, c-backward-syntactic-ws will + ;; have gone backwards over it. Check the backslash was "real". + (progn + (if (looking-at "[ \t]*\\\\+$") + (if (progn + (end-of-line) + (search-backward-regexp + "\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\$" ; ODD number of \s at EOL :-) + bol-pos t)) + (progn (end-of-line) ; escaped EOL. + (backward-char) + (c-backward-syntactic-ws bol-pos)) + (end-of-line))) ; The \ at eol is a fake. + (bolp)))) + nl-prop)) + +(defun c-awk-calculate-NL-prop-prev-line (&optional do-lim) + ;; Calculate and set the value of the c-awk-NL-prop on the immediately + ;; preceding EOL. This may also involve doing the same for several + ;; preceding EOLs. + ;; + ;; NOTE that if the property was already set, we return it without + ;; recalculation. (This is by accident rather than design.) + ;; + ;; Return the property which got set (or was already set) on the previous + ;; line. Return nil if we hit BOB. + ;; + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (save-match-data + (beginning-of-line) + (let* ((pos (point)) + (nl-prop (c-awk-back-to-contentful-text-or-NL-prop))) + ;; We are either (1) at a BOL (with nl-prop containing the previous + ;; line's c-awk-NL-prop) or (2) after contentful text on a line. At + ;; the BOB counts as case (1), so we test next for bolp rather than + ;; non-nil nl-prop. + (when (not (bolp)) + (setq nl-prop + (cond + ;; Incomplete statement which doesn't require escaped EOL? + ((or (c-awk-after-if-for-while-condition-p do-lim) + (c-awk-after-function-decl-param-list) + (c-awk-after-continue-token)) + ?\{) + ;; Escaped EOL (where there's also something to continue)? + ((and (looking-at "[ \t]*\\\\$") + (not (c-awk-after-rbrace-or-statement-semicolon))) + ?\\) + ;; A statement was completed on this line. How? + ((memq (char-before) '(?\; ?\})) ?\}) ; Real ; or } + (t ?\$))) ; A virtual semicolon. + (end-of-line) + (c-put-char-property (point) 'c-awk-NL-prop nl-prop) + (forward-line)) + + ;; We are now at a (possibly empty) sequence of content-free lines. + ;; Set c-awk-NL-prop on each of these lines's EOL. + (while (< (point) pos) ; one content-free line each iteration. + (cond ; recalculate nl-prop from previous line's value. + ((memq nl-prop '(?\} ?\$ nil)) (setq nl-prop ?\#)) + ((eq nl-prop ?\\) + (if (not (looking-at "[ \t]*\\\\$")) (setq nl-prop ?\$))) + ;; ?\# (empty line) and ?\{ (open stmt) don't change. + ) + (forward-line) + (c-put-char-property (1- (point)) 'c-awk-NL-prop nl-prop)) + nl-prop)))) + +(defun c-awk-get-NL-prop-prev-line (&optional do-lim) + ;; Get the c-awk-NL-prop text-property from the previous line, calculating + ;; it if necessary. Return nil if we're already at BOB. + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (if (bobp) + nil + (or (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop) + (c-awk-calculate-NL-prop-prev-line do-lim)))) + +(defun c-awk-get-NL-prop-cur-line (&optional do-lim) + ;; Get the c-awk-NL-prop text-property from the current line, calculating it + ;; if necessary. (As a special case, the property doesn't get set on an + ;; empty line at EOB (there's no position to set the property on), but the + ;; function returns the property value an EOL would have got.) + ;; + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (let ((extra-nl nil)) + (end-of-line) ; Necessary for the following test to work. + (when (= (forward-line) 1) ; if we were on the last line.... + (insert-char ?\n 1) ; ...artificial eol is needed for comment detection. + (setq extra-nl t)) + (prog1 (c-awk-get-NL-prop-prev-line do-lim) + (if extra-nl (delete-char -1)))))) + +(defsubst c-awk-prev-line-incomplete-p (&optional do-lim) + ;; Is there an incomplete statement at the end of the previous line? + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (memq (c-awk-get-NL-prop-prev-line do-lim) '(?\\ ?\{))) + +(defsubst c-awk-cur-line-incomplete-p (&optional do-lim) + ;; Is there an incomplete statement at the end of the current line? + ;; See c-awk-after-if-for-while-condition-p for a description of DO-LIM. + ;; + ;; This function might do hidden buffer changes. + (memq (c-awk-get-NL-prop-cur-line do-lim) '(?\\ ?\{))) + +;;;; NOTES ON "VIRTUAL SEMICOLONS" +;;;; +;;;; A "virtual semicolon" is what terminates a statement when there is no ; +;;;; or } to do the job. Like point, it is considered to lie _between_ two +;;;; characters. As from mid-March 2004, it is considered to lie just after +;;;; the last non-syntactic-whitespace character on the line; (previously, it +;;;; was considered an attribute of the EOL on the line). A real semicolon +;;;; never counts as a virtual one. + +(defun c-awk-at-vsemi-p (&optional pos) + ;; Is there a virtual semicolon at POS (or POINT)? + (save-excursion + (let (nl-prop + (pos-or-point (progn (if pos (goto-char pos)) (point)))) + (forward-line 0) + (search-forward-regexp c-awk-one-line-non-syn-ws*-re) + (and (eq (point) pos-or-point) + (progn + (while (and (eq (setq nl-prop (c-awk-get-NL-prop-cur-line)) ?\\) + (eq (forward-line) 0) + (looking-at c-awk-blank-or-comment-line-re))) + (eq nl-prop ?\$)))))) + +(defun c-awk-vsemi-status-unknown-p () + ;; Are we unsure whether there is a virtual semicolon on the current line? + ;; DO NOT under any circumstances attempt to calculate this; that would + ;; defeat the (admittedly kludgey) purpose of this function, which is to + ;; prevent an infinite recursion in c-beginning-of-statement-1 when point + ;; starts at a `while' token. + (not (c-get-char-property (c-point 'eol) 'c-awk-NL-prop))) + +(defun c-awk-clear-NL-props (beg end) + ;; This function is run from before-change-hooks. It clears the + ;; c-awk-NL-prop text property from beg to the end of the buffer (The END + ;; parameter is ignored). This ensures that the indentation engine will + ;; never use stale values for this property. + ;; + ;; This function might do hidden buffer changes. + (save-restriction + (widen) + (c-clear-char-properties beg (point-max) 'c-awk-NL-prop))) + +(defun c-awk-unstick-NL-prop () + ;; Ensure that the text property c-awk-NL-prop is "non-sticky". Without + ;; this, a new newline inserted after an old newline (e.g. by C-j) would + ;; inherit any c-awk-NL-prop from the old newline. This would be a Bad + ;; Thing. This function's action is required by c-put-char-property. + (if (and (boundp 'text-property-default-nonsticky) ; doesn't exist in Xemacs + (not (assoc 'c-awk-NL-prop text-property-default-nonsticky))) + (setq text-property-default-nonsticky + (cons '(c-awk-NL-prop . t) text-property-default-nonsticky)))) + +;; The following is purely a diagnostic command, to be commented out of the +;; final release. ACM, 2002/6/1 +;; (defun NL-props () +;; (interactive) +;; (let (pl-prop cl-prop) +;; (message "Prev-line: %s Cur-line: %s" +;; (if (setq pl-prop (c-get-char-property (c-point 'eopl) 'c-awk-NL-prop)) +;; (char-to-string pl-prop) +;; "nil") +;; (if (setq cl-prop (c-get-char-property (c-point 'eol) 'c-awk-NL-prop)) +;; (char-to-string cl-prop) +;; "nil")))) +;(define-key awk-mode-map [?\C-c ?\r] 'NL-props) ; commented out, 2002/8/31 +;for now. In the byte compiled version, this causes things to crash because +;awk-mode-map isn't yet defined. :-( + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; The following section of the code is to do with font-locking. The biggest +;; problem for font-locking is deciding whether a / is a regular expression +;; delimiter or a division sign - determining precisely where strings and +;; regular expressions start and stop is also troublesome. This is the +;; purpose of the function c-awk-set-syntax-table-properties and the myriad +;; elisp regular expressions it uses. +;; +;; Because AWK is a line oriented language, I felt the normal cc-mode strategy +;; for font-locking unterminated strings (i.e. font-locking the buffer up to +;; the next string delimiter as a string) was inappropriate. Instead, +;; unbalanced string/regexp delimiters are given the warning font, being +;; refonted with the string font as soon as the matching delimiter is entered. +;; +;; This requires the region processed by the current font-lock after-change +;; function to have access to the start of the string/regexp, which may be +;; several lines back. The elisp "advice" feature is used on these functions +;; to allow this. + +(defun c-awk-beginning-of-logical-line (&optional pos) +;; Go back to the start of the (apparent) current line (or the start of the +;; line containing POS), returning the buffer position of that point. I.e., +;; go back to the last line which doesn't have an escaped EOL before it. +;; +;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any +;; comment, string or regexp. IT MAY WELL BE that this function should not be +;; executed on a narrowed buffer. +;; +;; This function might do hidden buffer changes. + (if pos (goto-char pos)) + (forward-line 0) + (while (and (> (point) (point-min)) + (eq (char-before (1- (point))) ?\\)) + (forward-line -1)) + (point)) + +(defun c-awk-beyond-logical-line (&optional pos) +;; Return the position just beyond the (apparent) current logical line, or the +;; one containing POS. This is usually the beginning of the next line which +;; doesn't follow an escaped EOL. At EOB, this will be EOB. +;; +;; Point is unchanged. +;; +;; This is guaranteed to be "safe" for syntactic analysis, i.e. outwith any +;; comment, string or regexp. IT MAY WELL BE that this function should not be +;; executed on a narrowed buffer. + (save-excursion + (if pos (goto-char pos)) + (end-of-line) + (while (and (< (point) (point-max)) + (eq (char-before) ?\\)) + (end-of-line 2)) + (if (< (point) (point-max)) + (1+ (point)) + (point)))) + +;; ACM, 2002/02/15: The idea of the next function is to put the "Error font" +;; on strings/regexps which are missing their closing delimiter. +;; 2002/4/28. The default syntax for / has been changed from "string" to +;; "punctuation", to reduce hassle when this character appears within a string +;; or comment. + +(defun c-awk-set-string-regexp-syntax-table-properties (beg end) +;; BEG and END bracket a (possibly unterminated) string or regexp. The +;; opening delimiter is after BEG, and the closing delimiter, IF ANY, is AFTER +;; END. Set the appropriate syntax-table properties on the delimiters and +;; contents of this string/regex. +;; +;; "String" here can also mean a gawk 3.1 "localizable" string which starts +;; with _". In this case, we step over the _ and ignore it; It will get it's +;; font from an entry in awk-font-lock-keywords. +;; +;; If the closing delimiter is missing (i.e., there is an EOL there) set the +;; STRING-FENCE property on the opening " or / and closing EOL. +;; +;; This function does hidden buffer changes. + (if (eq (char-after beg) ?_) (setq beg (1+ beg))) + + ;; First put the properties on the delimiters. + (cond ((eq end (point-max)) ; string/regexp terminated by EOB + (c-put-char-property beg 'syntax-table '(15))) ; (15) = "string fence" + ((/= (char-after beg) (char-after end)) ; missing end delimiter + (c-put-char-property beg 'syntax-table '(15)) + (c-put-char-property end 'syntax-table '(15))) + ((eq (char-after beg) ?/) ; Properly bracketed regexp + (c-put-char-property beg 'syntax-table '(7)) ; (7) = "string" + (c-put-char-property end 'syntax-table '(7))) + (t)) ; Properly bracketed string: Nothing to do. + ;; Now change the properties of any escaped "s in the string to punctuation. + (save-excursion + (goto-char (1+ beg)) + (or (eobp) + (while (search-forward "\"" end t) + (c-put-char-property (1- (point)) 'syntax-table '(1)))))) + +(defun c-awk-syntax-tablify-string () + ;; Point is at the opening " or _" of a string. Set the syntax-table + ;; properties on this string, leaving point just after the string. + ;; + ;; The result is nil if a / immediately after the string would be a regexp + ;; opener, t if it would be a division sign. + ;; + ;; This function does hidden buffer changes. + (search-forward-regexp c-awk-string-without-end-here-re nil t) ; a (possibly unterminated) string + (c-awk-set-string-regexp-syntax-table-properties + (match-beginning 0) (match-end 0)) + (cond ((looking-at "\"") + (forward-char) + t) ; In AWK, ("15" / 5) gives 3 ;-) + ((looking-at "[\n\r]") ; Unterminated string with EOL. + (forward-char) + nil) ; / on next line would start a regexp + (t nil))) ; Unterminated string at EOB + +(defun c-awk-syntax-tablify-/ (anchor anchor-state-/div) + ;; Point is at a /. Determine whether this is a division sign or a regexp + ;; opener, and if the latter, apply syntax-table properties to the entire + ;; regexp. Point is left immediately after the division sign or regexp, as + ;; the case may be. + ;; + ;; ANCHOR-STATE-/DIV identifies whether a / at ANCHOR would have been a + ;; division sign (value t) or a regexp opener (value nil). The idea is that + ;; we analyse the line from ANCHOR up till point to determine what the / at + ;; point is. + ;; + ;; The result is what ANCHOR-STATE-/DIV (see above) is where point is left. + ;; + ;; This function does hidden buffer changes. + (let ((/point (point))) + (goto-char anchor) + ;; Analyse the line to find out what the / is. + (if (if anchor-state-/div + (not (search-forward-regexp c-awk-regexp-sign-re (1+ /point) t)) + (search-forward-regexp c-awk-div-sign-re (1+ /point) t)) + ;; A division sign. + (progn (goto-char (1+ /point)) nil) + ;; A regexp opener + ;; Jump over the regexp innards, setting the match data. + (goto-char /point) + (search-forward-regexp c-awk-regexp-without-end-re) + (c-awk-set-string-regexp-syntax-table-properties + (match-beginning 0) (match-end 0)) + (cond ((looking-at "/") ; Terminating / + (forward-char) + t) + ((looking-at "[\n\r]") ; Incomplete regexp terminated by EOL + (forward-char) + nil) ; / on next line would start another regexp + (t nil))))) ; Unterminated regexp at EOB + +(defun c-awk-set-syntax-table-properties (lim) +;; Scan the buffer text between point and LIM, setting (and clearing) the +;; syntax-table property where necessary. +;; +;; This function is designed to be called as the FUNCTION in a MATCHER in +;; font-lock-syntactic-keywords, and it always returns NIL (to inhibit +;; repeated calls from font-lock: See elisp info page "Search-based +;; Fontification"). It also gets called, with a bit of glue, from +;; after-change-functions when font-lock isn't active. Point is left +;; "undefined" after this function exits. THE BUFFER SHOULD HAVE BEEN +;; WIDENED, AND ANY PRECIOUS MATCH-DATA SAVED BEFORE CALLING THIS ROUTINE. +;; +;; We need to set/clear the syntax-table property on: +;; (i) / - It is set to "string" on a / which is the opening or closing +;; delimiter of the properly terminated regexp (and left unset on a +;; division sign). +;; (ii) the opener of an unterminated string/regexp, we set the property +;; "generic string delimiter" on both the opening " or / and the end of the +;; line where the closing delimiter is missing. +;; (iii) "s inside strings/regexps (these will all be escaped "s). They are +;; given the property "punctuation". This will later allow other routines +;; to use the regexp "\\S\"*" to skip over the string innards. +;; (iv) Inside a comment, all syntax-table properties are cleared. +;; +;; This function does hidden buffer changes. + (let (anchor + (anchor-state-/div nil)) ; t means a following / would be a div sign. + (c-awk-beginning-of-logical-line) ; ACM 2002/7/21. This is probably redundant. + (c-clear-char-properties (point) lim 'syntax-table) + ;; Once round the next loop for each string, regexp, or div sign + (while (progn + ;; Skip any "harmless" lines before the next tricky one. + (if (search-forward-regexp c-awk-harmless-lines+-here-re nil t) + (setq anchor-state-/div nil)) + (< (point) lim)) + (setq anchor (point)) + (search-forward-regexp c-awk-harmless-string*-here-re nil t) + ;; We are now looking at either a " or a /. + ;; Do our thing on the string, regexp or divsion sign. + (setq anchor-state-/div + (if (looking-at "_?\"") + (c-awk-syntax-tablify-string) + (c-awk-syntax-tablify-/ anchor anchor-state-/div)))) + nil)) + +;; ACM, 2002/07/21: Thoughts: We need an AWK Mode after-change function to set +;; the syntax-table properties even when font-lock isn't enabled, for the +;; subsequent use of movement functions, etc. However, it seems that if font +;; lock _is_ enabled, we can always leave it to do the job. +(defvar c-awk-old-ByLL 0) +(make-variable-buffer-local 'c-awk-old-Byll) +;; Just beyond logical line following the region which is about to be changed. +;; Set in c-awk-record-region-clear-NL and used in c-awk-after-change. + +(defun c-awk-record-region-clear-NL (beg end) +;; This function is called exclusively from the before-change-functions hook. +;; It does two things: Finds the end of the (logical) line on which END lies, +;; and clears c-awk-NL-prop text properties from this point onwards. BEG is +;; ignored. +;; +;; On entry, the buffer will have been widened and match-data will have been +;; saved; point is undefined on both entry and exit; the return value is +;; ignored. +;; +;; This function does hidden buffer changes. + (c-save-buffer-state () + (setq c-awk-old-ByLL (c-awk-beyond-logical-line end)) + (c-save-buffer-state nil + (c-awk-clear-NL-props end (point-max))))) + +(defun c-awk-end-of-change-region (beg end old-len) + ;; Find the end of the region which needs to be font-locked after a change. + ;; This is the end of the logical line on which the change happened, either + ;; as it was before the change, or as it is now, whichever is later. + ;; N.B. point is left undefined. + (max (+ (- c-awk-old-ByLL old-len) (- end beg)) + (c-awk-beyond-logical-line end))) + +;; ACM 2002/5/25. When font-locking is invoked by a buffer change, the region +;; specified by the font-lock after-change function must be expanded to +;; include ALL of any string or regexp within the region. The simplest way to +;; do this in practice is to use the beginning/end-of-logical-line functions. +;; Don't overlook the possibility of the buffer change being the "recapturing" +;; of a previously escaped newline. + +;; ACM 2008-02-05: +(defun c-awk-extend-and-syntax-tablify-region (beg end old-len) + ;; Expand the region (BEG END) as needed to (c-new-BEG c-new-END) then put + ;; `syntax-table' properties on this region. + ;; + ;; This function is called from an after-change function, BEG END and + ;; OLD-LEN being the standard parameters. + ;; + ;; Point is undefined both before and after this function call, the buffer + ;; has been widened, and match-data saved. The return value is ignored. + ;; + ;; It prepares the buffer for font + ;; locking, hence must get called before `font-lock-after-change-function'. + ;; + ;; This function is the AWK value of `c-before-font-lock-function'. + ;; It does hidden buffer changes. + (c-save-buffer-state () + (setq c-new-END (c-awk-end-of-change-region beg end old-len)) + (setq c-new-BEG (c-awk-beginning-of-logical-line beg)) + (goto-char c-new-BEG) + (c-awk-set-syntax-table-properties c-new-END))) + +;; Awk regexps written with help from Peter Galbraith +;; . +;; Take GNU Emacs's 'words out of the following regexp-opts. They dont work +;; in Xemacs 21.4.4. acm 2002/9/19. +(defconst awk-font-lock-keywords + (eval-when-compile + (list + ;; Function names. + '("^\\s *\\(func\\(tion\\)?\\)\\>\\s *\\(\\sw+\\)?" + (1 font-lock-keyword-face) (3 font-lock-function-name-face nil t)) + ;; + ;; Variable names. + (cons + (concat "\\<" + (regexp-opt + '("ARGC" "ARGIND" "ARGV" "BINMODE" "CONVFMT" "ENVIRON" + "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR" "FS" "IGNORECASE" + "LINT" "NF" "NR" "OFMT" "OFS" "ORS" "PROCINFO" "RLENGTH" + "RS" "RSTART" "RT" "SUBSEP" "TEXTDOMAIN") t) "\\>") + 'font-lock-variable-name-face) + + ;; Special file names. (acm, 2002/7/22) + ;; The following regexp was created by first evaluating this in GNU Emacs 21.1: + ;; (regexp-opt '("/dev/stdin" "/dev/stdout" "/dev/stderr" "/dev/fd/n" "/dev/pid" + ;; "/dev/ppid" "/dev/pgrpid" "/dev/user") 'words) + ;; , removing the "?:" from each "\\(?:" (for backward compatibility with older Emacsen) + ;; , replacing the "n" in "dev/fd/n" with "[0-9]+" + ;; , removing the unwanted \\< at the beginning, and finally filling out the + ;; regexp so that a " must come before, and either a " or heuristic stuff after. + ;; The surrounding quotes are fontified along with the filename, since, semantically, + ;; they are an indivisible unit. + '("\\(\"/dev/\\(fd/[0-9]+\\|p\\(\\(\\(gr\\)?p\\)?id\\)\\|\ +std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\ +\\(\\(\"\\)\\|\\([^\"/\n\r][^\"\n\r]*\\)?$\\)" + (1 font-lock-variable-name-face t) + (8 font-lock-variable-name-face t t)) + ;; Do the same (almost) with + ;; (regexp-opt '("/inet/tcp/lport/rhost/rport" "/inet/udp/lport/rhost/rport" + ;; "/inet/raw/lport/rhost/rport") 'words) + ;; This cannot be combined with the above pattern, because the match number + ;; for the (optional) closing \" would then exceed 9. + '("\\(\"/inet/\\(\\(raw\\|\\(tc\\|ud\\)p\\)/lport/rhost/rport\\)\\)\\>\ +\\(\\(\"\\)\\|\\([^\"/\n\r][^\"\n\r]*\\)?$\\)" + (1 font-lock-variable-name-face t) + (6 font-lock-variable-name-face t t)) + + ;; Keywords. + (concat "\\<" + (regexp-opt + '("BEGIN" "END" "break" "case" "continue" "default" "delete" + "do" "else" "exit" "for" "getline" "if" "in" "next" + "nextfile" "return" "switch" "while") + t) "\\>") + + ;; Builtins. + `(eval . (list + ,(concat + "\\<" + (regexp-opt + '("adump" "and" "asort" "atan2" "bindtextdomain" "close" + "compl" "cos" "dcgettext" "exp" "extension" "fflush" + "gensub" "gsub" "index" "int" "length" "log" "lshift" + "match" "mktime" "or" "print" "printf" "rand" "rshift" + "sin" "split" "sprintf" "sqrt" "srand" "stopme" + "strftime" "strtonum" "sub" "substr" "system" + "systime" "tolower" "toupper" "xor") t) + "\\>") + 0 c-preprocessor-face-name)) + + ;; gawk debugging keywords. (acm, 2002/7/21) + ;; (Removed, 2003/6/6. These functions are now fontified as built-ins) + ;; (list (concat "\\<" (regexp-opt '("adump" "stopme") t) "\\>") + ;; 0 'font-lock-warning-face) + + ;; User defined functions with an apparent spurious space before the + ;; opening parenthesis. acm, 2002/5/30. + `(,(concat "\\(\\w\\|_\\)" c-awk-escaped-nls* "\\s " + c-awk-escaped-nls*-with-space* "(") + (0 'font-lock-warning-face)) + + ;; Space after \ in what looks like an escaped newline. 2002/5/31 + '("\\\\\\s +$" 0 font-lock-warning-face t) + + ;; Unbalanced string (") or regexp (/) delimiters. 2002/02/16. + '("\\s|" 0 font-lock-warning-face t nil) + ;; gawk 3.1 localizable strings ( _"translate me!"). 2002/5/21 + '("\\(_\\)\\s|" 1 font-lock-warning-face) + '("\\(_\\)\\s\"" 1 font-lock-string-face) ; FIXME! not for XEmacs. 2002/10/6 + )) + "Default expressions to highlight in AWK mode.") + +;; ACM 2002/9/29. Movement functions, e.g. for C-M-a and C-M-e + +;; The following three regexps differ from those earlier on in cc-awk.el in +;; that they assume the syntax-table properties have been set. They are thus +;; not useful for code which sets these properties. +(defconst c-awk-terminated-regexp-or-string-here-re "\\=\\s\"\\S\"*\\s\"") +;; Matches a terminated string/regexp. + +(defconst c-awk-unterminated-regexp-or-string-here-re "\\=\\s|\\S|*$") +;; Matches an unterminated string/regexp, NOT including the eol at the end. + +(defconst c-awk-harmless-pattern-characters* + (concat "\\([^{;#/\"\\\\\n\r]\\|" c-awk-esc-pair-re "\\)*")) +;; Matches any "harmless" character in a pattern or an escaped character pair. + +(defun c-awk-at-statement-end-p () + ;; Point is not inside a comment or string. Is it AT the end of a + ;; statement? This means immediately after the last non-ws character of the + ;; statement. The caller is responsible for widening the buffer, if + ;; appropriate. + (and (not (bobp)) + (save-excursion + (backward-char) + (or (looking-at "[};]") + (and (memq (c-awk-get-NL-prop-cur-line) '(?\$ ?\\)) + (looking-at + (eval-when-compile + (concat "[^ \t\n\r\\]" c-awk-escaped-nls*-with-space* + "[#\n\r]")))))))) + +(defun c-awk-beginning-of-defun (&optional arg) + "Move backward to the beginning of an AWK \"defun\". With ARG, do it that +many times. Negative arg -N means move forward to Nth following beginning of +defun. Returns t unless search stops due to beginning or end of buffer. + +By a \"defun\" is meant either a pattern-action pair or a function. The start +of a defun is recognized as code starting at column zero which is neither a +closing brace nor a comment nor a continuation of the previous line. Unlike +in some other modes, having an opening brace at column 0 is neither necessary +nor helpful. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (interactive "p") + (or arg (setq arg 1)) + (save-match-data + (c-save-buffer-state ; ensures the buffer is writable. + nil + (let ((found t)) ; Has the most recent regexp search found b-of-defun? + (if (>= arg 0) + ;; Go back one defun each time round the following loop. (For +ve arg) + (while (and found (> arg 0) (not (eq (point) (point-min)))) + ;; Go back one "candidate" each time round the next loop until one + ;; is genuinely a beginning-of-defun. + (while (and (setq found (search-backward-regexp + "^[^#} \t\n\r]" (point-min) 'stop-at-limit)) + (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#))))) + (setq arg (1- arg))) + ;; The same for a -ve arg. + (if (not (eq (point) (point-max))) (forward-char 1)) + (while (and found (< arg 0) (not (eq (point) (point-max)))) ; The same for -ve arg. + (while (and (setq found (search-forward-regexp + "^[^#} \t\n\r]" (point-max) 'stop-at-limit)) + (not (memq (c-awk-get-NL-prop-prev-line) '(?\$ ?\} ?\#))))) + (setq arg (1+ arg))) + (if found (goto-char (match-beginning 0)))) + (eq arg 0))))) + +(defun c-awk-forward-awk-pattern () + ;; Point is at the start of an AWK pattern (which may be null) or function + ;; declaration. Move to the pattern's end, and past any trailing space or + ;; comment. Typically, we stop at the { which denotes the corresponding AWK + ;; action/function body. Otherwise we stop at the EOL (or ;) marking the + ;; absence of an explicit action. + ;; + ;; This function might do hidden buffer changes. + (while + (progn + (search-forward-regexp c-awk-harmless-pattern-characters*) + (if (looking-at "#") (end-of-line)) + (cond + ((eobp) nil) + ((looking-at "[{;]") nil) ; We've finished! + ((eolp) + (if (c-awk-cur-line-incomplete-p) + (forward-line) ; returns non-nil + nil)) + ((search-forward-regexp c-awk-terminated-regexp-or-string-here-re nil t)) + ((search-forward-regexp c-awk-unterminated-regexp-or-string-here-re nil t)) + ((looking-at "/") (forward-char) t))))) ; division sign. + +(defun c-awk-end-of-defun1 () + ;; point is at the start of a "defun". Move to its end. Return end position. + ;; + ;; This function might do hidden buffer changes. + (c-awk-forward-awk-pattern) + (cond + ((looking-at "{") (goto-char (scan-sexps (point) 1))) + ((looking-at ";") (forward-char)) + ((eolp)) + (t (error "c-awk-end-of-defun1: Failure of c-awk-forward-awk-pattern"))) + (point)) + +(defun c-awk-beginning-of-defun-p () + ;; Are we already at the beginning of a defun? (i.e. at code in column 0 + ;; which isn't a }, and isn't a continuation line of any sort. + ;; + ;; This function might do hidden buffer changes. + (and (looking-at "^[^#} \t\n\r]") + (not (c-awk-prev-line-incomplete-p)))) + +(defun c-awk-end-of-defun (&optional arg) + "Move forward to next end of defun. With argument, do it that many times. +Negative argument -N means move back to Nth preceding end of defun. + +An end of a defun occurs right after the closing brace that matches the +opening brace at its start, or immediately after the AWK pattern when there is +no explicit action; see function `c-awk-beginning-of-defun'. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (interactive "p") + (or arg (setq arg 1)) + (save-match-data + (c-save-buffer-state + nil + (let ((start-point (point)) end-point) + ;; Strategy: (For +ve ARG): If we're not already at a beginning-of-defun, + ;; move backwards to one. + ;; Repeat [(i) move forward to end-of-current-defun (see below); + ;; (ii) If this isn't it, move forward to beginning-of-defun]. + ;; We start counting ARG only when step (i) has passed the original point. + (when (> arg 0) + ;; Try to move back to a beginning-of-defun, if not already at one. + (if (not (c-awk-beginning-of-defun-p)) + (when (not (c-awk-beginning-of-defun 1)) ; No bo-defun before point. + (goto-char start-point) + (c-awk-beginning-of-defun -1))) ; if this fails, we're at EOB, tough! + ;; Now count forward, one defun at a time + (while (and (not (eobp)) + (c-awk-end-of-defun1) + (if (> (point) start-point) (setq arg (1- arg)) t) + (> arg 0) + (c-awk-beginning-of-defun -1)))) + + (when (< arg 0) + (setq end-point start-point) + (while (and (not (bobp)) + (c-awk-beginning-of-defun 1) + (if (< (setq end-point (if (bobp) (point) + (save-excursion (c-awk-end-of-defun1)))) + start-point) + (setq arg (1+ arg)) t) + (< arg 0))) + (goto-char (min start-point end-point))))))) + + +(cc-provide 'cc-awk) ; Changed from 'awk-mode, ACM 2002/5/21 + +;;; arch-tag: c4836289-3aa4-4a59-9934-9ccc2bacccf3 +;;; awk-mode.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-bytecomp.el b/site-lisp/cc-mode/5.32.3/cc-bytecomp.el new file mode 100644 index 0000000..ae002e3 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-bytecomp.el @@ -0,0 +1,494 @@ +;;; cc-bytecomp.el --- compile time setup for proper compilation + +;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +;; 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Author: Martin Stjernholm +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 15-Jul-2000 +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; This file is used to ensure that the CC Mode files are correctly +;; compiled regardless the environment (e.g. if an older CC Mode with +;; outdated macros are loaded during compilation). It also provides +;; features to defeat the compiler warnings for selected symbols. +;; +;; There's really nothing CC Mode specific here; this functionality +;; ought to be provided by the byte compilers or some accompanying +;; library. To use it from some package "foo.el", begin by putting +;; the following blurb at the top of the file: +;; +;; (eval-when-compile +;; (let ((load-path +;; (if (and (boundp 'byte-compile-dest-file) +;; (stringp byte-compile-dest-file)) +;; (cons (file-name-directory byte-compile-dest-file) load-path) +;; load-path))) +;; (load "cc-bytecomp" nil t)) +;; +;; This (unfortunately rather clumsy) form will ensure that the +;; cc-bytecomp.el in the same directory as foo.el is loaded during +;; byte compilation of the latter. +;; +;; At the end of foo.el there should normally be a "(provide 'foo)". +;; Replace it with "(cc-provide 'foo)"; that is necessary to restore +;; the environment after the byte compilation. If you don't have a +;; `provide' at the end, you have to add the following as the very +;; last form in the file: +;; +;; (eval-when-compile (cc-bytecomp-restore-environment)) +;; +;; Now everything is set to use the various functions and macros in +;; this package. +;; +;; If your package is split into several files, you should use +;; `cc-require', `cc-require-when-compile' or `cc-load' to load them. +;; That ensures that the files in the same directory always are +;; loaded, to avoid mixup with other versions of them that might exist +;; elsewhere in the load path. +;; +;; To suppress byte compiler warnings, use the macros +;; `cc-bytecomp-defun', `cc-bytecomp-defvar', +;; `cc-bytecomp-obsolete-fun', and `cc-bytecomp-obsolete-var'. +;; +;; This file is not used at all after the package has been byte +;; compiled. It is however necessary when running uncompiled. + + +;;; Code: + +(defvar cc-bytecomp-unbound-variables nil) +(defvar cc-bytecomp-original-functions nil) +(defvar cc-bytecomp-original-properties nil) +(defvar cc-bytecomp-loaded-files nil) +(defvar cc-bytecomp-push-vars nil + "A stack ((VAR GLOBAL-VAL SETQD-VAL) ...)") + +(setq cc-bytecomp-unbound-variables nil) +(setq cc-bytecomp-original-functions nil) +(setq cc-bytecomp-original-properties nil) +(setq cc-bytecomp-loaded-files nil) +(setq cc-bytecomp-push-vars nil) + +(defvar cc-bytecomp-environment-set nil) + +(defmacro cc-bytecomp-debug-msg (&rest args) + ;;`(message ,@args) + ) + +(defun cc-bytecomp-setup-environment () + ;; Eval'ed during compilation to setup variables, functions etc + ;; declared with `cc-bytecomp-defvar' et al. + (if (not load-in-progress) + ;; Look at `load-in-progress' to tell whether we're called + ;; directly in the file being compiled or just from some file + ;; being loaded during compilation. + (let (p) + (if cc-bytecomp-environment-set + (error "Byte compilation environment already set - \ +perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere")) + (setq p cc-bytecomp-unbound-variables) + (while p + (if (not (boundp (car p))) + (progn + (eval `(defvar ,(car p))) + (set (car p) (intern (concat "cc-bytecomp-ignore-var:" + (symbol-name (car p))))) + (cc-bytecomp-debug-msg + "cc-bytecomp-setup-environment: Covered variable %s" + (car p)))) + (setq p (cdr p))) + (setq p cc-bytecomp-original-functions) + (while p + (let ((fun (car (car p))) + (temp-macro (car (cdr (car p))))) + (if (not (fboundp fun)) + (if temp-macro + (progn + (eval `(defmacro ,fun ,@temp-macro)) + (cc-bytecomp-debug-msg + "cc-bytecomp-setup-environment: Bound macro %s" fun)) + (fset fun (intern (concat "cc-bytecomp-ignore-fun:" + (symbol-name fun)))) + (cc-bytecomp-debug-msg + "cc-bytecomp-setup-environment: Covered function %s" fun)))) + (setq p (cdr p))) + (setq p cc-bytecomp-original-properties) + (while p + (let ((sym (car (car (car p)))) + (prop (cdr (car (car p)))) + (tempdef (car (cdr (car p))))) + (put sym prop tempdef) + (cc-bytecomp-debug-msg + "cc-bytecomp-setup-environment: Bound property %s for %s to %s" + prop sym tempdef)) + (setq p (cdr p))) + (setq p (reverse cc-bytecomp-push-vars)) + (while p + (let ((var (caar p)) + (setqd-val (cadr (cdar p)))) + (set var setqd-val) + (cc-bytecomp-debug-msg + "cc-bytecomp-setup-environment: Set variable %s to %s" + var setqd-val)) + (setq p (cdr p))) + (setq cc-bytecomp-environment-set t) + (cc-bytecomp-debug-msg + "cc-bytecomp-setup-environment: Done")))) + +(defun cc-bytecomp-restore-environment () + ;; Eval'ed during compilation to restore variables, functions etc + ;; declared with `cc-bytecomp-defvar' et al. + (if (not load-in-progress) + (let (p) + (setq p cc-bytecomp-unbound-variables) + (while p + (let ((var (car p))) + (if (boundp var) + (if (eq (intern (concat "cc-bytecomp-ignore-var:" + (symbol-name var))) + (symbol-value var)) + (progn + (makunbound var) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Unbound variable %s" + var)) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Not restoring variable %s" + var)))) + (setq p (cdr p))) + (setq p cc-bytecomp-original-functions) + (while p + (let ((fun (car (car p))) + (temp-macro (car (cdr (car p)))) + (def (car (cdr (cdr (car p)))))) + (if (fboundp fun) + (if (eq (or temp-macro + (intern (concat "cc-bytecomp-ignore-fun:" + (symbol-name fun)))) + (symbol-function fun)) + (if (eq def 'unbound) + (progn + (fmakunbound fun) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Unbound function %s" + fun)) + (fset fun def) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Restored function %s" + fun)) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Not restoring function %s" + fun)))) + (setq p (cdr p))) + (setq p cc-bytecomp-original-properties) + (while p + (let ((sym (car (car (car p)))) + (prop (cdr (car (car p)))) + (tempdef (car (cdr (car p)))) + (origdef (cdr (cdr (car p))))) + (if (eq (get sym prop) tempdef) + (progn + (put sym prop origdef) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Restored property %s for %s to %s" + prop sym origdef)) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Not restoring property %s for %s" + prop sym))) + (setq p (cdr p))) + (setq p cc-bytecomp-push-vars) + (while p + (let ((var (caar p)) + (global-val (cadr (car p))) + ) + (if (eq global-val 'cc-bytecomp-unbound) + (makunbound var) + (set var global-val)) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Restored variable %s to %s" + var global-val)) + (setq p (cdr p))) + (setq cc-bytecomp-environment-set nil) + (cc-bytecomp-debug-msg + "cc-bytecomp-restore-environment: Done")))) + +(eval + ;; This eval is to avoid byte compilation of the function below. + ;; There's some bug in XEmacs 21.4.6 that can cause it to dump core + ;; here otherwise. My theory is that `cc-bytecomp-load' might be + ;; redefined recursively during the `load' inside it, and if it in + ;; that case is byte compiled then the byte interpreter gets + ;; confused. I haven't succeeded in isolating the bug, though. /mast + + '(defun cc-bytecomp-load (cc-part) + ;; Eval'ed during compilation to load a CC Mode file from the source + ;; directory (assuming it's the same as the compiled file + ;; destination dir). + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (progn + (cc-bytecomp-restore-environment) + (let ((load-path + (cons (file-name-directory byte-compile-dest-file) + load-path)) + (cc-file (concat cc-part ".el"))) + (if (member cc-file cc-bytecomp-loaded-files) + () + (setq cc-bytecomp-loaded-files + (cons cc-file cc-bytecomp-loaded-files)) + (cc-bytecomp-debug-msg + "cc-bytecomp-load: Loading %S" cc-file) + (load cc-file nil t t) + (cc-bytecomp-debug-msg + "cc-bytecomp-load: Loaded %S" cc-file))) + (cc-bytecomp-setup-environment) + t)))) + +(defmacro cc-require (cc-part) + "Force loading of the corresponding .el file in the current directory +during compilation, but compile in a `require'. Don't use within +`eval-when-compile'. + +Having cyclic cc-require's will result in infinite recursion. That's +somewhat intentional." + `(progn + (eval-when-compile (cc-bytecomp-load (symbol-name ,cc-part))) + (require ,cc-part))) + +(defmacro cc-provide (feature) + "A replacement for the `provide' form that restores the environment +after the compilation. Don't use within `eval-when-compile'." + `(progn + (eval-when-compile (cc-bytecomp-restore-environment)) + (provide ,feature))) + +(defmacro cc-load (cc-part) + "Force loading of the corresponding .el file in the current directory +during compilation. Don't use outside `eval-when-compile' or +`eval-and-compile'. + +Having cyclic cc-load's will result in infinite recursion. That's +somewhat intentional." + `(or (and (featurep 'cc-bytecomp) + (cc-bytecomp-load ,cc-part)) + (load ,cc-part nil t nil))) + +(defmacro cc-require-when-compile (cc-part) + "Force loading of the corresponding .el file in the current directory +during compilation, but do a compile time `require' otherwise. Don't +use within `eval-when-compile'." + `(eval-when-compile + (if (and (featurep 'cc-bytecomp) + (cc-bytecomp-is-compiling)) + (if (or (not load-in-progress) + (not (featurep ,cc-part))) + (cc-bytecomp-load (symbol-name ,cc-part))) + (require ,cc-part)))) + +(defmacro cc-external-require (feature) + "Do a `require' of an external package. +This restores and sets up the compilation environment before and +afterwards. Don't use within `eval-when-compile'." + `(progn + (eval-when-compile (cc-bytecomp-restore-environment)) + (require ,feature) + (eval-when-compile (cc-bytecomp-setup-environment)))) + +(defun cc-bytecomp-is-compiling () + "Return non-nil if eval'ed during compilation. Don't use outside +`eval-when-compile'." + (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file))) + +(defmacro cc-bytecomp-defvar (var) + "Binds the symbol as a variable during compilation of the file, +to silence the byte compiler. Don't use within `eval-when-compile'." + `(eval-when-compile + (if (boundp ',var) + (cc-bytecomp-debug-msg + "cc-bytecomp-defvar: %s bound already as variable" ',var) + (if (not (memq ',var cc-bytecomp-unbound-variables)) + (progn + (cc-bytecomp-debug-msg + "cc-bytecomp-defvar: Saving %s (as unbound)" ',var) + (setq cc-bytecomp-unbound-variables + (cons ',var cc-bytecomp-unbound-variables)))) + (if (and (cc-bytecomp-is-compiling) + (not load-in-progress)) + (progn + (defvar ,var) + (set ',var (intern (concat "cc-bytecomp-ignore-var:" + (symbol-name ',var)))) + (cc-bytecomp-debug-msg + "cc-bytecomp-defvar: Covered variable %s" ',var)))))) + +(defmacro cc-bytecomp-defun (fun) + "Bind the symbol as a function during compilation of the file, +to silence the byte compiler. Don't use within `eval-when-compile'. + +If the symbol already is bound as a function, it will keep that +definition. That means that this macro will not shut up warnings +about incorrect number of arguments. It's dangerous to try to replace +existing functions since the byte compiler might need the definition +at compile time, e.g. for macros and inline functions." + `(eval-when-compile + (if (fboundp ',fun) + (cc-bytecomp-debug-msg + "cc-bytecomp-defun: %s bound already as function" ',fun) + (if (not (assq ',fun cc-bytecomp-original-functions)) + (progn + (cc-bytecomp-debug-msg + "cc-bytecomp-defun: Saving %s (as unbound)" ',fun) + (setq cc-bytecomp-original-functions + (cons (list ',fun nil 'unbound) + cc-bytecomp-original-functions)))) + (if (and (cc-bytecomp-is-compiling) + (not load-in-progress)) + (progn + (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:" + (symbol-name ',fun)))) + (cc-bytecomp-debug-msg + "cc-bytecomp-defun: Covered function %s" ',fun)))))) + +(put 'cc-bytecomp-defmacro 'lisp-indent-function 'defun) +(defmacro cc-bytecomp-defmacro (fun &rest temp-macro) + "Bind the symbol as a macro during compilation (and evaluation) of the +file. Don't use outside `eval-when-compile'." + `(let ((orig-fun (assq ',fun cc-bytecomp-original-functions))) + (if (not orig-fun) + (setq orig-fun + (list ',fun + nil + (if (fboundp ',fun) + (progn + (cc-bytecomp-debug-msg + "cc-bytecomp-defmacro: Saving %s" ',fun) + (symbol-function ',fun)) + (cc-bytecomp-debug-msg + "cc-bytecomp-defmacro: Saving %s as unbound" ',fun) + 'unbound)) + cc-bytecomp-original-functions + (cons orig-fun cc-bytecomp-original-functions))) + (defmacro ,fun ,@temp-macro) + (cc-bytecomp-debug-msg + "cc-bytecomp-defmacro: Bound macro %s" ',fun) + (setcar (cdr orig-fun) (symbol-function ',fun)))) + +(defmacro cc-bytecomp-put (symbol propname value) + "Set a property on a symbol during compilation (and evaluation) of +the file. Don't use outside `eval-when-compile'." + `(eval-when-compile + (if (not (assoc (cons ,symbol ,propname) cc-bytecomp-original-properties)) + (progn + (cc-bytecomp-debug-msg + "cc-bytecomp-put: Saving property %s for %s with value %s" + ,propname ,symbol (get ,symbol ,propname)) + (setq cc-bytecomp-original-properties + (cons (cons (cons ,symbol ,propname) + (cons ,value (get ,symbol ,propname))) + cc-bytecomp-original-properties)))) + (put ,symbol ,propname ,value) + (cc-bytecomp-debug-msg + "cc-bytecomp-put: Bound property %s for %s to %s" + ,propname ,symbol ,value))) + +(defmacro cc-bytecomp-push (symbol value) + "Set SYMBOL to VALUE during compilation (and evaluation) of the file. +Don't use within `eval-when-compile'." + `(eval-when-compile + (cc-bytecomp-debug-msg + "cc-bytecomp-push: symbol is %s, value is %s" + ',symbol ,value) + (setq cc-bytecomp-set-vars + (cons (list ',symbol + (if (boundp ',symbol) + ,symbol + 'cc-bytecomp-unbound) + ,value) + cc-bytecomp-push-vars)) + (cc-bytecomp-debug-msg + "cc-bytecomp-push: set %s to %s" ',symbol ,value) + (set ',symbol ,value) + (cc-bytecomp-debug-msg + "cc-bytecomp-push: cc-bytecomp-push-vars is %s" cc-bytecomp-push-vars))) + +(defmacro cc-bytecomp-obsolete-var (symbol) + "Suppress warnings that the given symbol is an obsolete variable. +Don't use within `eval-when-compile'." + `(eval-when-compile + (if (get ',symbol 'byte-obsolete-variable) + (cc-bytecomp-put ',symbol 'byte-obsolete-variable nil) + ;; This avoids a superfluous compiler warning + ;; about calling `get' for effect. + t))) + +(defun cc-bytecomp-ignore-obsolete (form) + ;; Wraps a call to `byte-compile-obsolete' that suppresses the warning. + (let ((byte-compile-warnings byte-compile-warnings)) + (if (fboundp 'byte-compile-disable-warning) ; Emacs 23+ + (byte-compile-disable-warning 'obsolete) + (delq 'obsolete (append byte-compile-warnings nil))) + (if (fboundp 'byte-compile-obsolete) ; purely to suppress a warnin. + (byte-compile-obsolete form)))) + +(defmacro cc-bytecomp-obsolete-fun (symbol) + "Suppress warnings that the given symbol is an obsolete function. +Don't use within `eval-when-compile'." + `(eval-when-compile + ,(if (fboundp 'byte-compile-obsolete) + `(if (eq (get ',symbol 'byte-compile) 'byte-compile-obsolete) + (cc-bytecomp-put ',symbol 'byte-compile + 'cc-bytecomp-ignore-obsolete) + ;; This avoids a superfluous compiler warning + ;; about calling `get' for effect. + t) + `(cc-bytecomp-push byte-compile-not-obsolete-funcs '(,symbol))))) + +(defmacro cc-bytecomp-boundp (symbol) + "Return non-nil if the given symbol is bound as a variable outside +the compilation. This is the same as using `boundp' but additionally +exclude any variables that have been bound during compilation with +`cc-bytecomp-defvar'." + (if (and (cc-bytecomp-is-compiling) + (memq (car (cdr symbol)) cc-bytecomp-unbound-variables)) + nil + `(boundp ,symbol))) + +(defmacro cc-bytecomp-fboundp (symbol) + "Return non-nil if the given symbol is bound as a function outside +the compilation. This is the same as using `fboundp' but additionally +exclude any functions that have been bound during compilation with +`cc-bytecomp-defun'." + (let (fun-elem) + (if (and (cc-bytecomp-is-compiling) + (setq fun-elem (assq (car (cdr symbol)) + cc-bytecomp-original-functions)) + (eq (elt fun-elem 2) 'unbound)) + nil + `(fboundp ,symbol)))) + + +(provide 'cc-bytecomp) + +;;; arch-tag: 2d71b3ad-57b0-4b13-abd3-ab836e08f975 +;;; cc-bytecomp.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-cmds.el b/site-lisp/cc-mode/5.32.3/cc-cmds.el new file mode 100644 index 0000000..3dcdb39 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-cmds.el @@ -0,0 +1,4710 @@ +;;; cc-cmds.el --- user level commands for CC Mode + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2003- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 22-Apr-1997 (split from cc-mode.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-engine) + +;; Silence the compiler. +(cc-bytecomp-defun delete-forward-p) ; XEmacs +(cc-bytecomp-defvar filladapt-mode) ; c-fill-paragraph contains a kludge + ; which looks at this. +(cc-bytecomp-defun c-forward-subword) +(cc-bytecomp-defun c-backward-subword) + +;; Indentation / Display syntax functions +(defvar c-fix-backslashes t) + +(defun c-indent-line (&optional syntax quiet ignore-point-pos) + "Indent the current line according to the syntactic context, +if `c-syntactic-indentation' is non-nil. Optional SYNTAX is the +syntactic information for the current line. Be silent about syntactic +errors if the optional argument QUIET is non-nil, even if +`c-report-syntactic-errors' is non-nil. Normally the position of +point is used to decide where the old indentation is on a lines that +is otherwise empty \(ignoring any line continuation backslash), but +that's not done if IGNORE-POINT-POS is non-nil. Returns the amount of +indentation change \(in columns)." + + (let ((line-cont-backslash (save-excursion + (end-of-line) + (eq (char-before) ?\\))) + (c-fix-backslashes c-fix-backslashes) + bs-col + shift-amt) + (when (and (not ignore-point-pos) + (save-excursion + (beginning-of-line) + (looking-at (if line-cont-backslash + ;; Don't use "\\s " - ^L doesn't count as WS + ;; here + "\\([ \t]*\\)\\\\$" + "\\([ \t]*\\)$"))) + (<= (point) (match-end 1))) + ;; Delete all whitespace after point if there's only whitespace + ;; on the line, so that any code that does back-to-indentation + ;; or similar gets the current column in this case. If this + ;; removes a line continuation backslash it'll be restored + ;; at the end. + (unless c-auto-align-backslashes + ;; Should try to keep the backslash alignment + ;; in this case. + (save-excursion + (goto-char (match-end 0)) + (setq bs-col (1- (current-column))))) + (delete-region (point) (match-end 0)) + (setq c-fix-backslashes t)) + (if c-syntactic-indentation + (setq c-parsing-error + (or (let ((c-parsing-error nil) + (c-syntactic-context + (or syntax + (and (boundp 'c-syntactic-context) + c-syntactic-context)))) + (c-save-buffer-state (indent) + (unless c-syntactic-context + (setq c-syntactic-context (c-guess-basic-syntax))) + (setq indent (c-get-syntactic-indentation + c-syntactic-context)) + (and (not (c-echo-parsing-error quiet)) + c-echo-syntactic-information-p + (message "syntax: %s, indent: %d" + c-syntactic-context indent)) + (setq shift-amt (- indent (current-indentation)))) + (c-shift-line-indentation shift-amt) + (run-hooks 'c-special-indent-hook) + c-parsing-error) + c-parsing-error)) + (let ((indent 0)) + (save-excursion + (while (and (= (forward-line -1) 0) + (if (looking-at "\\s *\\\\?$") + t + (setq indent (current-indentation)) + nil)))) + (setq shift-amt (- indent (current-indentation))) + (c-shift-line-indentation shift-amt))) + (when (and c-fix-backslashes line-cont-backslash) + (if bs-col + (save-excursion + (indent-to bs-col) + (insert ?\\)) + (when c-auto-align-backslashes + ;; Realign the line continuation backslash. + (c-backslash-region (point) (point) nil t)))) + shift-amt)) + +(defun c-newline-and-indent (&optional newline-arg) + "Insert a newline and indent the new line. +This function fixes line continuation backslashes if inside a macro, +and takes care to set the indentation before calling +`indent-according-to-mode', so that lineup functions like +`c-lineup-dont-change' works better." + + ;; TODO: Backslashes before eol in comments and literals aren't + ;; kept intact. + (let ((c-macro-start (c-query-macro-start)) + ;; Avoid calling c-backslash-region from c-indent-line if it's + ;; called during the newline call, which can happen due to + ;; c-electric-continued-statement, for example. We also don't + ;; want any backslash alignment from indent-according-to-mode. + (c-fix-backslashes nil) + has-backslash insert-backslash + start col) + (save-excursion + (beginning-of-line) + (setq start (point)) + (while (and (looking-at "[ \t]*\\\\?$") + (= (forward-line -1) 0))) + (setq col (current-indentation))) + (when c-macro-start + (if (and (eolp) (eq (char-before) ?\\)) + (setq insert-backslash t + has-backslash t) + (setq has-backslash (eq (char-before (c-point 'eol)) ?\\)))) + (newline newline-arg) + (indent-to col) + (when c-macro-start + (if insert-backslash + (progn + ;; The backslash stayed on the previous line. Insert one + ;; before calling c-backslash-region, so that + ;; bs-col-after-end in it works better. Fixup the + ;; backslashes on the newly inserted line. + (insert ?\\) + (backward-char) + (c-backslash-region (point) (point) nil t)) + ;; The backslash moved to the new line, if there was any. Let + ;; c-backslash-region fix a backslash on the previous line, + ;; and the one that might be on the new line. + ;; c-auto-align-backslashes is intentionally ignored here; + ;; maybe the moved backslash should be left alone if it's set, + ;; but we fix both lines on the grounds that the old backslash + ;; has been moved anyway and is now in a different context. + (c-backslash-region start (if has-backslash (point) start) nil t))) + (when c-syntactic-indentation + ;; Reindent syntactically. The indentation done above is not + ;; wasted, since c-indent-line might look at the current + ;; indentation. + (let ((c-syntactic-context (c-save-buffer-state nil + (c-guess-basic-syntax)))) + ;; We temporarily insert another line break, so that the + ;; lineup functions will see the line as empty. That makes + ;; e.g. c-lineup-cpp-define more intuitive since it then + ;; proceeds to the preceding line in this case. + (insert ?\n) + (delete-horizontal-space) + (setq start (- (point-max) (point))) + (unwind-protect + (progn + (backward-char) + (indent-according-to-mode)) + (goto-char (- (point-max) start)) + (delete-char -1))) + (when has-backslash + ;; Must align the backslash again after reindentation. The + ;; c-backslash-region call above can't be optimized to ignore + ;; this line, since it then won't align correctly with the + ;; lines below if the first line in the macro is broken. + (c-backslash-region (point) (point) nil t))))) + +(defun c-show-syntactic-information (arg) + "Show syntactic information for current line. +With universal argument, inserts the analysis as a comment on that line." + (interactive "P") + (let* ((c-parsing-error nil) + (syntax (if (boundp 'c-syntactic-context) + ;; Use `c-syntactic-context' in the same way as + ;; `c-indent-line', to be consistent. + c-syntactic-context + (c-save-buffer-state nil + (c-guess-basic-syntax))))) + (if (not (consp arg)) + (let (elem pos ols) + (message "Syntactic analysis: %s" syntax) + (unwind-protect + (progn + (while syntax + (setq elem (pop syntax)) + (when (setq pos (c-langelem-pos elem)) + (push (c-put-overlay pos (1+ pos) + 'face 'highlight) + ols)) + (when (setq pos (c-langelem-2nd-pos elem)) + (push (c-put-overlay pos (1+ pos) + 'face 'secondary-selection) + ols))) + (sit-for 10)) + (while ols + (c-delete-overlay (pop ols))))) + (indent-for-comment) + (insert-and-inherit (format "%s" syntax)) + )) + (c-keep-region-active)) + +(defun c-syntactic-information-on-region (from to) + "Insert a comment with the syntactic analysis on every line in the region." + (interactive "*r") + (save-excursion + (save-restriction + (narrow-to-region from to) + (goto-char (point-min)) + (while (not (eobp)) + (c-show-syntactic-information '(0)) + (forward-line))))) + + +;; Minor mode functions. +(defun c-update-modeline () + (let ((fmt (format "/%s%s%s%s" + (if c-electric-flag "l" "") + (if (and c-electric-flag c-auto-newline) + "a" "") + (if c-hungry-delete-key "h" "") + (if (and + ;; cc-subword might not be loaded. + (boundp 'c-subword-mode) + (symbol-value 'c-subword-mode)) + "w" + ""))) + (bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name) + (substring mode-name (match-beginning 1) (match-end 1)) + mode-name))) +;; (setq c-submode-indicators +;; (if (> (length fmt) 1) +;; fmt)) + (setq mode-name + (if (> (length fmt) 1) + (concat bare-mode-name fmt) + bare-mode-name)) + (force-mode-line-update))) + +(defun c-toggle-syntactic-indentation (&optional arg) + "Toggle syntactic indentation. +Optional numeric ARG, if supplied, turns on syntactic indentation when +positive, turns it off when negative, and just toggles it when zero or +left out. + +When syntactic indentation is turned on (the default), the indentation +functions and the electric keys indent according to the syntactic +context keys, when applicable. + +When it's turned off, the electric keys don't reindent, the indentation +functions indents every new line to the same level as the previous +nonempty line, and \\[c-indent-command] adjusts the indentation in steps +specified by `c-basic-offset'. The indentation style has no effect in +this mode, nor any of the indentation associated variables, +e.g. `c-special-indent-hook'. + +This command sets the variable `c-syntactic-indentation'." + (interactive "P") + (setq c-syntactic-indentation + (c-calculate-state arg c-syntactic-indentation)) + (c-keep-region-active)) + +(defun c-toggle-auto-newline (&optional arg) + "Toggle auto-newline feature. +Optional numeric ARG, if supplied, turns on auto-newline when +positive, turns it off when negative, and just toggles it when zero or +left out. + +Turning on auto-newline automatically enables electric indentation. + +When the auto-newline feature is enabled (indicated by \"/la\" on the +modeline after the mode name) newlines are automatically inserted +after special characters such as brace, comma, semi-colon, and colon." + (interactive "P") + (setq c-auto-newline + (c-calculate-state arg (and c-auto-newline c-electric-flag))) + (if c-auto-newline (setq c-electric-flag t)) + (c-update-modeline) + (c-keep-region-active)) + +(defalias 'c-toggle-auto-state 'c-toggle-auto-newline) +(make-obsolete 'c-toggle-auto-state 'c-toggle-auto-newline nil) + +(defun c-toggle-hungry-state (&optional arg) + "Toggle hungry-delete-key feature. +Optional numeric ARG, if supplied, turns on hungry-delete when +positive, turns it off when negative, and just toggles it when zero or +left out. + +When the hungry-delete-key feature is enabled (indicated by \"/h\" on +the modeline after the mode name) the delete key gobbles all preceding +whitespace in one fell swoop." + (interactive "P") + (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key)) + (c-update-modeline) + (c-keep-region-active)) + +(defun c-toggle-auto-hungry-state (&optional arg) + "Toggle auto-newline and hungry-delete-key features. +Optional numeric ARG, if supplied, turns on auto-newline and +hungry-delete when positive, turns them off when negative, and just +toggles them when zero or left out. + +See `c-toggle-auto-newline' and `c-toggle-hungry-state' for details." + (interactive "P") + (setq c-auto-newline (c-calculate-state arg c-auto-newline)) + (setq c-hungry-delete-key (c-calculate-state arg c-hungry-delete-key)) + (c-update-modeline) + (c-keep-region-active)) + +(defun c-toggle-electric-state (&optional arg) + "Toggle the electric indentation feature. +Optional numeric ARG, if supplied, turns on electric indentation when +positive, turns it off when negative, and just toggles it when zero or +left out." + (interactive "P") + (setq c-electric-flag (c-calculate-state arg c-electric-flag)) + (c-update-modeline) + (c-keep-region-active)) + + +;; Electric keys + +(defun c-electric-backspace (arg) + "Delete the preceding character or whitespace. +If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode +line) then all preceding whitespace is consumed. If however a prefix +argument is supplied, or `c-hungry-delete-key' is nil, or point is +inside a literal then the function in the variable +`c-backspace-function' is called." + (interactive "*P") + (if (c-save-buffer-state () + (or (not c-hungry-delete-key) + arg + (c-in-literal))) + (funcall c-backspace-function (prefix-numeric-value arg)) + (c-hungry-delete-backwards))) + +(defun c-hungry-delete-backwards () + "Delete the preceding character or all preceding whitespace +back to the previous non-whitespace character. +See also \\[c-hungry-delete-forward]." + (interactive) + (let ((here (point))) + (c-skip-ws-backward) + (if (/= (point) here) + (delete-region (point) here) + (funcall c-backspace-function 1)))) + +(defalias 'c-hungry-backspace 'c-hungry-delete-backwards) + +(defun c-electric-delete-forward (arg) + "Delete the following character or whitespace. +If `c-hungry-delete-key' is non-nil (indicated by \"/h\" on the mode +line) then all following whitespace is consumed. If however a prefix +argument is supplied, or `c-hungry-delete-key' is nil, or point is +inside a literal then the function in the variable `c-delete-function' +is called." + (interactive "*P") + (if (c-save-buffer-state () + (or (not c-hungry-delete-key) + arg + (c-in-literal))) + (funcall c-delete-function (prefix-numeric-value arg)) + (c-hungry-delete-forward))) + +(defun c-hungry-delete-forward () + "Delete the following character or all following whitespace +up to the next non-whitespace character. +See also \\[c-hungry-delete-backwards]." + (interactive) + (let ((here (point))) + (c-skip-ws-forward) + (if (/= (point) here) + (delete-region (point) here) + (funcall c-delete-function 1)))) + +;; This function is only used in XEmacs. +(defun c-electric-delete (arg) + "Deletes preceding or following character or whitespace. +This function either deletes forward as `c-electric-delete-forward' or +backward as `c-electric-backspace', depending on the configuration: If +the function `delete-forward-p' is defined and returns non-nil, it +deletes forward. Otherwise it deletes backward. + +Note: This is the way in XEmacs to choose the correct action for the +\[delete] key, whichever key that means. Other flavors don't use this +function to control that." + (interactive "*P") + (if (and (fboundp 'delete-forward-p) + (delete-forward-p)) + (c-electric-delete-forward arg) + (c-electric-backspace arg))) + +;; This function is only used in XEmacs. +(defun c-hungry-delete () + "Delete a non-whitespace char, or all whitespace up to the next non-whitespace char. +The direction of deletion depends on the configuration: If the +function `delete-forward-p' is defined and returns non-nil, it deletes +forward using `c-hungry-delete-forward'. Otherwise it deletes +backward using `c-hungry-backspace'. + +Note: This is the way in XEmacs to choose the correct action for the +\[delete] key, whichever key that means. Other flavors don't use this +function to control that." + (interactive) + (if (and (fboundp 'delete-forward-p) + (delete-forward-p)) + (c-hungry-delete-forward) + (c-hungry-delete-backwards))) + +(defun c-electric-pound (arg) + "Insert a \"#\". +If `c-electric-flag' is set, handle it specially according to the variable +`c-electric-pound-behavior'. If a numeric ARG is supplied, or if point is +inside a literal or a macro, nothing special happens." + (interactive "*P") + (if (c-save-buffer-state () + (or arg + (not c-electric-flag) + (not (memq 'alignleft c-electric-pound-behavior)) + (save-excursion + (skip-chars-backward " \t") + (not (bolp))) + (save-excursion + (and (= (forward-line -1) 0) + (progn (end-of-line) + (eq (char-before) ?\\)))) + (c-in-literal))) + ;; do nothing special + (self-insert-command (prefix-numeric-value arg)) + ;; place the pound character at the left edge + (let ((pos (- (point-max) (point))) + (bolp (bolp))) + (beginning-of-line) + (delete-horizontal-space) + (insert last-command-event) + (and (not bolp) + (goto-char (- (point-max) pos))) + ))) + +(defun c-point-syntax () + ;; Return the syntactic context of the construct at point. (This is NOT + ;; nec. the same as the s.c. of the line point is on). N.B. This won't work + ;; between the `#' of a cpp thing and what follows (see c-opt-cpp-prefix). + (c-save-buffer-state (;; shut this up too + (c-echo-syntactic-information-p nil) + syntax) + (c-tentative-buffer-changes + ;; insert a newline to isolate the construct at point for syntactic + ;; analysis. + (insert-char ?\n 1) + ;; In AWK (etc.) or in a macro, make sure this CR hasn't changed + ;; the syntax. (There might already be an escaped NL there.) + (when (or (c-at-vsemi-p (1- (point))) + (let ((pt (point))) + (save-excursion + (backward-char) + (and (c-beginning-of-macro) + (progn (c-end-of-macro) + (< (point) pt)))))) + (backward-char) + (insert-char ?\\ 1) + (forward-char)) + (let ((c-syntactic-indentation-in-macros t) + (c-auto-newline-analysis t)) + ;; Turn on syntactic macro analysis to help with auto + ;; newlines only. + (setq syntax (c-guess-basic-syntax)) + nil)) + syntax)) + +(defun c-brace-newlines (syntax) + ;; A brace stands at point. SYNTAX is the syntactic context of this brace + ;; (not necessarily the same as the S.C. of the line it is on). Return + ;; NEWLINES, the list containing some combination of the symbols `before' + ;; and `after' saying where newlines should be inserted. + (c-save-buffer-state + ((syms + ;; This is the list of brace syntactic symbols that can hang. + ;; If any new ones are added to c-offsets-alist, they should be + ;; added here as well. + ;; + ;; The order of this list is important; if SYNTAX has several + ;; elements, the element that "wins" is the earliest in SYMS. + '(arglist-cont-nonempty ; e.g. an array literal. + class-open class-close defun-open defun-close + inline-open inline-close + brace-list-open brace-list-close + brace-list-intro brace-entry-open + block-open block-close + substatement-open statement-case-open + extern-lang-open extern-lang-close + namespace-open namespace-close + module-open module-close + composition-open composition-close + inexpr-class-open inexpr-class-close + ;; `statement-cont' is here for the case with a brace + ;; list opener inside a statement. C.f. CASE B.2 in + ;; `c-guess-continued-construct'. + statement-cont)) + ;; shut this up too + (c-echo-syntactic-information-p nil) + symb-newlines) ; e.g. (substatement-open . (after)) + + (setq symb-newlines + ;; Do not try to insert newlines around a special + ;; (Pike-style) brace list. + (if (and c-special-brace-lists + (save-excursion + (c-safe (if (= (char-before) ?{) + (forward-char -1) + (c-forward-sexp -1)) + (c-looking-at-special-brace-list)))) + nil + ;; Seek the matching entry in c-hanging-braces-alist. + (or (c-lookup-lists + syms + ;; Substitute inexpr-class and class-open or + ;; class-close with inexpr-class-open or + ;; inexpr-class-close. + (if (assq 'inexpr-class syntax) + (cond ((assq 'class-open syntax) + '((inexpr-class-open))) + ((assq 'class-close syntax) + '((inexpr-class-close))) + (t syntax)) + syntax) + c-hanging-braces-alist) + '(ignore before after)))) ; Default, when not in c-h-b-l. + + ;; If syntax is a function symbol, then call it using the + ;; defined semantics. + (if (and (not (consp (cdr symb-newlines))) + (functionp (cdr symb-newlines))) + (let ((c-syntactic-context syntax)) + (funcall (cdr symb-newlines) + (car symb-newlines) + (point))) + (cdr symb-newlines)))) + +(defun c-try-one-liner () + ;; Point is just after a newly inserted }. If the non-whitespace + ;; content of the braces is a single line of code, compact the whole + ;; construct to a single line, if this line isn't too long. The Right + ;; Thing is done with comments. + ;; + ;; Point will be left after the }, regardless of whether the clean-up is + ;; done. Return NON-NIL if the clean-up happened, NIL if it didn't. + + (let ((here (point)) + (pos (- (point-max) (point))) + mbeg1 mend1 mbeg4 mend4 + eol-col cmnt-pos cmnt-col cmnt-gap) + + (when + (save-excursion + (save-restriction + ;; Avoid backtracking over a very large block. The one we + ;; deal with here can never be more than three lines. + (narrow-to-region (save-excursion + (forward-line -2) + (point)) + (point)) + (and (c-safe (c-backward-sexp)) + (progn + (forward-char) + (narrow-to-region (point) (1- here)) ; innards of {.} + (looking-at + (cc-eval-when-compile + (concat + "\\(" ; (match-beginning 1) + "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL + "\\)" ; (match-end 1) + "[^ \t\r\n]+\\([ \t]+[^ \t\r\n]+\\)*" ; non-WS + "\\(" ; (match-beginning 4) + "[ \t]*\\([\r\n][ \t]*\\)?" ; WS with opt. NL + "\\)\\'"))))))) ; (match-end 4) at EOB. + + (if (c-tentative-buffer-changes + (setq mbeg1 (match-beginning 1) mend1 (match-end 1) + mbeg4 (match-beginning 4) mend4 (match-end 4)) + (backward-char) ; back over the `}' + (save-excursion + (setq cmnt-pos (and (c-backward-single-comment) + (- (point) (- mend1 mbeg1))))) + (delete-region mbeg4 mend4) + (delete-region mbeg1 mend1) + (setq eol-col (save-excursion (end-of-line) (current-column))) + + ;; Necessary to put the closing brace before any line + ;; oriented comment to keep it syntactically significant. + ;; This isn't necessary for block comments, but the result + ;; looks nicer anyway. + (when cmnt-pos + (delete-char 1) ; the `}' has blundered into a comment + (goto-char cmnt-pos) + (setq cmnt-col (1+ (current-column))) + (setq cmnt-pos (1+ cmnt-pos)) ; we're inserting a `}' + (c-skip-ws-backward) + (insert-char ?\} 1) ; reinsert the `}' before the comment. + (setq cmnt-gap (- cmnt-col (current-column))) + (when (zerop cmnt-gap) + (insert-char ?\ 1) ; Put a space before a bare comment. + (setq cmnt-gap 1))) + + (or (null c-max-one-liner-length) + (zerop c-max-one-liner-length) + (<= eol-col c-max-one-liner-length) + ;; Can we trim space before comment to make the line fit? + (and cmnt-gap + (< (- eol-col cmnt-gap) c-max-one-liner-length) + (progn (goto-char cmnt-pos) + (backward-delete-char-untabify + (- eol-col c-max-one-liner-length)) + t)))) + (goto-char (- (point-max) pos)))))) + +(defun c-electric-brace (arg) + "Insert a brace. + +If `c-electric-flag' is non-nil, the brace is not inside a literal and a +numeric ARG hasn't been supplied, the command performs several electric +actions: + +\(a) If the auto-newline feature is turned on (indicated by \"/la\" on +the mode line) newlines are inserted before and after the brace as +directed by the settings in `c-hanging-braces-alist'. + +\(b) Any auto-newlines are indented. The original line is also +reindented unless `c-syntactic-indentation' is nil. + +\(c) If auto-newline is turned on, various newline cleanups based on the +settings of `c-cleanup-list' are done." + + (interactive "*P") + (let (safepos literal + ;; We want to inhibit blinking the paren since this would be + ;; most disruptive. We'll blink it ourselves later on. + (old-blink-paren blink-paren-function) + blink-paren-function case-fold-search) + + (c-save-buffer-state () + (setq safepos (c-safe-position (point) (c-parse-state)) + literal (c-in-literal safepos))) + + ;; Insert the brace. Note that expand-abbrev might reindent + ;; the line here if there's a preceding "else" or something. + (self-insert-command (prefix-numeric-value arg)) + + (when (and c-electric-flag (not literal) (not arg)) + (if (not (looking-at "[ \t]*\\\\?$")) + (if c-syntactic-indentation + (indent-according-to-mode)) + + (let ( ;; shut this up too + (c-echo-syntactic-information-p nil) + newlines + ln-syntax br-syntax syntax) ; Syntactic context of the original line, + ; of the brace itself, of the line the brace ends up on. + (c-save-buffer-state ((c-syntactic-indentation-in-macros t) + (c-auto-newline-analysis t)) + (setq ln-syntax (c-guess-basic-syntax))) + (if c-syntactic-indentation + (c-indent-line ln-syntax)) + + (when c-auto-newline + (backward-char) + (setq br-syntax (c-point-syntax) + newlines (c-brace-newlines br-syntax)) + + ;; Insert the BEFORE newline, if wanted, and reindent the newline. + (if (and (memq 'before newlines) + (> (current-column) (current-indentation))) + (if c-syntactic-indentation + ;; Only a plain newline for now - it's indented + ;; after the cleanups when the line has its final + ;; appearance. + (newline) + (c-newline-and-indent))) + (forward-char) + + ;; `syntax' is the syntactic context of the line which ends up + ;; with the brace on it. + (setq syntax (if (memq 'before newlines) br-syntax ln-syntax)) + + ;; Do all appropriate clean ups + (let ((here (point)) + (pos (- (point-max) (point))) + mbeg mend + ) + + ;; `}': clean up empty defun braces + (when (c-save-buffer-state () + (and (memq 'empty-defun-braces c-cleanup-list) + (eq last-command-event ?\}) + (c-intersect-lists '(defun-close class-close inline-close) + syntax) + (progn + (forward-char -1) + (c-skip-ws-backward) + (eq (char-before) ?\{)) + ;; make sure matching open brace isn't in a comment + (not (c-in-literal)))) + (delete-region (point) (1- here)) + (setq here (- (point-max) pos))) + (goto-char here) + + ;; `}': compact to a one-liner defun? + (save-match-data + (when + (and (eq last-command-event ?\}) + (memq 'one-liner-defun c-cleanup-list) + (c-intersect-lists '(defun-close) syntax) + (c-try-one-liner)) + (setq here (- (point-max) pos)))) + + ;; `{': clean up brace-else-brace and brace-elseif-brace + (when (eq last-command-event ?\{) + (cond + ((and (memq 'brace-else-brace c-cleanup-list) + (re-search-backward + (concat "}" + "\\([ \t\n]\\|\\\\\n\\)*" + "else" + "\\([ \t\n]\\|\\\\\n\\)*" + "{" + "\\=") + nil t)) + (delete-region (match-beginning 0) (match-end 0)) + (insert-and-inherit "} else {")) + ((and (memq 'brace-elseif-brace c-cleanup-list) + (progn + (goto-char (1- here)) + (setq mend (point)) + (c-skip-ws-backward) + (setq mbeg (point)) + (eq (char-before) ?\))) + (zerop (c-save-buffer-state nil (c-backward-token-2 1 t))) + (eq (char-after) ?\() + ; (progn + ; (setq tmp (point)) + (re-search-backward + (concat "}" + "\\([ \t\n]\\|\\\\\n\\)*" + "else" + "\\([ \t\n]\\|\\\\\n\\)+" + "if" + "\\([ \t\n]\\|\\\\\n\\)*" + "\\=") + nil t);) + ;(eq (match-end 0) tmp); + ) + (delete-region mbeg mend) + (goto-char mbeg) + (insert ?\ )))) + + (goto-char (- (point-max) pos)) + + ;; Indent the line after the cleanups since it might + ;; very well indent differently due to them, e.g. if + ;; c-indent-one-line-block is used together with the + ;; one-liner-defun cleanup. + (when c-syntactic-indentation + (c-indent-line))) + + ;; does a newline go after the brace? + (if (memq 'after newlines) + (c-newline-and-indent)) + )))) + + ;; blink the paren + (and (eq last-command-event ?\}) + (not executing-kbd-macro) + old-blink-paren + (save-excursion + (c-save-buffer-state nil + (c-backward-syntactic-ws safepos)) + (funcall old-blink-paren))))) + +(defun c-electric-slash (arg) + "Insert a slash character. + +If the slash is inserted immediately after the comment prefix in a c-style +comment, the comment might get closed by removing whitespace and possibly +inserting a \"*\". See the variable `c-cleanup-list'. + +Indent the line as a comment, if: + + 1. The slash is second of a \"//\" line oriented comment introducing + token and we are on a comment-only-line, or + + 2. The slash is part of a \"*/\" token that closes a block oriented + comment. + +If a numeric ARG is supplied, point is inside a literal, or +`c-syntactic-indentation' is nil or `c-electric-flag' is nil, indentation +is inhibited." + (interactive "*P") + (let ((literal (c-save-buffer-state () (c-in-literal))) + indentp + ;; shut this up + (c-echo-syntactic-information-p nil)) + + ;; comment-close-slash cleanup? This DOESN'T need `c-electric-flag' or + ;; `c-syntactic-indentation' set. + (when (and (not arg) + (eq literal 'c) + (memq 'comment-close-slash c-cleanup-list) + (eq last-command-event ?/) + (looking-at (concat "[ \t]*\\(" + (regexp-quote comment-end) "\\)?$")) + ; (eq c-block-comment-ender "*/") ; C-style comments ALWAYS end in */ + (save-excursion + (save-restriction + (narrow-to-region (point-min) (point)) + (back-to-indentation) + (looking-at (concat c-current-comment-prefix "[ \t]*$"))))) + (delete-region (progn (forward-line 0) (point)) + (progn (end-of-line) (point))) + (insert-char ?* 1)) ; the / comes later. ; Do I need a t (retain sticky properties) here? + + (setq indentp (and (not arg) + c-syntactic-indentation + c-electric-flag + (eq last-command-event ?/) + (eq (char-before) (if literal ?* ?/)))) + (self-insert-command (prefix-numeric-value arg)) + (if indentp + (indent-according-to-mode)))) + +(defun c-electric-star (arg) + "Insert a star character. +If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, and +the star is the second character of a C style comment starter on a +comment-only-line, indent the line as a comment. If a numeric ARG is +supplied, point is inside a literal, or `c-syntactic-indentation' is nil, +this indentation is inhibited." + + (interactive "*P") + (self-insert-command (prefix-numeric-value arg)) + ;; if we are in a literal, or if arg is given do not reindent the + ;; current line, unless this star introduces a comment-only line. + (if (c-save-buffer-state () + (and c-syntactic-indentation + c-electric-flag + (not arg) + (eq (c-in-literal) 'c) + (eq (char-before) ?*) + (save-excursion + (forward-char -1) + (skip-chars-backward "*") + (if (eq (char-before) ?/) + (forward-char -1)) + (skip-chars-backward " \t") + (bolp)))) + (let (c-echo-syntactic-information-p) ; shut this up + (indent-according-to-mode)) + )) + +(defun c-electric-semi&comma (arg) + "Insert a comma or semicolon. + +If `c-electric-flag' is non-nil, point isn't inside a literal and a +numeric ARG hasn't been supplied, the command performs several electric +actions: + +\(a) When the auto-newline feature is turned on (indicated by \"/la\" on +the mode line) a newline might be inserted. See the variable +`c-hanging-semi&comma-criteria' for how newline insertion is determined. + +\(b) Any auto-newlines are indented. The original line is also +reindented unless `c-syntactic-indentation' is nil. + +\(c) If auto-newline is turned on, a comma following a brace list or a +semicolon following a defun might be cleaned up, depending on the +settings of `c-cleanup-list'." + (interactive "*P") + (let* (lim literal c-syntactic-context + (here (point)) + ;; shut this up + (c-echo-syntactic-information-p nil)) + + (c-save-buffer-state () + (setq lim (c-most-enclosing-brace (c-parse-state)) + literal (c-in-literal lim))) + + (self-insert-command (prefix-numeric-value arg)) + + (if (and c-electric-flag (not literal) (not arg)) + ;; do all cleanups and newline insertions if c-auto-newline is on. + (if (or (not c-auto-newline) + (not (looking-at "[ \t]*\\\\?$"))) + (when c-syntactic-indentation + (let ((syntax (c-guess-basic-syntax))) + (c-indent-line syntax) + ;; Guard against the C hacker inserting a statement before a + ;; non-compound statement in an if/while/for. + (if (eq (caar syntax) 'substatement) + (save-excursion + (if (eq 0 (forward-line)) + (c-indent-line)))))) + ;; clean ups: list-close-comma or defun-close-semi + (let ((pos (- (point-max) (point)))) + (if (c-save-buffer-state () + (and (or (and + (eq last-command-event ?,) + (memq 'list-close-comma c-cleanup-list)) + (and + (eq last-command-event ?\;) + (memq 'defun-close-semi c-cleanup-list))) + (progn + (forward-char -1) + (c-skip-ws-backward) + (eq (char-before) ?})) + ;; make sure matching open brace isn't in a comment + (not (c-in-literal lim)))) + (delete-region (point) here)) + (goto-char (- (point-max) pos))) + ;; reindent line + (when c-syntactic-indentation + (setq c-syntactic-context (c-guess-basic-syntax)) + (c-indent-line c-syntactic-context)) + ;; check to see if a newline should be added + (let ((criteria c-hanging-semi&comma-criteria) + answer add-newline-p) + (while criteria + (setq answer (funcall (car criteria))) + ;; only nil value means continue checking + (if (not answer) + (setq criteria (cdr criteria)) + (setq criteria nil) + ;; only 'stop specifically says do not add a newline + (setq add-newline-p (not (eq answer 'stop))) + )) + (if add-newline-p + (c-newline-and-indent)) + ))))) + +(defun c-electric-colon (arg) + "Insert a colon. + +If `c-electric-flag' is non-nil, the colon is not inside a literal and a +numeric ARG hasn't been supplied, the command performs several electric +actions: + +\(a) If the auto-newline feature is turned on (indicated by \"/la\" on +the mode line) newlines are inserted before and after the colon based on +the settings in `c-hanging-colons-alist'. + +\(b) Any auto-newlines are indented. The original line is also +reindented unless `c-syntactic-indentation' is nil. + +\(c) If auto-newline is turned on, whitespace between two colons will be +\"cleaned up\" leaving a scope operator, if this action is set in +`c-cleanup-list'." + + (interactive "*P") + (let* ((bod (c-point 'bod)) + (literal (c-save-buffer-state () (c-in-literal bod))) + newlines is-scope-op + ;; shut this up + (c-echo-syntactic-information-p nil)) + (self-insert-command (prefix-numeric-value arg)) + ;; Any electric action? + (if (and c-electric-flag (not literal) (not arg)) + ;; Unless we're at EOL, only re-indentation happens. + (if (not (looking-at "[ \t]*\\\\?$")) + (if c-syntactic-indentation + (indent-according-to-mode)) + + ;; scope-operator clean-up? + (let ((pos (- (point-max) (point))) + (here (point))) + (if (c-save-buffer-state () ; Why do we need this? [ACM, 2003-03-12] + (and c-auto-newline + (memq 'scope-operator c-cleanup-list) + (eq (char-before) ?:) + (progn + (forward-char -1) + (c-skip-ws-backward) + (eq (char-before) ?:)) + (not (c-in-literal)) + (not (eq (char-after (- (point) 2)) ?:)))) + (progn + (delete-region (point) (1- here)) + (setq is-scope-op t))) + (goto-char (- (point-max) pos))) + + ;; indent the current line if it's done syntactically. + (if c-syntactic-indentation + ;; Cannot use the same syntax analysis as we find below, + ;; since that's made with c-syntactic-indentation-in-macros + ;; always set to t. + (indent-according-to-mode)) + + ;; Calculate where, if anywhere, we want newlines. + (c-save-buffer-state + ((c-syntactic-indentation-in-macros t) + (c-auto-newline-analysis t) + ;; Turn on syntactic macro analysis to help with auto newlines + ;; only. + (syntax (c-guess-basic-syntax)) + (elem syntax)) + ;; Translate substatement-label to label for this operation. + (while elem + (if (eq (car (car elem)) 'substatement-label) + (setcar (car elem) 'label)) + (setq elem (cdr elem))) + ;; some language elements can only be determined by checking + ;; the following line. Lets first look for ones that can be + ;; found when looking on the line with the colon + (setq newlines + (and c-auto-newline + (or (c-lookup-lists '(case-label label access-label) + syntax c-hanging-colons-alist) + (c-lookup-lists '(member-init-intro inher-intro) + (progn + (insert ?\n) + (unwind-protect + (c-guess-basic-syntax) + (delete-char -1))) + c-hanging-colons-alist))))) + ;; does a newline go before the colon? Watch out for already + ;; non-hung colons. However, we don't unhang them because that + ;; would be a cleanup (and anti-social). + (if (and (memq 'before newlines) + (not is-scope-op) + (save-excursion + (skip-chars-backward ": \t") + (not (bolp)))) + (let ((pos (- (point-max) (point)))) + (forward-char -1) + (c-newline-and-indent) + (goto-char (- (point-max) pos)))) + ;; does a newline go after the colon? + (if (and (memq 'after (cdr-safe newlines)) + (not is-scope-op)) + (c-newline-and-indent)) + )))) + +(defun c-electric-lt-gt (arg) + "Insert a \"<\" or \">\" character. +If the current language uses angle bracket parens (e.g. template +arguments in C++), try to find out if the inserted character is a +paren and give it paren syntax if appropriate. + +If `c-electric-flag' and `c-syntactic-indentation' are both non-nil, the +line will be reindented if the inserted character is a paren or if it +finishes a C++ style stream operator in C++ mode. Exceptions are when a +numeric argument is supplied, or the point is inside a literal." + + (interactive "*P") + (let ((c-echo-syntactic-information-p nil) + final-pos found-delim case-fold-search) + + (self-insert-command (prefix-numeric-value arg)) + (setq final-pos (point)) + +;;;; 2010-01-31: There used to be code here to put a syntax-table text +;;;; property on the new < or > and its mate (if any) when they are template +;;;; parens. This is now done in an after-change function. + + ;; Indent the line if appropriate. + (when (and c-electric-flag c-syntactic-indentation c-recognize-<>-arglists) + (setq found-delim + (if (eq last-command-event ?<) + ;; If a <, basically see if it's got "template" before it ..... + (or (and (progn + (backward-char) + (= (point) + (progn (c-beginning-of-current-token) (point)))) + (progn + (c-backward-token-2) + (looking-at c-opt-<>-sexp-key))) + ;; ..... or is a C++ << operator. + (and (c-major-mode-is 'c++-mode) + (progn + (goto-char (1- final-pos)) + (c-beginning-of-current-token) + (looking-at "<<")) + (>= (match-end 0) final-pos))) + + ;; It's a >. Either a C++ >> operator. ...... + (or (and (c-major-mode-is 'c++-mode) + (progn + (goto-char (1- final-pos)) + (c-beginning-of-current-token) + (looking-at ">>")) + (>= (match-end 0) final-pos)) + ;; ...., or search back for a < which isn't already marked as an + ;; opening template delimiter. + (save-restriction + (widen) + ;; Narrow to avoid `c-forward-<>-arglist' below searching past + ;; our position. + (narrow-to-region (point-min) final-pos) + (goto-char final-pos) + (while + (and + (progn + (c-syntactic-skip-backward "^<;}" nil t) + (eq (char-before) ?<)) + (progn + (backward-char) + (looking-at "\\s\(")))) + (and (eq (char-after) ?<) + (not (looking-at "\\s\(")) + (progn (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward)) + (or (looking-at c-opt-<>-sexp-key) + (not (looking-at c-keywords-regexp))))))))) + + (goto-char final-pos) + (when found-delim + (indent-according-to-mode) + (when (and (eq (char-before) ?>) + (not executing-kbd-macro) + blink-paren-function) + ;; Note: Most paren blink functions, such as the standard + ;; `blink-matching-open', currently doesn't handle paren chars + ;; marked with text properties very well. Maybe we should avoid + ;; this call for the time being? + (funcall blink-paren-function))))) + +(defun c-electric-paren (arg) + "Insert a parenthesis. + +If `c-syntactic-indentation' and `c-electric-flag' are both non-nil, the +line is reindented unless a numeric ARG is supplied, or the parenthesis +is inserted inside a literal. + +Whitespace between a function name and the parenthesis may get added or +removed; see the variable `c-cleanup-list'. + +Also, if `c-electric-flag' and `c-auto-newline' are both non-nil, some +newline cleanups are done if appropriate; see the variable `c-cleanup-list'." + (interactive "*P") + (let ((literal (c-save-buffer-state () (c-in-literal))) + ;; shut this up + (c-echo-syntactic-information-p nil) + case-fold-search) + (self-insert-command (prefix-numeric-value arg)) + + (if (and (not arg) (not literal)) + (let* ( ;; We want to inhibit blinking the paren since this will + ;; be most disruptive. We'll blink it ourselves + ;; afterwards. + (old-blink-paren blink-paren-function) + blink-paren-function) + (if (and c-syntactic-indentation c-electric-flag) + (indent-according-to-mode)) + + ;; If we're at EOL, check for new-line clean-ups. + (when (and c-electric-flag c-auto-newline + (looking-at "[ \t]*\\\\?$")) + + ;; clean up brace-elseif-brace + (when + (and (memq 'brace-elseif-brace c-cleanup-list) + (eq last-command-event ?\() + (re-search-backward + (concat "}" + "\\([ \t\n]\\|\\\\\n\\)*" + "else" + "\\([ \t\n]\\|\\\\\n\\)+" + "if" + "\\([ \t\n]\\|\\\\\n\\)*" + "(" + "\\=") + nil t) + (not (c-save-buffer-state () (c-in-literal)))) + (delete-region (match-beginning 0) (match-end 0)) + (insert-and-inherit "} else if (")) + + ;; clean up brace-catch-brace + (when + (and (memq 'brace-catch-brace c-cleanup-list) + (eq last-command-event ?\() + (re-search-backward + (concat "}" + "\\([ \t\n]\\|\\\\\n\\)*" + "catch" + "\\([ \t\n]\\|\\\\\n\\)*" + "(" + "\\=") + nil t) + (not (c-save-buffer-state () (c-in-literal)))) + (delete-region (match-beginning 0) (match-end 0)) + (insert-and-inherit "} catch ("))) + + ;; Check for clean-ups at function calls. These two DON'T need + ;; `c-electric-flag' or `c-syntactic-indentation' set. + ;; Point is currently just after the inserted paren. + (let (beg (end (1- (point)))) + (cond + + ;; space-before-funcall clean-up? + ((and (memq 'space-before-funcall c-cleanup-list) + (eq last-command-event ?\() + (save-excursion + (backward-char) + (skip-chars-backward " \t") + (setq beg (point)) + (and (c-save-buffer-state () (c-on-identifier)) + ;; Don't add a space into #define FOO().... + (not (and (c-beginning-of-macro) + (c-forward-over-cpp-define-id) + (eq (point) beg)))))) + (save-excursion + (delete-region beg end) + (goto-char beg) + (insert ?\ ))) + + ;; compact-empty-funcall clean-up? + ((c-save-buffer-state () + (and (memq 'compact-empty-funcall c-cleanup-list) + (eq last-command-event ?\)) + (save-excursion + (c-safe (backward-char 2)) + (when (looking-at "()") + (setq end (point)) + (skip-chars-backward " \t") + (setq beg (point)) + (c-on-identifier))))) + (delete-region beg end)))) + (and (eq last-input-event ?\)) + (not executing-kbd-macro) + old-blink-paren + (funcall old-blink-paren)))))) + +(defun c-electric-continued-statement () + "Reindent the current line if appropriate. + +This function is used to reindent the line after a keyword which +continues an earlier statement is typed, e.g. an \"else\" or the +\"while\" in a do-while block. + +The line is reindented if there is nothing but whitespace before the +keyword on the line, the keyword is not inserted inside a literal, and +`c-electric-flag' and `c-syntactic-indentation' are both non-nil." + (let (;; shut this up + (c-echo-syntactic-information-p nil)) + (when (c-save-buffer-state () + (and c-electric-flag + c-syntactic-indentation + (not (eq last-command-event ?_)) + (= (save-excursion + (skip-syntax-backward "w") + (point)) + (c-point 'boi)) + (not (c-in-literal (c-point 'bod))))) + ;; Have to temporarily insert a space so that + ;; c-guess-basic-syntax recognizes the keyword. Follow the + ;; space with a nonspace to avoid messing up any whitespace + ;; sensitive meddling that might be done, e.g. by + ;; `c-backslash-region'. + (insert-and-inherit " x") + (unwind-protect + (indent-according-to-mode) + (delete-char -2))))) + + +;; "nomenclature" functions + c-scope-operator. +(defun c-forward-into-nomenclature (&optional arg) + "Compatibility alias for `c-forward-subword'." + (interactive "p") + (require 'cc-subword) + (c-forward-subword arg)) +(make-obsolete 'c-forward-into-nomenclature 'c-forward-subword nil) + +(defun c-backward-into-nomenclature (&optional arg) + "Compatibility alias for `c-backward-subword'." + (interactive "p") + (require 'cc-subword) + (c-backward-subword arg)) +(make-obsolete 'c-backward-into-nomenclature 'c-backward-subword nil) + +(defun c-scope-operator () + "Insert a double colon scope operator at point. +No indentation or other \"electric\" behavior is performed." + (interactive "*") + (insert-and-inherit "::")) + + +;; Movement (etc.) by defuns. +(defun c-in-function-trailer-p (&optional lim) + ;; Return non-nil if point is between the closing brace and the semicolon of + ;; a brace construct which needs a semicolon, e.g. within the "variables" + ;; portion of a declaration like "struct foo {...} bar ;". + ;; + ;; Return the position of the main declaration. Otherwise, return nil. + ;; Point is assumed to be at the top level and outside of any macro or + ;; literal. + ;; + ;; If LIM is non-nil, it is the bound on a the backward search for the + ;; beginning of the declaration. + ;; + ;; This function might do hidden buffer changes. + (and c-opt-block-decls-with-vars-key + (save-excursion + (c-syntactic-skip-backward "^;}" lim) + (let ((eo-block (point)) + bod) + (and (eq (char-before) ?\}) + (eq (car (c-beginning-of-decl-1 lim)) 'previous) + (setq bod (point)) + ;; Look for struct or union or ... If we find one, it might + ;; be the return type of a function, or the like. Exclude + ;; this case. + (c-syntactic-re-search-forward + (concat "[;=\(\[{]\\|\\(" + c-opt-block-decls-with-vars-key + "\\)") + eo-block t t t) + (match-beginning 1) ; Is there a "struct" etc., somewhere? + (not (eq (char-before) ?_)) + (c-syntactic-re-search-forward "[;=\(\[{]" eo-block t t t) + (eq (char-before) ?\{) + bod))))) + +(defun c-where-wrt-brace-construct () + ;; Determine where we are with respect to functions (or other brace + ;; constructs, included in the term "function" in the rest of this comment). + ;; Point is assumed to be outside any macro or literal. + ;; This is used by c-\(begining\|end\)-of-defun. + ;; + ;; Return one of these symbols: + ;; at-header : we're at the start of a function's header. + ;; in-header : we're inside a function's header, this extending right + ;; up to the brace. This bit includes any k&r declarations. + ;; in-block : we're inside a function's brace block. + ;; in-trailer : we're in the area between the "}" and ";" of something + ;; like "struct foo {...} bar, baz;". + ;; at-function-end : we're just after the closing brace (or semicolon) that + ;; terminates the function. + ;; outwith-function: we're not at or in any function. Being inside a + ;; non-brace construct also counts as 'outwith-function'. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (let* (kluge-start + decl-result brace-decl-p + (start (point)) + (paren-state (c-parse-state)) + (least-enclosing (c-least-enclosing-brace paren-state))) + + (cond + ((and least-enclosing + (eq (char-after least-enclosing) ?\{)) + 'in-block) + ((c-in-function-trailer-p) + 'in-trailer) + ((and (not least-enclosing) + (consp paren-state) + (consp (car paren-state)) + (eq start (cdar paren-state))) + 'at-function-end) + (t + ;; Find the start of the current declaration. NOTE: If we're in the + ;; variables after a "struct/eval" type block, we don't get to the + ;; real declaration here - we detect and correct for this later. + + ;;If we're in the parameters' parens, move back out of them. + (if least-enclosing (goto-char least-enclosing)) + ;; Kluge so that c-beginning-of-decl-1 won't go back if we're already + ;; at a declaration. + (if (or (and (eolp) (not (eobp))) ; EOL is matched by "\\s>" + (not (c-looking-at-non-alphnumspace))) + (forward-char)) + (setq kluge-start (point)) + (setq decl-result + (car (c-beginning-of-decl-1 + ;; NOTE: If we're in a K&R region, this might be the start + ;; of a parameter declaration, not the actual function. + ;; It might also leave us at a label or "label" like + ;; "private:". + (and least-enclosing ; LIMIT for c-b-of-decl-1 + (c-safe-position least-enclosing paren-state))))) + + ;; Has the declaration we've gone back to got braces? + (or (eq decl-result 'label) + (setq brace-decl-p + (save-excursion + (and (c-syntactic-re-search-forward "[;{]" nil t t) + (or (eq (char-before) ?\{) + (and c-recognize-knr-p + ;; Might have stopped on the + ;; ';' in a K&R argdecl. In + ;; that case the declaration + ;; should contain a block. + (c-in-knr-argdecl))))))) + + (cond + ((or (eq decl-result 'label) ; e.g. "private:" or invalid syntax. + (= (point) kluge-start)) ; might be BOB or unbalanced parens. + 'outwith-function) + ((eq decl-result 'same) + (if brace-decl-p + (if (eq (point) start) + 'at-header + 'in-header) + 'outwith-function)) + ((eq decl-result 'previous) + (if (and (not brace-decl-p) + (c-in-function-trailer-p)) + 'at-function-end + 'outwith-function)) + (t (error + "c-where-wrt-brace-construct: c-beginning-of-decl-1 returned %s" + decl-result)))))))) + +(defun c-backward-to-nth-BOF-{ (n where) + ;; Skip to the opening brace of the Nth function before point. If + ;; point is inside a function, this counts as the first. Point must be + ;; outside any comment/string or macro. + ;; + ;; N must be strictly positive. + ;; WHERE describes the position of point, one of the symbols `at-header', + ;; `in-header', `in-block', `in-trailer', `at-function-end', + ;; `outwith-function' as returned by c-where-wrt-brace-construct. + ;; + ;; If we run out of functions, leave point at BOB. Return zero on success, + ;; otherwise the number of {s still to go. + ;; + ;; This function may do hidden buffer changes + (cond + ;; What we do to go back the first defun depends on where we start. + ((bobp)) + ((eq where 'in-block) + (goto-char (c-least-enclosing-brace (c-parse-state))) + (setq n (1- n))) + ((eq where 'in-header) + (c-syntactic-re-search-forward "{") + (backward-char) + (setq n (1- n))) + ((memq where '(at-header outwith-function at-function-end in-trailer)) + (c-syntactic-skip-backward "^}") + (when (eq (char-before) ?\}) + (backward-sexp) + (setq n (1- n)))) + (t (error "Unknown `where' %s in c-backward-to-nth-EOF-{" where))) + + ;; Each time round the loop, go back to a "{" at the outermost level. + (while (and (> n 0) (not (bobp))) + (c-parse-state) ; This call speeds up the following one + ; by a factor of ~6. Hmmm. 2006/4/5. + (c-syntactic-skip-backward "^}") + (when (eq (char-before) ?\}) + (backward-sexp) + (setq n (1- n)))) + n) + +(defun c-narrow-to-most-enclosing-decl-block (&optional inclusive) + ;; If we are inside a decl-block (in the sense of c-looking-at-decl-block), + ;; i.e. something like namespace{} or extern{}, narrow to the insides of + ;; that block (NOT including the enclosing braces) if INCLUSIVE is nil, + ;; otherwise include the braces. If the closing brace is missing, + ;; (point-max) is used instead. + (let ((paren-state (c-parse-state)) + encl-decl) + (setq encl-decl (and paren-state (c-most-enclosing-decl-block paren-state))) + (if encl-decl + (save-excursion + (narrow-to-region + (if inclusive + (progn (goto-char encl-decl) + (c-beginning-of-decl-1) + (point)) + (1+ encl-decl)) + (progn + (goto-char encl-decl) + (or (c-safe (forward-list) + (if inclusive + (point) + (1- (point)))) + (point-max)))))))) + +(defun c-widen-to-enclosing-decl-scope (paren-state orig-point-min orig-point-max) + ;; Narrow the buffer to the innermost declaration scope (e.g. a class, a + ;; namespace or the "whole buffer") recorded in PAREN-STATE, the bounding + ;; braces NOT being included in the resulting region. On no account may the + ;; final region exceed that bounded by ORIG-POINT-MIN, ORIG-POINT-MAX. + ;; PAREN-STATE is a list of buffer positions in the style of + ;; (c-parse-state), one of which will be that of the desired opening brace, + ;; if there is one. + ;; + ;; Return the position of the enclosing opening brace, or nil + (let (encl-decl) ; putative position of decl-scope's opening brace. + (save-restriction + (narrow-to-region orig-point-min orig-point-max) + (setq encl-decl (and paren-state + (c-most-enclosing-decl-block paren-state)))) + (if encl-decl + (progn + (widen) + (narrow-to-region (1+ encl-decl) + (save-excursion + (goto-char encl-decl) + (or (c-safe (forward-list) + (1- (point))) + orig-point-max))) + encl-decl) + (narrow-to-region orig-point-min orig-point-max) + nil))) + +(eval-and-compile + (defmacro c-while-widening-to-decl-block (condition) + ;; Repeatedly evaluate CONDITION until it returns nil. After each + ;; evaluation, if `c-defun-tactic' is set appropriately, widen to innards + ;; of the next enclosing declaration block (e.g. namespace, class), or the + ;; buffer's original restriction. + ;; + ;; This is a very special purpose macro, which assumes the existence of + ;; several variables. It is for use only in c-beginning-of-defun and + ;; c-end-of-defun. + `(while + (and ,condition + (eq c-defun-tactic 'go-outward) + lim) + (setq paren-state (c-whack-state-after lim paren-state)) + (setq lim (c-widen-to-enclosing-decl-scope + paren-state orig-point-min orig-point-max)) + (setq where 'in-block)))) + +(defun c-beginning-of-defun (&optional arg) + "Move backward to the beginning of a defun. +Every top level declaration that contains a brace paren block is +considered to be a defun. + +With a positive argument, move backward that many defuns. A negative +argument -N means move forward to the Nth following beginning. Return +t unless search stops due to beginning or end of buffer. + +Unlike the built-in `beginning-of-defun' this tries to be smarter +about finding the char with open-parenthesis syntax that starts the +defun." + + (interactive "p") + (or arg (setq arg 1)) + + (c-save-buffer-state + (beginning-of-defun-function end-of-defun-function + (start (point)) + (paren-state (copy-tree (c-parse-state))) ; This must not share list + ; structure with other users of c-state-cache. + (orig-point-min (point-min)) (orig-point-max (point-max)) + lim ; Position of { which has been widened to. + where pos case-fold-search) + + (save-restriction + (if (eq c-defun-tactic 'go-outward) + (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace. + paren-state orig-point-min orig-point-max))) + + ;; Move back out of any macro/comment/string we happen to be in. + (c-beginning-of-macro) + (setq pos (c-literal-limits)) + (if pos (goto-char (car pos))) + + (setq where (c-where-wrt-brace-construct)) + + (if (< arg 0) + ;; Move forward to the closing brace of a function. + (progn + (if (memq where '(at-function-end outwith-function)) + (setq arg (1+ arg))) + (if (< arg 0) + (c-while-widening-to-decl-block + (< (setq arg (- (c-forward-to-nth-EOF-} (- arg) where))) 0))) + ;; Move forward to the next opening brace.... + (when (and (= arg 0) + (progn + (c-while-widening-to-decl-block + (not (c-syntactic-re-search-forward "{" nil 'eob))) + (eq (char-before) ?{))) + (backward-char) + ;; ... and backward to the function header. + (c-beginning-of-decl-1) + t)) + + ;; Move backward to the opening brace of a function, making successively + ;; larger portions of the buffer visible as necessary. + (when (> arg 0) + (c-while-widening-to-decl-block + (> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0))) + + (when (eq arg 0) + ;; Go backward to this function's header. + (c-beginning-of-decl-1) + + (setq pos (point)) + ;; We're now there, modulo comments and whitespace. + ;; Try to be line oriented; position point at the closest + ;; preceding boi that isn't inside a comment, but if we hit + ;; the previous declaration then we use the current point + ;; instead. + (while (and (/= (point) (c-point 'boi)) + (c-backward-single-comment))) + (if (/= (point) (c-point 'boi)) + (goto-char pos))) + + (c-keep-region-active) + (= arg 0))))) + +(defun c-forward-to-nth-EOF-} (n where) + ;; Skip to the closing brace of the Nth function after point. If + ;; point is inside a function, this counts as the first. Point must be + ;; outside any comment/string or macro. + ;; + ;; N must be strictly positive. + ;; WHERE describes the position of point, one of the symbols `at-header', + ;; `in-header', `in-block', `in-trailer', `at-function-end', + ;; `outwith-function' as returned by c-where-wrt-brace-construct. + ;; + ;; If we run out of functions, leave point at EOB. Return zero on success, + ;; otherwise the number of }s still to go. + ;; + ;; This function may do hidden buffer changes. + + (cond + ;; What we do to go forward over the first defun depends on where we + ;; start. We go to the closing brace of that defun, even when we go + ;; backwards to it (in a "struct foo {...} bar ;"). + ((eobp)) + ((eq where 'in-block) + (goto-char (c-least-enclosing-brace (c-parse-state))) + (forward-sexp) + (setq n (1- n))) + ((eq where 'in-trailer) + (c-syntactic-skip-backward "^}") + (setq n (1- n))) + ((memq where '(at-function-end outwith-function at-header in-header)) + (when (c-syntactic-re-search-forward "{" nil 'eob) + (backward-char) + (forward-sexp) + (setq n (1- n)))) + (t (error "c-forward-to-nth-EOF-}: `where' is %s" where))) + + ;; Each time round the loop, go forward to a "}" at the outermost level. + (while (and (> n 0) (not (eobp))) + ;(c-parse-state) ; This call speeds up the following one by a factor + ; of ~6. Hmmm. 2006/4/5. + (when (c-syntactic-re-search-forward "{" nil 'eob) + (backward-char) + (forward-sexp)) + (setq n (1- n))) + n) + +(defun c-end-of-defun (&optional arg) + "Move forward to the end of a top level declaration. +With argument, do it that many times. Negative argument -N means move +back to Nth preceding end. Returns t unless search stops due to +beginning or end of buffer. + +An end of a defun occurs right after the close-parenthesis that matches +the open-parenthesis that starts a defun; see `beginning-of-defun'." + (interactive "p") + (or arg (setq arg 1)) + + (c-save-buffer-state + (beginning-of-defun-function end-of-defun-function + (start (point)) + (paren-state (copy-tree (c-parse-state))) ; This must not share list + ; structure with other users of c-state-cache. + (orig-point-min (point-min)) (orig-point-max (point-max)) + lim + where pos case-fold-search) + + (save-restriction + (if (eq c-defun-tactic 'go-outward) + (setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace + paren-state orig-point-min orig-point-max))) + + ;; Move back out of any macro/comment/string we happen to be in. + (c-beginning-of-macro) + (setq pos (c-literal-limits)) + (if pos (goto-char (car pos))) + + (setq where (c-where-wrt-brace-construct)) + + (if (< arg 0) + ;; Move backwards to the } of a function + (progn + (if (memq where '(at-header outwith-function)) + (setq arg (1+ arg))) + (if (< arg 0) + (c-while-widening-to-decl-block + (< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0))) + (if (= arg 0) + (c-while-widening-to-decl-block + (progn (c-syntactic-skip-backward "^}") + (not (eq (char-before) ?})))))) + + ;; Move forward to the } of a function + (if (> arg 0) + (c-while-widening-to-decl-block + (> (setq arg (c-forward-to-nth-EOF-} arg where)) 0)))) + + ;; Do we need to move forward from the brace to the semicolon? + (when (eq arg 0) + (if (c-in-function-trailer-p) ; after "}" of struct/enum, etc. + (c-syntactic-re-search-forward ";")) + + (setq pos (point)) + ;; We're there now, modulo comments and whitespace. + ;; Try to be line oriented; position point after the next + ;; newline that isn't inside a comment, but if we hit the + ;; next declaration then we use the current point instead. + (while (and (not (bolp)) + (not (looking-at "\\s *$")) + (c-forward-single-comment))) + (cond ((bolp)) + ((looking-at "\\s *$") + (forward-line 1)) + (t + (goto-char pos)))) + + (c-keep-region-active) + (= arg 0)))) + +(defun c-defun-name () + "Return the name of the current defun, or NIL if there isn't one. +\"Defun\" here means a function, or other top level construct +with a brace block." + (interactive) + (c-save-buffer-state + (beginning-of-defun-function end-of-defun-function + where pos name-end case-fold-search) + + (save-restriction + (widen) + (save-excursion + ;; Move back out of any macro/comment/string we happen to be in. + (c-beginning-of-macro) + (setq pos (c-literal-limits)) + (if pos (goto-char (car pos))) + + (setq where (c-where-wrt-brace-construct)) + + ;; Move to the beginning of the current defun, if any, if we're not + ;; already there. + (if (eq where 'outwith-function) + nil + (unless (eq where 'at-header) + (c-backward-to-nth-BOF-{ 1 where) + (c-beginning-of-decl-1)) + + ;; Pick out the defun name, according to the type of defun. + (cond + ;; struct, union, enum, or similar: + ((and (looking-at c-type-prefix-key) + (progn (c-forward-token-2 2) ; over "struct foo " + (or (eq (char-after) ?\{) + (looking-at c-symbol-key)))) ; "struct foo bar ..." + (save-match-data (c-forward-token-2)) + (when (eq (char-after) ?\{) + (c-backward-token-2) + (looking-at c-symbol-key)) + (match-string-no-properties 0)) + + ((looking-at "DEFUN\\s-*(") ;"DEFUN\\_>") think of XEmacs! + ;; DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory, ...) ==> Ffile_name_directory + ;; DEFUN(POSIX::STREAM-LOCK, stream lockp &key BLOCK SHARED START LENGTH) ==> POSIX::STREAM-LOCK + (down-list 1) + (c-forward-syntactic-ws) + (when (eq (char-after) ?\") + (forward-sexp 1) + (c-forward-token-2)) ; over the comma and following WS. + (buffer-substring-no-properties + (point) + (progn + (c-forward-token-2) + (c-backward-syntactic-ws) + (point)))) + + (t + ;; Normal function or initializer. + (when (c-syntactic-re-search-forward "[{(]" nil t) + (backward-char) + (c-backward-syntactic-ws) + (when (eq (char-before) ?\=) ; struct foo bar = {0, 0} ; + (c-backward-token-2) + (c-backward-syntactic-ws)) + (setq name-end (point)) + (c-backward-token-2) + (buffer-substring-no-properties (point) name-end))))))))) + +(defun c-declaration-limits (near) + ;; Return a cons of the beginning and end positions of the current + ;; top level declaration or macro. If point is not inside any then + ;; nil is returned, unless NEAR is non-nil in which case the closest + ;; following one is chosen instead (if there is any). The end + ;; position is at the next line, providing there is one before the + ;; declaration. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (save-restriction + (when (eq c-defun-tactic 'go-outward) + (c-narrow-to-most-enclosing-decl-block t) ; e.g. class, namespace + (or (save-restriction + (c-narrow-to-most-enclosing-decl-block nil) + + ;; Note: Some code duplication in `c-beginning-of-defun' and + ;; `c-end-of-defun'. + (catch 'exit + (let ((start (point)) + (paren-state (c-parse-state)) + lim pos end-pos) + (unless (c-safe + (goto-char (c-least-enclosing-brace paren-state)) + ;; If we moved to the outermost enclosing paren + ;; then we can use c-safe-position to set the + ;; limit. Can't do that otherwise since the + ;; earlier paren pair on paren-state might very + ;; well be part of the declaration we should go + ;; to. + (setq lim (c-safe-position (point) paren-state)) + t) + ;; At top level. Make sure we aren't inside a literal. + (setq pos (c-literal-limits + (c-safe-position (point) paren-state))) + (if pos (goto-char (car pos)))) + + (when (c-beginning-of-macro) + (throw 'exit + (cons (point) + (save-excursion + (c-end-of-macro) + (forward-line 1) + (point))))) + + (setq pos (point)) + (when (or (eq (car (c-beginning-of-decl-1 lim)) 'previous) + (= pos (point))) + ;; We moved back over the previous defun. Skip to the next + ;; one. Not using c-forward-syntactic-ws here since we + ;; should not skip a macro. We can also be directly after + ;; the block in a `c-opt-block-decls-with-vars-key' + ;; declaration, but then we won't move significantly far + ;; here. + (goto-char pos) + (c-forward-comments) + + (when (and near (c-beginning-of-macro)) + (throw 'exit + (cons (point) + (save-excursion + (c-end-of-macro) + (forward-line 1) + (point)))))) + + (if (eobp) (throw 'exit nil)) + + ;; Check if `c-beginning-of-decl-1' put us after the block in a + ;; declaration that doesn't end there. We're searching back and + ;; forth over the block here, which can be expensive. + (setq pos (point)) + (if (and c-opt-block-decls-with-vars-key + (progn + (c-backward-syntactic-ws) + (eq (char-before) ?})) + (eq (car (c-beginning-of-decl-1)) + 'previous) + (save-excursion + (c-end-of-decl-1) + (and (> (point) pos) + (setq end-pos (point))))) + nil + (goto-char pos)) + + (if (and (not near) (> (point) start)) + nil + + ;; Try to be line oriented; position the limits at the + ;; closest preceding boi, and after the next newline, that + ;; isn't inside a comment, but if we hit a neighboring + ;; declaration then we instead use the exact declaration + ;; limit in that direction. + (cons (progn + (setq pos (point)) + (while (and (/= (point) (c-point 'boi)) + (c-backward-single-comment))) + (if (/= (point) (c-point 'boi)) + pos + (point))) + (progn + (if end-pos + (goto-char end-pos) + (c-end-of-decl-1)) + (setq pos (point)) + (while (and (not (bolp)) + (not (looking-at "\\s *$")) + (c-forward-single-comment))) + (cond ((bolp) + (point)) + ((looking-at "\\s *$") + (forward-line 1) + (point)) + (t + pos)))))))) + (and (not near) + (goto-char (point-min)) + (c-forward-decl-or-cast-1 -1 nil nil) + (eq (char-after) ?\{) + (cons (point-min) (point-max)))))))) + +(defun c-mark-function () + "Put mark at end of the current top-level declaration or macro, point at beginning. +If point is not inside any then the closest following one is +chosen. Each successive call of this command extends the marked +region by one function. + +A mark is left where the command started. + +As opposed to \\[c-beginning-of-defun] and \\[c-end-of-defun], this +function does not require the declaration to contain a brace block." + ;; Middle sentence of doc-string was: A mark is left where the command + ;; started, unless the region is already active \(in Transient Mark mode). + ;; FIXME!!! for transient-mark/zemacs sometime. (2012-03-08.) + (interactive) + + (let (decl-limits case-fold-search) + (c-save-buffer-state nil + ;; We try to be line oriented, unless there are several + ;; declarations on the same line. + (if (looking-at c-syntactic-eol) + (c-backward-token-2 1 nil (c-point 'bol))) + (setq decl-limits (c-declaration-limits t))) + + (if (not decl-limits) + (error "Cannot find any declaration") + (let* ((extend-region-p + (and (eq this-command 'c-mark-function) + (eq last-command 'c-mark-function))) + (push-mark-p (and (eq this-command 'c-mark-function) + (not extend-region-p) + ;; (not (and transient-mark-mode mark-active)) + ;; FIXME!!!, sometime (2012-03-08.) + ))) + (if push-mark-p (push-mark (point))) + (if extend-region-p + (progn + (exchange-point-and-mark) + (setq decl-limits (c-declaration-limits t)) + (when (not decl-limits) + (exchange-point-and-mark) + (error "Cannot find any declaration")) + (goto-char (cdr decl-limits)) + (exchange-point-and-mark)) + (goto-char (car decl-limits)) + (push-mark (cdr decl-limits) nil t)))))) + +(defun c-cpp-define-name () + "Return the name of the current CPP macro, or NIL if we're not in one." + (interactive) + (let (case-fold-search) + (save-excursion + (and c-opt-cpp-macro-define-start + (c-beginning-of-macro) + (looking-at c-opt-cpp-macro-define-start) + (match-string-no-properties 1))))) + + +;; Movement by statements. +(defun c-in-comment-line-prefix-p () + ;; Point is within a comment. Is it also within a comment-prefix? + ;; Space at BOL which precedes a comment-prefix counts as part of it. + ;; + ;; This function might do hidden buffer changes. + (let ((here (point))) + (save-excursion + (beginning-of-line) + (skip-chars-forward " \t") + (and (looking-at c-current-comment-prefix) + (/= (match-beginning 0) (match-end 0)) + (< here (match-end 0)))))) + +(defun c-narrow-to-comment-innards (range) + ;; Narrow to the "inside" of the comment (block) defined by range, as + ;; follows: + ;; + ;; A c-style block comment has its opening "/*" and its closing "*/" (if + ;; present) removed. A c++-style line comment retains its opening "//" but + ;; has any final NL removed. If POINT is currently outwith these innards, + ;; move it to the appropriate boundary. + ;; + ;; This narrowing simplifies the sentence movement functions, since it + ;; eliminates awkward things at the boundaries of the comment (block). + ;; + ;; This function might do hidden buffer changes. + (let* ((lit-type (c-literal-type range)) + (beg (if (eq lit-type 'c) (+ (car range) 2) (car range))) + (end (if (eq lit-type 'c) + (if (and (eq (char-before (cdr range)) ?/) + (eq (char-before (1- (cdr range))) ?*)) + (- (cdr range) 2) + (point-max)) + (if (eq (cdr range) (point-max)) + (point-max) + (- (cdr range) 1))))) + (if (> (point) end) + (goto-char end)) ; This would be done automatically by ... + (if (< (point) beg) + (goto-char beg)) ; ... narrow-to-region but is not documented. + (narrow-to-region beg end))) + +(defun c-beginning-of-sentence-in-comment (range) + ;; Move backwards to the "beginning of a sentence" within the comment + ;; defined by RANGE, a cons of its starting and ending positions. If we + ;; find a BOS, return NIL. Otherwise, move point to just before the start + ;; of the comment and return T. + ;; + ;; The BOS is either text which follows a regexp match of sentence-end, + ;; or text which is a beginning of "paragraph". + ;; Comment-prefixes are treated like WS when calculating BOSes or BOPs. + ;; + ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. + ;; It is not a general function, but is intended only for calling from + ;; c-move-over-sentence. Not all preconditions have been explicitly stated. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let ((start-point (point))) + (save-restriction + (c-narrow-to-comment-innards range) ; This may move point back. + (let* ((here (point)) + last + (here-filler ; matches WS and comment-prefices at point. + (concat "\\=\\(^[ \t]*\\(" c-current-comment-prefix "\\)" + "\\|[ \t\n\r\f]\\)*")) + (prefix-at-bol-here ; matches WS and prefix at BOL, just before point + (concat "^[ \t]*\\(" c-current-comment-prefix "\\)[ \t\n\r\f]*\\=")) + ;; First, find the previous paragraph start, if any. + (par-beg ; point where non-WS/non-prefix text of paragraph starts. + (save-excursion + (forward-paragraph -1) ; uses cc-mode values of + ; paragraph-\(start\|separate\) + (if (> (re-search-forward here-filler nil t) here) + (goto-char here)) + (when (>= (point) here) + (forward-paragraph -2) + (if (> (re-search-forward here-filler nil t) here) + (goto-char here))) + (point)))) + + ;; Now seek successively earlier sentence ends between PAR-BEG and + ;; HERE, until the "start of sentence" following it is earlier than + ;; HERE, or we hit PAR-BEG. Beware of comment prefices! + (while (and (re-search-backward (c-sentence-end) par-beg 'limit) + (setq last (point)) + (goto-char (match-end 0)) ; tentative beginning of sentence + (or (>= (point) here) + (and (not (bolp)) ; Found a non-blank comment-prefix? + (save-excursion + (if (re-search-backward prefix-at-bol-here nil t) + (/= (match-beginning 1) (match-end 1))))) + (progn ; Skip the crud to find a real b-o-s. + (if (c-in-comment-line-prefix-p) + (beginning-of-line)) + (re-search-forward here-filler) ; always succeeds. + (>= (point) here)))) + (goto-char last)) + (re-search-forward here-filler))) + + (if (< (point) start-point) + nil + (goto-char (car range)) + t)))) + +(defun c-end-of-sentence-in-comment (range) + ;; Move forward to the "end of a sentence" within the comment defined by + ;; RANGE, a cons of its starting and ending positions (enclosing the opening + ;; comment delimiter and the terminating */ or newline). If we find an EOS, + ;; return NIL. Otherwise, move point to just after the end of the comment + ;; and return T. + ;; + ;; The EOS is just after the non-WS part of the next match of the regexp + ;; sentence-end. Typically, this is just after one of [.!?]. If there is + ;; no sentence-end match following point, any WS before the end of the + ;; comment will count as EOS, providing we're not already in it. + ;; + ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. + ;; It is not a general function, but is intended only for calling from + ;; c-move-over-sentence. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let ((start-point (point)) + ;; (lit-type (c-literal-type range)) ; Commented out, 2005/11/23, ACM + ) + (save-restriction + (c-narrow-to-comment-innards range) ; This might move point forwards. + (let* ((here (point)) + (par-end ; EOL position of last text in current/next paragraph. + (save-excursion + ;; The cc-mode values of paragraph-\(start\|separate\), set + ;; in c-setup-paragraph-variables, are used in the + ;; following. + (forward-paragraph 1) + (if (eq (preceding-char) ?\n) (forward-char -1)) + (when (<= (point) here) ; can happen, e.g., when HERE is at EOL. + (goto-char here) + (forward-paragraph 2) + (if (eq (preceding-char) ?\n) (forward-char -1))) + (point))) + + last + (prefix-at-bol-here + (concat "^[ \t]*\\(" c-current-comment-prefix "\\)\\="))) + ;; Go forward one "comment-prefix which looks like sentence-end" + ;; each time round the following: + (while (and (re-search-forward (c-sentence-end) par-end 'limit) + (progn + (setq last (point)) + (skip-chars-backward " \t\n") + (or (and (not (bolp)) + (re-search-backward prefix-at-bol-here nil t) + (/= (match-beginning 1) (match-end 1))) + (<= (point) here)))) + (goto-char last)) + + ;; Take special action if we're up against the end of a comment (of + ;; either sort): Leave point just after the last non-ws text. + (if (eq (point) (point-max)) + (while (or (/= (skip-chars-backward " \t\n") 0) + (and (re-search-backward prefix-at-bol-here nil t) + (/= (match-beginning 1) (match-end 1)))))))) + + (if (> (point) start-point) + nil + (goto-char (cdr range)) + t)))) + +(defun c-beginning-of-sentence-in-string (range) + ;; Move backwards to the "beginning of a sentence" within the string defined + ;; by RANGE, a cons of its starting and ending positions (enclosing the + ;; string quotes). If we find a BOS, return NIL. Otherwise, move point to + ;; just before the start of the string and return T. + ;; + ;; The BOS is either the text which follows a regexp match of sentence-end + ;; or text which is a beginning of "paragraph". For the purposes of + ;; determining paragraph boundaries, escaped newlines are treated as + ;; ordinary newlines. + ;; + ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. + ;; It is not a general function, but is intended only for calling from + ;; c-move-over-sentence. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let* ((here (point)) last + (end (1- (cdr range))) + (here-filler ; matches WS and escaped newlines at point. + "\\=\\([ \t\n\r\f]\\|\\\\[\n\r]\\)*") + ;; Enhance paragraph-start and paragraph-separate also to recognise + ;; blank lines terminated by escaped EOLs. IT MAY WELL BE that + ;; these values should be customizable user options, or something. + (paragraph-start c-string-par-start) + (paragraph-separate c-string-par-separate) + + (par-beg ; beginning of current (or previous) paragraph. + (save-excursion + (save-restriction + (narrow-to-region (1+ (car range)) end) + (forward-paragraph -1) ; uses above values of + ; paragraph-\(start\|separate\) + (if (> (re-search-forward here-filler nil t) here) + (goto-char here)) + (when (>= (point) here) + (forward-paragraph -2) + (if (> (re-search-forward here-filler nil t) here) + (goto-char here))) + (point))))) + ;; Now see if we can find a sentence end after PAR-BEG. + (while (and (re-search-backward c-sentence-end-with-esc-eol par-beg 'limit) + (setq last (point)) + (goto-char (match-end 0)) + (or (> (point) end) + (progn + (re-search-forward + here-filler end t) ; always succeeds. Use end rather + ; than here, in case point starts + ; beyond the closing quote. + (>= (point) here)))) + (goto-char last)) + (re-search-forward here-filler here t) + (if (< (point) here) + nil + (goto-char (car range)) + t)))) + +(defun c-end-of-sentence-in-string (range) + ;; Move forward to the "end of a sentence" within the string defined by + ;; RANGE, a cons of its starting and ending positions. If we find an EOS, + ;; return NIL. Otherwise, move point to just after the end of the string + ;; and return T. + ;; + ;; The EOS is just after the non-WS part of the next match of the regexp + ;; sentence-end. Typically, this is just after one of [.!?]. If there is + ;; no sentence-end match following point, any WS before the end of the + ;; string will count as EOS, providing we're not already in it. + ;; + ;; This code was adapted from GNU Emacs's forward-sentence in paragraphs.el. + ;; It is not a general function, but is intended only for calling from + ;; c-move-over-sentence. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let* ((here (point)) + last + ;; Enhance paragraph-start and paragraph-separate to recognise + ;; blank lines terminated by escaped EOLs. + (paragraph-start c-string-par-start) + (paragraph-separate c-string-par-separate) + + (par-end ; EOL position of last text in current/next paragraph. + (save-excursion + (save-restriction + (narrow-to-region (car range) (1- (cdr range))) + ;; The above values of paragraph-\(start\|separate\) are used + ;; in the following. + (forward-paragraph 1) + (setq last (point)) + ;; (re-search-backward filler-here nil t) would find an empty + ;; string. Therefore we simulate it by the following: + (while (or (/= (skip-chars-backward " \t\n\r\f") 0) + (re-search-backward "\\\\\\($\\)\\=" nil t))) + (unless (> (point) here) + (goto-char last) + (forward-paragraph 1) + (while (or (/= (skip-chars-backward " \t\n\r\f") 0) + (re-search-backward "\\\\\\($\\)\\=" nil t)))) + (point))))) + ;; Try to go forward a sentence. + (when (re-search-forward c-sentence-end-with-esc-eol par-end 'limit) + (setq last (point)) + (while (or (/= (skip-chars-backward " \t\n") 0) + (re-search-backward "\\\\\\($\\)\\=" nil t)))) + ;; Did we move a sentence, or did we hit the end of the string? + (if (> (point) here) + nil + (goto-char (cdr range)) + t)))) + +(defun c-ascertain-preceding-literal () + ;; Point is not in a literal (i.e. comment or string (include AWK regexp)). + ;; If a literal is the next thing (aside from whitespace) to be found before + ;; point, return a cons of its start.end positions (enclosing the + ;; delimiters). Otherwise return NIL. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (c-collect-line-comments + (let ((here (point)) + pos) + (if (c-backward-single-comment) + (cons (point) (progn (c-forward-single-comment) (point))) + (save-restriction + ;; to prevent `looking-at' seeing a " at point. + (narrow-to-region (point-min) here) + (when + (or + ;; An EOL can act as an "open string" terminator in AWK. + (looking-at c-ws*-string-limit-regexp) + (and (not (bobp)) + (progn (backward-char) + (looking-at c-string-limit-regexp)))) + (goto-char (match-end 0)) ; just after the string terminator. + (setq pos (point)) + (c-safe (c-backward-sexp 1) ; move back over the string. + (cons (point) pos))))))))) + +(defun c-ascertain-following-literal () + ;; Point is not in a literal (i.e. comment or string (include AWK regexp)). + ;; If a literal is the next thing (aside from whitespace) following point, + ;; return a cons of its start.end positions (enclosing the delimiters). + ;; Otherwise return NIL. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (c-collect-line-comments + (let (pos) + (c-skip-ws-forward) + (if (looking-at c-string-limit-regexp) ; string-delimiter. + (cons (point) (or (c-safe (progn (c-forward-sexp 1) (point))) + (point-max))) + (setq pos (point)) + (if (c-forward-single-comment) + (cons pos (point)))))))) + +(defun c-after-statement-terminator-p () ; Should we pass in LIM here? + ;; Does point immediately follow a statement "terminator"? A virtual + ;; semicolon is regarded here as such. So is a an opening brace ;-) + ;; + ;; This function might do hidden buffer changes. + (or (save-excursion + (backward-char) + (and (looking-at "[;{}]") + (not (and c-special-brace-lists ; Pike special brace lists. + (eq (char-after) ?{) + (c-looking-at-special-brace-list))))) + (c-at-vsemi-p) + ;; The following (for macros) is not strict about exactly where we are + ;; wrt white space at the end of the macro. Doesn't seem to matter too + ;; much. ACM 2004/3/29. + (let (eom) + (save-excursion + (if (c-beginning-of-macro) + (setq eom (progn (c-end-of-macro) + (point))))) + (when eom + (save-excursion + (c-forward-comments) + (>= (point) eom)))))) + +(defun c-back-over-illiterals (macro-start) + ;; Move backwards over code which isn't a literal (i.e. comment or string), + ;; stopping before reaching BOB or a literal or the boundary of a + ;; preprocessor statement or the "beginning of a statement". MACRO-START is + ;; the position of the '#' beginning the current preprocessor directive, or + ;; NIL if we're not in such. + ;; + ;; Return a cons (A.B), where + ;; A is NIL if we moved back to a BOS (and know it), T otherwise (we + ;; didn't move, or we hit a literal, or we're not sure about BOS). + ;; B is MACRO-BOUNDARY if we are about to cross the boundary out of or + ;; into a macro, otherwise LITERAL if we've hit a literal, otherwise NIL + ;; + ;; The total collection of returned values is as follows: + ;; (nil . nil): Found a BOS whilst remaining inside the illiterals. + ;; (t . literal): No BOS found: only a comment/string. We _might_ be at + ;; a BOS - the caller must check this. + ;; (nil . macro-boundary): only happens with non-nil macro-start. We've + ;; moved and reached the opening # of the macro. + ;; (t . macro-boundary): Every other circumstance in which we're at a + ;; macro-boundary. We might be at a BOS. + ;; + ;; Point is left either at the beginning-of-statement, or at the last non-ws + ;; code before encountering the literal/BOB or macro-boundary. + ;; + ;; Note that this function moves within either preprocessor commands + ;; (macros) or normal code, but will not cross a boundary between the two, + ;; or between two distinct preprocessor commands. + ;; + ;; Stop before `{' and after `;', `{', `}' and `};' when not followed by `}' + ;; or `)', but on the other side of the syntactic ws. Move by sexps and + ;; move into parens. Also stop before `#' when it's at boi on a line. + ;; + ;; This function might do hidden buffer changes. + (save-match-data + (let ((here (point)) + last) ; marks the position of non-ws code, what'll be BOS if, say, a + ; semicolon precedes it. + (catch 'done + (while t ;; We go back one "token" each iteration of the loop. + (setq last (point)) + (cond + ;; Stop at the token after a comment. + ((c-backward-single-comment) ; Also functions as backwards-ws. + (goto-char last) + (throw 'done '(t . literal))) + + ;; If we've gone back over a LF, we might have moved into or out of + ;; a preprocessor line. + ((and (save-excursion + (beginning-of-line) + (re-search-forward "\\(^\\|[^\\]\\)[\n\r]" last t)) + (if macro-start + (< (point) macro-start) + (c-beginning-of-macro))) + (goto-char last) + ;; Return a car of NIL ONLY if we've hit the opening # of a macro. + (throw 'done (cons (or (eq (point) here) + (not macro-start)) + 'macro-boundary))) + + ;; Have we found a virtual semicolon? If so, stop, unless the next + ;; statement is where we started from. + ((and (c-at-vsemi-p) + (< last here) + (not (memq (char-after last) '(?\) ?})))) ; we've moved back from ) or } + (goto-char last) + (throw 'done '(nil . nil))) + + ;; Hit the beginning of the buffer/region? + ((bobp) + (if (/= here last) + (goto-char last)) + (throw 'done '(nil . nil))) + + ;; Move back a character. + ((progn (backward-char) nil)) + + ;; Stop at "{" (unless it's a PIKE special brace list.) + ((eq (char-after) ?\{) + (if (and c-special-brace-lists + (c-looking-at-special-brace-list)) + (skip-syntax-backward "w_") ; Speedup only. + (if (/= here last) + (goto-char last)) + (throw 'done '(nil . nil)))) + + ;; Have we reached the start of a macro? This always counts as + ;; BOS. (N.B. I don't think (eq (point) here) can ever be true + ;; here. FIXME!!! ACM 2004/3/29) + ((and macro-start (eq (point) macro-start)) + (throw 'done (cons (eq (point) here) 'macro-boundary))) + + ;; Stop at token just after "}" or ";". + ((looking-at "[;}]") + ;; If we've gone back over ;, {, or }, we're done. + (if (or (= here last) + (memq (char-after last) '(?\) ?}))) ; we've moved back from ) or } + (if (and (eq (char-before) ?}) ; If };, treat them as a unit. + (eq (char-after) ?\;)) + (backward-char)) + (goto-char last) ; To the statement starting after the ; or }. + (throw 'done '(nil . nil)))) + + ;; Stop at the token after a string. + ((looking-at c-string-limit-regexp) ; Just gone back over a string terminator? + (goto-char last) + (throw 'done '(t . literal))) + + ;; Nothing special: go back word characters. + (t (skip-syntax-backward "w_")) ; Speedup only. + )))))) + +(defun c-forward-over-illiterals (macro-end allow-early-stop) + ;; Move forwards over code, stopping before reaching EOB or a literal + ;; (i.e. a comment/string) or the boundary of a preprocessor statement or + ;; the "end of a statement". MACRO-END is the position of the EOL/EOB which + ;; terminates the current preprocessor directive, or NIL if we're not in + ;; such. + ;; + ;; ALLOW-EARLY-STOP is non-nil if it is permissible to return without moving + ;; forward at all, should we encounter a `{'. This is an ugly kludge, but + ;; seems unavoidable. Depending on the context this function is called + ;; from, we _sometimes_ need to stop there. Currently (2004/4/3), + ;; ALLOW-EARLY-STOP is applied only to open braces, not to virtual + ;; semicolons, or anything else. + ;; + ;; Return a cons (A.B), where + ;; A is NIL if we moved forward to an EOS, or stay at one (when + ;; ALLOW-EARLY-STOP is set), T otherwise (we hit a literal). + ;; B is 'MACRO-BOUNDARY if we are about to cross the boundary out of or + ;; into a macro, otherwise 'LITERAL if we've hit a literal, otherwise NIL + ;; + ;; Point is left either after the end-of-statement, or at the last non-ws + ;; code before encountering the literal, or the # of the preprocessor + ;; statement, or at EOB [or just after last non-WS stuff??]. + ;; + ;; As a clarification of "after the end-of-statement", if a comment or + ;; whitespace follows a completed AWK statement, that statement is treated + ;; as ending just after the last non-ws character before the comment. + ;; + ;; Note that this function moves within either preprocessor commands + ;; (macros) or normal code, but not both within the same invocation. + ;; + ;; Stop before `{', `}', and `#' when it's at boi on a line, but on the + ;; other side of the syntactic ws, and after `;', `}' and `};'. Only + ;; stop before `{' if at top level or inside braces, though. Move by + ;; sexps and move into parens. Also stop at eol of lines with `#' at + ;; the boi. + ;; + ;; This function might do hidden buffer changes. + (let ((here (point)) + last) + (catch 'done + (while t ;; We go one "token" forward each time round this loop. + (setq last (point)) + + ;; If we've moved forward to a virtual semicolon, we're done. + (if (and (> last here) ; Should we check ALLOW-EARLY-STOP, here? 2004/4/3 + (c-at-vsemi-p)) + (throw 'done '(nil . nil))) + + (c-skip-ws-forward) + (cond + ;; Gone past the end of a macro? + ((and macro-end (> (point) macro-end)) + (goto-char last) + (throw 'done (cons (eq (point) here) 'macro-boundary))) + + ;; About to hit a comment? + ((save-excursion (c-forward-single-comment)) + (goto-char last) + (throw 'done '(t . literal))) + + ;; End of buffer? + ((eobp) + (if (/= here last) + (goto-char last)) + (throw 'done '(nil . nil))) + + ;; If we encounter a '{', stop just after the previous token. + ((and (eq (char-after) ?{) + (not (and c-special-brace-lists + (c-looking-at-special-brace-list))) + (or allow-early-stop (/= here last)) + (save-excursion ; Is this a check that we're NOT at top level? +;;;; NO! This seems to check that (i) EITHER we're at the top level; OR (ii) The next enclosing +;;;; level of bracketing is a '{'. HMM. Doesn't seem to make sense. +;;;; 2003/8/8 This might have something to do with the GCC extension "Statement Expressions", e.g. +;;;; while ({stmt1 ; stmt2 ; exp ;}). This form excludes such Statement Expressions. + (or (not (c-safe (up-list -1) t)) + (= (char-after) ?{)))) + (goto-char last) + (throw 'done '(nil . nil))) + + ;; End of a PIKE special brace list? If so, step over it and continue. + ((and c-special-brace-lists + (eq (char-after) ?}) + (save-excursion + (and (c-safe (up-list -1) t) + (c-looking-at-special-brace-list)))) + (forward-char) + (skip-syntax-forward "w_")) ; Speedup only. + + ;; Have we got a '}' after having moved? If so, stop after the + ;; previous token. + ((and (eq (char-after) ?}) + (/= here last)) + (goto-char last) + (throw 'done '(nil . nil))) + + ;; Stop if we encounter a preprocessor line. Continue if we hit a naked # + ((and c-opt-cpp-prefix + (not macro-end) + (eq (char-after) ?#) + (= (point) (c-point 'boi))) + (if (= (point) here) ; Not a macro, therefore naked #. + (forward-char) + (throw 'done '(t . macro-boundary)))) + + ;; Stop after a ';', '}', or "};" + ((looking-at ";\\|};?") + (goto-char (match-end 0)) + (throw 'done '(nil . nil))) + + ;; Found a string (this subsumes AWK regexps)? + ((looking-at c-string-limit-regexp) + (goto-char last) + (throw 'done '(t . literal))) + + (t + (forward-char) ; Can't fail - we checked (eobp) earlier on. + (skip-syntax-forward "w_") ; Speedup only. + (when (and macro-end (> (point) macro-end)) + (goto-char last) + (throw 'done (cons (eq (point) here) 'macro-boundary)))) + ))))) + +(defun c-one-line-string-p (range) + ;; Is the literal defined by RANGE a string contained in a single line? + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (goto-char (car range)) + (and (looking-at c-string-limit-regexp) + (progn (skip-chars-forward "^\n" (cdr range)) + (eq (point) (cdr range)))))) + +(defun c-beginning-of-statement (&optional count lim sentence-flag) + "Go to the beginning of the innermost C statement. +With prefix arg, go back N - 1 statements. If already at the +beginning of a statement then go to the beginning of the closest +preceding one, moving into nested blocks if necessary (use +\\[backward-sexp] to skip over a block). If within or next to a +comment or multiline string, move by sentences instead of statements. + +When called from a program, this function takes 3 optional args: the +repetition count, a buffer position limit which is the farthest back +to search for the syntactic context, and a flag saying whether to do +sentence motion in or near comments and multiline strings. + +Note that for use in programs, `c-beginning-of-statement-1' is +usually better. It has much better defined semantics than this one, +which is intended for interactive use, and might therefore change to +be more \"DWIM:ey\"." + (interactive (list (prefix-numeric-value current-prefix-arg) + nil t)) + (if (< count 0) + (c-end-of-statement (- count) lim sentence-flag) + (c-save-buffer-state + ((count (or count 1)) + last ; start point for going back ONE chunk. Updated each chunk movement. + (macro-fence + (save-excursion (and (not (bobp)) (c-beginning-of-macro) (point)))) + res ; result from sub-function call + not-bos ; "not beginning-of-statement" + (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL + + ;; Go back one statement at each iteration of the following loop. + (while (and (/= count 0) + (or (not lim) (> (point) lim))) + ;; Go back one "chunk" each time round the following loop, stopping + ;; when we reach a statement boundary, etc. + (setq last (point)) + (while + (cond ; Each arm of this cond returns NIL on reaching a desired + ; statement boundary, non-NIL otherwise. + ((bobp) + (setq count 0) + nil) + + (range ; point is within or approaching a literal. + (cond + ;; Single line string or sentence-flag is null => skip the + ;; entire literal. + ((or (null sentence-flag) + (c-one-line-string-p range)) + (goto-char (car range)) + (setq range (c-ascertain-preceding-literal)) + ;; N.B. The following is essentially testing for an AWK regexp + ;; at BOS: + ;; Was the previous non-ws thing an end of statement? + (save-excursion + (if macro-fence + (c-backward-comments) + (c-backward-syntactic-ws)) + (not (or (bobp) (c-after-statement-terminator-p))))) + + ;; Comment inside a statement or a multi-line string. + (t (when (setq res ; returns non-nil when we go out of the literal + (if (eq (c-literal-type range) 'string) + (c-beginning-of-sentence-in-string range) + (c-beginning-of-sentence-in-comment range))) + (setq range (c-ascertain-preceding-literal))) + res))) + + ;; Non-literal code. + (t (setq res (c-back-over-illiterals macro-fence)) + (setq not-bos ; "not reached beginning-of-statement". + (or (= (point) last) + (memq (char-after) '(?\) ?\})) + (and + (car res) + ;; We're at a tentative BOS. The next form goes + ;; back over WS looking for an end of previous + ;; statement. + (not (save-excursion + (if macro-fence + (c-backward-comments) + (c-backward-syntactic-ws)) + (or (bobp) (c-after-statement-terminator-p))))))) + ;; Are we about to move backwards into or out of a + ;; preprocessor command? If so, locate it's beginning. + (when (eq (cdr res) 'macro-boundary) + (save-excursion + (beginning-of-line) + (setq macro-fence + (and (not (bobp)) + (progn (c-skip-ws-backward) (c-beginning-of-macro)) + (point))))) + ;; Are we about to move backwards into a literal? + (when (memq (cdr res) '(macro-boundary literal)) + (setq range (c-ascertain-preceding-literal))) + not-bos)) + (setq last (point))) + + (if (/= count 0) (setq count (1- count)))) + (c-keep-region-active)))) + +(defun c-end-of-statement (&optional count lim sentence-flag) + "Go to the end of the innermost C statement. +With prefix arg, go forward N - 1 statements. Move forward to the end +of the next statement if already at end, and move into nested blocks +\(use \\[forward-sexp] to skip over a block). If within or next to a +comment or multiline string, move by sentences instead of statements. + +When called from a program, this function takes 3 optional args: the +repetition count, a buffer position limit which is the farthest back +to search for the syntactic context, and a flag saying whether to do +sentence motion in or near comments and multiline strings." + (interactive (list (prefix-numeric-value current-prefix-arg) + nil t)) + (setq count (or count 1)) + (if (< count 0) (c-beginning-of-statement (- count) lim sentence-flag) + + (c-save-buffer-state + (here ; start point for going forward ONE statement. Updated each statement. + (macro-fence + (save-excursion + (and (not (eobp)) (c-beginning-of-macro) + (progn (c-end-of-macro) (point))))) + res + (range (c-collect-line-comments (c-literal-limits lim)))) ; (start.end) of current literal or NIL + + ;; Go back/forward one statement at each iteration of the following loop. + (while (and (/= count 0) + (or (not lim) (< (point) lim))) + (setq here (point)) ; ONLY HERE is HERE updated + + ;; Go forward one "chunk" each time round the following loop, stopping + ;; when we reach a statement boundary, etc. + (while + (cond ; Each arm of this cond returns NIL on reaching a desired + ; statement boundary, non-NIL otherwise. + ((eobp) + (setq count 0) + nil) + + (range ; point is within a literal. + (cond + ;; sentence-flag is null => skip the entire literal. + ;; or a Single line string. + ((or (null sentence-flag) + (c-one-line-string-p range)) + (goto-char (cdr range)) + (setq range (c-ascertain-following-literal)) + ;; Is there a virtual semicolon here (e.g. for AWK)? + (not (c-at-vsemi-p))) + + ;; Comment or multi-line string. + (t (when (setq res ; gets non-nil when we go out of the literal + (if (eq (c-literal-type range) 'string) + (c-end-of-sentence-in-string range) + (c-end-of-sentence-in-comment range))) + (setq range (c-ascertain-following-literal))) + ;; If we've just come forward out of a literal, check for + ;; vsemi. (N.B. AWK can't have a vsemi after a comment, but + ;; some other language may do in the future) + (and res + (not (c-at-vsemi-p)))))) + + ;; Non-literal code. + (t (setq res (c-forward-over-illiterals macro-fence + (> (point) here))) + ;; Are we about to move forward into or out of a + ;; preprocessor command? + (when (eq (cdr res) 'macro-boundary) + (setq macro-fence + (save-excursion + (if macro-fence + (progn + (end-of-line) + (and (not (eobp)) + (progn (c-skip-ws-forward) + (c-beginning-of-macro)) + (progn (c-end-of-macro) + (point)))) + (and (not (eobp)) + (c-beginning-of-macro) + (progn (c-end-of-macro) (point))))))) + ;; Are we about to move forward into a literal? + (when (memq (cdr res) '(macro-boundary literal)) + (setq range (c-ascertain-following-literal))) + (car res)))) + + (if (/= count 0) (setq count (1- count)))) + (c-keep-region-active)))) + + +;; set up electric character functions to work with pending-del, +;; (a.k.a. delsel) mode. All symbols get the t value except +;; the functions which delete, which gets 'supersede. +(mapc + (function + (lambda (sym) + (put sym 'delete-selection t) ; for delsel (Emacs) + (put sym 'pending-delete t))) ; for pending-del (XEmacs) + '(c-electric-pound + c-electric-brace + c-electric-slash + c-electric-star + c-electric-semi&comma + c-electric-lt-gt + c-electric-colon + c-electric-paren)) +(put 'c-electric-delete 'delete-selection 'supersede) ; delsel +(put 'c-electric-delete 'pending-delete 'supersede) ; pending-del +(put 'c-electric-backspace 'delete-selection 'supersede) ; delsel +(put 'c-electric-backspace 'pending-delete 'supersede) ; pending-del +(put 'c-electric-delete-forward 'delete-selection 'supersede) ; delsel +(put 'c-electric-delete-forward 'pending-delete 'supersede) ; pending-del + + +;; Inserting/indenting comments +(defun c-calc-comment-indent (entry) + ;; This function might do hidden buffer changes. + (if (symbolp entry) + (setq entry (or (assq entry c-indent-comment-alist) + (assq 'other c-indent-comment-alist) + '(default . (column . nil))))) + (let ((action (car (cdr entry))) + (value (cdr (cdr entry))) + (col (current-column))) + (cond ((eq action 'space) + (+ col value)) + ((eq action 'column) + (unless value (setq value comment-column)) + (if (bolp) + ;; Do not pad with one space if we're at bol. + value + (max (1+ col) value))) + ((eq action 'align) + (or (save-excursion + (beginning-of-line) + (unless (bobp) + (backward-char) + (let ((lim (c-literal-limits (c-point 'bol) t))) + (when (consp lim) + (goto-char (car lim)) + (when (looking-at "/[/*]") ; FIXME!!! Adapt for AWK! (ACM, 2005/11/18) + ;; Found comment to align with. + (if (bolp) + ;; Do not pad with one space if we're at bol. + 0 + (max (1+ col) (current-column)))))))) + ;; Recurse to handle value as a new spec. + (c-calc-comment-indent (cdr entry))))))) + +(defun c-comment-indent () + "Used by `indent-for-comment' to create and indent comments. +See `c-indent-comment-alist' for a description." + (save-excursion + (end-of-line) + (c-save-buffer-state + ((eot (let ((lim (c-literal-limits (c-point 'bol) t))) + (or (when (consp lim) + (goto-char (car lim)) + (when (looking-at "/[/*]") + (skip-chars-backward " \t") + (point))) + (progn + (skip-chars-backward " \t") + (point))))) + (line-type + (cond ((looking-at "^/[/*]") + 'anchored-comment) + ((progn (beginning-of-line) + (eq (point) eot)) + 'empty-line) + ((progn (back-to-indentation) + (and (eq (char-after) ?}) + (eq (point) (1- eot)))) + 'end-block) + ((and (looking-at "#[ \t]*\\(endif\\|else\\)") + (eq (match-end 0) eot)) + 'cpp-end-block) + (t + 'other))) + case-fold-search) + (if (and (memq line-type '(anchored-comment empty-line)) + c-indent-comments-syntactically-p) + (let ((c-syntactic-context (c-guess-basic-syntax))) + ;; BOGOSITY ALERT: if we're looking at the eol, its + ;; because indent-for-comment hasn't put the comment-start + ;; in the buffer yet. this will screw up the syntactic + ;; analysis so we kludge in the necessary info. Another + ;; kludge is that if we're at the bol, then we really want + ;; to ignore any anchoring as specified by + ;; c-comment-only-line-offset since it doesn't apply here. + (if (eolp) + (c-add-syntax 'comment-intro)) + (let ((c-comment-only-line-offset + (if (consp c-comment-only-line-offset) + c-comment-only-line-offset + (cons c-comment-only-line-offset + c-comment-only-line-offset)))) + (c-get-syntactic-indentation c-syntactic-context))) + (goto-char eot) + (c-calc-comment-indent line-type))))) + + +;; used by outline-minor-mode +(defun c-outline-level () + (let (buffer-invisibility-spec);; This so that `current-column' DTRT + ;; in otherwise-hidden text. + (save-excursion + (skip-chars-forward "\t ") + (current-column)))) + + +;; Movement by CPP conditionals. +(defun c-up-conditional (count) + "Move back to the containing preprocessor conditional, leaving mark behind. +A prefix argument acts as a repeat count. With a negative argument, +move forward to the end of the containing preprocessor conditional. + +\"#elif\" is treated like \"#else\" followed by \"#if\", so the +function stops at them when going backward, but not when going +forward." + (interactive "p") + (let ((new-point (c-scan-conditionals (- count) -1))) + (push-mark) + (goto-char new-point)) + (c-keep-region-active)) + +(defun c-up-conditional-with-else (count) + "Move back to the containing preprocessor conditional, including \"#else\". +Just like `c-up-conditional', except it also stops at \"#else\" +directives." + (interactive "p") + (let ((new-point (c-scan-conditionals (- count) -1 t))) + (push-mark) + (goto-char new-point)) + (c-keep-region-active)) + +(defun c-down-conditional (count) + "Move forward into the next preprocessor conditional, leaving mark behind. +A prefix argument acts as a repeat count. With a negative argument, +move backward into the previous preprocessor conditional. + +\"#elif\" is treated like \"#else\" followed by \"#if\", so the +function stops at them when going forward, but not when going +backward." + (interactive "p") + (let ((new-point (c-scan-conditionals count 1))) + (push-mark) + (goto-char new-point)) + (c-keep-region-active)) + +(defun c-down-conditional-with-else (count) + "Move forward into the next preprocessor conditional, including \"#else\". +Just like `c-down-conditional', except it also stops at \"#else\" +directives." + (interactive "p") + (let ((new-point (c-scan-conditionals count 1 t))) + (push-mark) + (goto-char new-point)) + (c-keep-region-active)) + +(defun c-backward-conditional (count &optional target-depth with-else) + "Move back across a preprocessor conditional, leaving mark behind. +A prefix argument acts as a repeat count. With a negative argument, +move forward across a preprocessor conditional. + +The optional arguments TARGET-DEPTH and WITH-ELSE are historical, +and have the same meanings as in `c-scan-conditionals'. If you +are calling c-forward-conditional from a program, you might want +to call `c-scan-conditionals' directly instead." + (interactive "p") + (let ((new-point (c-scan-conditionals (- count) target-depth with-else))) + (push-mark) + (goto-char new-point)) + (c-keep-region-active)) + +(defun c-forward-conditional (count &optional target-depth with-else) + "Move forward across a preprocessor conditional, leaving mark behind. +A prefix argument acts as a repeat count. With a negative argument, +move backward across a preprocessor conditional. + +If there aren't enough conditionals after \(or before) point, an +error is signalled. + +\"#elif\" is treated like \"#else\" followed by \"#if\", except that +the nesting level isn't changed when tracking subconditionals. + +The optional arguments TARGET-DEPTH and WITH-ELSE are historical, +and have the same meanings as in `c-scan-conditionals'. If you +are calling c-forward-conditional from a program, you might want +to call `c-scan-conditionals' directly instead." + (interactive "p") + (let ((new-point (c-scan-conditionals count target-depth with-else))) + (push-mark) + (goto-char new-point))) + +(defun c-scan-conditionals (count &optional target-depth with-else) + "Scan forward across COUNT preprocessor conditionals. +With a negative argument, scan backward across preprocessor +conditionals. Return the end position. Point is not moved. + +If there aren't enough preprocessor conditionals, throw an error. + +\"#elif\" is treated like \"#else\" followed by \"#if\", except that +the nesting level isn't changed when tracking subconditionals. + +The optional argument TARGET-DEPTH specifies the wanted nesting depth +after each scan. E.g. if TARGET-DEPTH is -1, the end position will be +outside the enclosing conditional. A non-integer non-nil TARGET-DEPTH +counts as -1. + +If the optional argument WITH-ELSE is non-nil, \"#else\" directives +are treated as conditional clause limits. Normally they are ignored." + (let* ((forward (> count 0)) + (increment (if forward -1 1)) + (search-function (if forward 're-search-forward 're-search-backward)) + new case-fold-search) + (unless (integerp target-depth) + (setq target-depth (if target-depth -1 0))) + (save-excursion + (while (/= count 0) + (let ((depth 0) + ;; subdepth is the depth in "uninteresting" subtrees, + ;; i.e. those that takes us farther from the target + ;; depth instead of closer. + (subdepth 0) + found) + (save-excursion + ;; Find the "next" significant line in the proper direction. + (while (and (not found) + ;; Rather than searching for a # sign that + ;; comes at the beginning of a line aside from + ;; whitespace, search first for a string + ;; starting with # sign. Then verify what + ;; precedes it. This is faster on account of + ;; the fastmap feature of the regexp matcher. + (funcall search-function + "#[ \t]*\\(if\\|elif\\|endif\\|else\\)" + nil t)) + (beginning-of-line) + ;; Now verify it is really a preproc line. + (if (looking-at "^[ \t]*#[ \t]*\\(if\\|elif\\|endif\\|else\\)") + (let (dchange (directive (match-string 1))) + (cond ((string= directive "if") + (setq dchange (- increment))) + ((string= directive "endif") + (setq dchange increment)) + ((= subdepth 0) + ;; When we're not in an "uninteresting" + ;; subtree, we might want to act on "elif" + ;; and "else" too. + (if (cond (with-else + ;; Always move toward the target depth. + (setq dchange + (if (> target-depth 0) 1 -1))) + ((string= directive "elif") + (setq dchange (- increment)))) + ;; Ignore the change if it'd take us + ;; into an "uninteresting" subtree. + (if (eq (> dchange 0) (<= target-depth 0)) + (setq dchange nil))))) + (when dchange + (when (or (/= subdepth 0) + (eq (> dchange 0) (<= target-depth 0))) + (setq subdepth (+ subdepth dchange))) + (setq depth (+ depth dchange)) + ;; If we are trying to move across, and we find an + ;; end before we find a beginning, get an error. + (if (and (< depth target-depth) (< dchange 0)) + (error (if forward + "No following conditional at this level" + "No previous conditional at this level")))) + ;; When searching forward, start from next line so + ;; that we don't find the same line again. + (if forward (forward-line 1)) + ;; We found something if we've arrived at the + ;; target depth. + (if (and dchange (= depth target-depth)) + (setq found (point)))) + ;; else + (if forward (forward-line 1))))) + (or found + (error "No containing preprocessor conditional")) + (goto-char (setq new found))) + (setq count (+ count increment)))) + (c-keep-region-active) + new)) + + +;; commands to indent lines, regions, defuns, and expressions +(defun c-indent-command (&optional arg) + "Indent current line as C code, and/or insert some whitespace. + +If `c-tab-always-indent' is t, always just indent the current line. +If nil, indent the current line only if point is at the left margin or +in the line's indentation; otherwise insert some whitespace[*]. If +other than nil or t, then some whitespace[*] is inserted only within +literals (comments and strings), but the line is always reindented. + +If `c-syntactic-indentation' is t, indentation is done according to +the syntactic context. A numeric argument, regardless of its value, +means indent rigidly all the lines of the expression starting after +point so that this line becomes properly indented. The relative +indentation among the lines of the expression is preserved. + +If `c-syntactic-indentation' is nil, the line is just indented one +step according to `c-basic-offset'. In this mode, a numeric argument +indents a number of such steps, positive or negative, and an empty +prefix argument is equivalent to -1. + + [*] The amount and kind of whitespace inserted is controlled by the + variable `c-insert-tab-function', which is called to do the actual + insertion of whitespace. Normally the function in this variable + just inserts a tab character, or the equivalent number of spaces, + depending on the variable `indent-tabs-mode'." + + (interactive "P") + (let ((indent-function + (if c-syntactic-indentation + (symbol-function 'indent-according-to-mode) + (lambda () + (let ((c-macro-start c-macro-start) + (steps (if (equal arg '(4)) + -1 + (prefix-numeric-value arg)))) + (c-shift-line-indentation (* steps c-basic-offset)) + (when (and c-auto-align-backslashes + (save-excursion + (end-of-line) + (eq (char-before) ?\\)) + (c-query-and-set-macro-start)) + ;; Realign the line continuation backslash if inside a macro. + (c-backslash-region (point) (point) nil t))) + )))) + (if (and c-syntactic-indentation arg) + ;; If c-syntactic-indentation and got arg, always indent this + ;; line as C and shift remaining lines of expression the same + ;; amount. + (let ((shift-amt (save-excursion + (back-to-indentation) + (current-column))) + beg end) + (c-indent-line) + (setq shift-amt (- (save-excursion + (back-to-indentation) + (current-column)) + shift-amt)) + (save-excursion + (if (eq c-tab-always-indent t) + (beginning-of-line)) ; FIXME!!! What is this here for? ACM 2005/10/31 + (setq beg (point)) + (c-forward-sexp 1) + (setq end (point)) + (goto-char beg) + (forward-line 1) + (setq beg (point))) + (if (> end beg) + (indent-code-rigidly beg end shift-amt "#"))) + ;; Else use c-tab-always-indent to determine behavior. + (cond + ;; CASE 1: indent when at column zero or in line's indentation, + ;; otherwise insert a tab + ((not c-tab-always-indent) + (if (save-excursion + (skip-chars-backward " \t") + (not (bolp))) + (funcall c-insert-tab-function) + (funcall indent-function))) + ;; CASE 2: just indent the line + ((eq c-tab-always-indent t) + (funcall indent-function)) + ;; CASE 3: if in a literal, insert a tab, but always indent the + ;; line + (t + (if (c-save-buffer-state () (c-in-literal)) + (funcall c-insert-tab-function)) + (funcall indent-function) + ))))) + +(defun c-indent-exp (&optional shutup-p) + "Indent each line in the balanced expression following point syntactically. +If optional SHUTUP-P is non-nil, no errors are signaled if no +balanced expression is found." + (interactive "*P") + (let ((here (point-marker)) + end) + (set-marker-insertion-type here t) + (unwind-protect + (let ((start (save-restriction + ;; Find the closest following open paren that + ;; ends on another line. + (narrow-to-region (point-min) (c-point 'eol)) + (let (beg (end (point))) + (while (and (setq beg (c-down-list-forward end)) + (setq end (c-up-list-forward beg)))) + (and beg + (eq (char-syntax (char-before beg)) ?\() + (1- beg)))))) + ;; sanity check + (if (not start) + (unless shutup-p + (error "Cannot find start of balanced expression to indent")) + (goto-char start) + (setq end (c-safe (scan-sexps (point) 1))) + (if (not end) + (unless shutup-p + (error "Cannot find end of balanced expression to indent")) + (forward-line) + (if (< (point) end) + (c-indent-region (point) end))))) + (goto-char here) + (set-marker here nil)))) + +(defun c-indent-defun () + "Indent the current top-level declaration or macro syntactically. +In the macro case this also has the effect of realigning any line +continuation backslashes, unless `c-auto-align-backslashes' is nil." + (interactive "*") + (let ((here (point-marker)) decl-limits case-fold-search) + (unwind-protect + (progn + (c-save-buffer-state nil + ;; We try to be line oriented, unless there are several + ;; declarations on the same line. + (if (looking-at c-syntactic-eol) + (c-backward-token-2 1 nil (c-point 'bol)) + (c-forward-token-2 0 nil (c-point 'eol))) + (setq decl-limits (c-declaration-limits nil))) + (if decl-limits + (c-indent-region (car decl-limits) + (cdr decl-limits)))) + (goto-char here) + (set-marker here nil)))) + +(defun c-indent-region (start end &optional quiet) + "Indent syntactically every line whose first char is between START +and END inclusive. If the optional argument QUIET is non-nil then no +syntactic errors are reported, even if `c-report-syntactic-errors' is +non-nil." + (save-excursion + (goto-char end) + (skip-chars-backward " \t\n\r\f\v") + (setq end (point)) + (goto-char start) + ;; Advance to first nonblank line. + (beginning-of-line) + (skip-chars-forward " \t\n\r\f\v") + (setq start (point)) + (beginning-of-line) + (setq c-parsing-error + (or (let ((endmark (copy-marker end)) + (c-parsing-error nil) + ;; shut up any echo msgs on indiv lines + (c-echo-syntactic-information-p nil) + (ml-macro-start ; Start pos of multi-line macro. + (and (c-save-buffer-state () + (save-excursion (c-beginning-of-macro))) + (eq (char-before (c-point 'eol)) ?\\) + start)) + (c-fix-backslashes nil) + syntax) + (unwind-protect + (progn + (c-progress-init start end 'c-indent-region) + + (while (and (bolp) ;; One line each time round the loop. + (not (eobp)) + (< (point) endmark)) + ;; update progress + (c-progress-update) + ;; skip empty lines + (unless (or (looking-at "\\s *$") + (and ml-macro-start (looking-at "\\s *\\\\$"))) + ;; Get syntax and indent. + (c-save-buffer-state nil + (setq syntax (c-guess-basic-syntax))) + (c-indent-line syntax t t)) + + (if ml-macro-start + ;; End of current multi-line macro? + (when (and c-auto-align-backslashes + (not (eq (char-before (c-point 'eol)) ?\\))) + ;; Fixup macro backslashes. + (c-backslash-region ml-macro-start (c-point 'bonl) nil) + (setq ml-macro-start nil)) + ;; New multi-line macro? + (if (and (assq 'cpp-macro syntax) + (eq (char-before (c-point 'eol)) ?\\)) + (setq ml-macro-start (point)))) + + (forward-line)) + + (if (and ml-macro-start c-auto-align-backslashes) + (c-backslash-region ml-macro-start (c-point 'bopl) nil t))) + (set-marker endmark nil) + (c-progress-fini 'c-indent-region)) + (c-echo-parsing-error quiet)) + c-parsing-error)))) + +(defun c-fn-region-is-active-p () + ;; Function version of the macro for use in places that aren't + ;; compiled, e.g. in the menus. + (c-region-is-active-p)) + +(defun c-indent-line-or-region () + "When the region is active, indent it syntactically. Otherwise +indent the current line syntactically." + ;; Emacs has a variable called mark-active, XEmacs uses region-active-p + (interactive) + (if (c-region-is-active-p) + (c-indent-region (region-beginning) (region-end)) + (c-indent-line))) + + +;; for progress reporting +(defvar c-progress-info nil) + +(defun c-progress-init (start end context) + (cond + ;; Be silent + ((not c-progress-interval)) + ;; Start the progress update messages. If this Emacs doesn't have + ;; a built-in timer, just be dumb about it. + ((not (fboundp 'current-time)) + (message "Indenting region... (this may take a while)")) + ;; If progress has already been initialized, do nothing. otherwise + ;; initialize the counter with a vector of: + ;; [start end lastsec context] + (c-progress-info) + (t (setq c-progress-info (vector start + (save-excursion + (goto-char end) + (point-marker)) + (nth 1 (current-time)) + context)) + (message "Indenting region...")) + )) + +(defun c-progress-update () + (if (not (and c-progress-info c-progress-interval)) + nil + (let ((now (nth 1 (current-time))) + (start (aref c-progress-info 0)) + (end (aref c-progress-info 1)) + (lastsecs (aref c-progress-info 2))) + ;; should we update? currently, update happens every 2 seconds, + ;; what's the right value? + (if (< c-progress-interval (- now lastsecs)) + (progn + (message "Indenting region... (%d%% complete)" + (/ (* 100 (- (point) start)) (- end start))) + (aset c-progress-info 2 now))) + ))) + +(defun c-progress-fini (context) + (if (not c-progress-interval) + nil + (if (or (eq context (aref c-progress-info 3)) + (eq context t)) + (progn + (set-marker (aref c-progress-info 1) nil) + (setq c-progress-info nil) + (message "Indenting region... done"))))) + + + +;;; This page handles insertion and removal of backslashes for C macros. + +(defun c-backslash-region (from to delete-flag &optional line-mode) + "Insert, align, or delete end-of-line backslashes on the lines in the region. +With no argument, inserts backslashes and aligns existing backslashes. +With an argument, deletes the backslashes. The backslash alignment is +done according to the settings in `c-backslash-column', +`c-backslash-max-column' and `c-auto-align-backslashes'. + +This function does not modify blank lines at the start of the region. +If the region ends at the start of a line and the macro doesn't +continue below it, the backslash (if any) at the end of the previous +line is deleted. + +You can put the region around an entire macro definition and use this +command to conveniently insert and align the necessary backslashes." + (interactive "*r\nP") + (let ((endmark (make-marker)) + ;; Keep the backslash trimming functions from changing the + ;; whitespace around point, since in this case it's only the + ;; position of point that tells the indentation of the line. + (point-pos (if (save-excursion + (skip-chars-backward " \t") + (and (bolp) (looking-at "[ \t]*\\\\?$"))) + (point-marker) + (point-min))) + column longest-line-col bs-col-after-end) + (save-excursion + (goto-char to) + (if (and (not line-mode) (bobp)) + ;; Nothing to do if to is at bob, since we should back up + ;; and there's no line to back up to. + nil + (when (and (not line-mode) (bolp)) + ;; Do not back up the to line if line-mode is set, to make + ;; e.g. c-newline-and-indent consistent regardless whether + ;; the (newline) call leaves point at bol or not. + (backward-char) + (setq to (point))) + (if delete-flag + (progn + (set-marker endmark (point)) + (goto-char from) + (c-delete-backslashes-forward endmark point-pos)) + ;; Set bs-col-after-end to the column of any backslash + ;; following the region, or nil if there is none. + (setq bs-col-after-end + (and (progn (end-of-line) + (eq (char-before) ?\\)) + (= (forward-line 1) 0) + (progn (end-of-line) + (eq (char-before) ?\\)) + (1- (current-column)))) + (when line-mode + ;; Back up the to line if line-mode is set, since the line + ;; after the newly inserted line break should not be + ;; touched in c-newline-and-indent. + (setq to (max from (or (c-safe (c-point 'eopl)) from))) + (unless bs-col-after-end + ;; Set bs-col-after-end to non-nil in any case, since we + ;; do not want to delete the backslash at the last line. + (setq bs-col-after-end t))) + (if (and line-mode + (not c-auto-align-backslashes)) + (goto-char from) + ;; Compute the smallest column number past the ends of all + ;; the lines. + (setq longest-line-col 0) + (goto-char to) + (if bs-col-after-end + ;; Include one more line in the max column + ;; calculation, since the to line will be backslashed + ;; too. + (forward-line 1)) + (end-of-line) + (while (and (>= (point) from) + (progn + (if (eq (char-before) ?\\) + (forward-char -1)) + (skip-chars-backward " \t") + (setq longest-line-col (max longest-line-col + (1+ (current-column)))) + (beginning-of-line) + (not (bobp)))) + (backward-char)) + ;; Try to align with surrounding backslashes. + (goto-char from) + (beginning-of-line) + (if (and (not (bobp)) + (progn (backward-char) + (eq (char-before) ?\\))) + (progn + (setq column (1- (current-column))) + (if (numberp bs-col-after-end) + ;; Both a preceding and a following backslash. + ;; Choose the greatest of them. + (setq column (max column bs-col-after-end))) + (goto-char from)) + ;; No preceding backslash. Try to align with one + ;; following the region. Disregard the backslash at the + ;; to line since it's likely to be bogus (e.g. when + ;; called from c-newline-and-indent). + (if (numberp bs-col-after-end) + (setq column bs-col-after-end)) + ;; Don't modify blank lines at start of region. + (goto-char from) + (while (and (< (point) to) (bolp) (eolp)) + (forward-line 1))) + (if (and column (< column longest-line-col)) + ;; Don't try to align with surrounding backslashes if + ;; any line is too long. + (setq column nil)) + (unless column + ;; Impose minimum limit and tab width alignment only if + ;; we can't align with surrounding backslashes. + (if (> (% longest-line-col tab-width) 0) + (setq longest-line-col + (* (/ (+ longest-line-col tab-width -1) + tab-width) + tab-width))) + (setq column (max c-backslash-column + longest-line-col))) + ;; Always impose maximum limit. + (setq column (min column c-backslash-max-column))) + (if bs-col-after-end + ;; Add backslashes on all lines if the macro continues + ;; after the to line. + (progn + (set-marker endmark to) + (c-append-backslashes-forward endmark column point-pos)) + ;; Add backslashes on all lines except the last, and + ;; remove any on the last line. + (if (save-excursion + (goto-char to) + (beginning-of-line) + (if (not (bobp)) + (set-marker endmark (1- (point))))) + (progn + (c-append-backslashes-forward endmark column point-pos) + ;; The function above leaves point on the line + ;; following endmark. + (set-marker endmark (point))) + (set-marker endmark to)) + (c-delete-backslashes-forward endmark point-pos))))) + (set-marker endmark nil) + (if (markerp point-pos) + (set-marker point-pos nil)))) + +(defun c-append-backslashes-forward (to-mark column point-pos) + (let ((state (parse-partial-sexp (c-point 'bol) (point)))) + (if column + (while + (and + (<= (point) to-mark) + + (let ((start (point)) (inserted nil) end col) + (end-of-line) + (unless (eq (char-before) ?\\) + (insert ?\\) + (setq inserted t)) + (setq state (parse-partial-sexp + start (point) nil nil state)) + (backward-char) + (setq col (current-column)) + + ;; Avoid unnecessary changes of the buffer. + (cond ((and (not inserted) (nth 3 state)) + ;; Don't realign backslashes in string literals + ;; since that would change them. + ) + + ((< col column) + (delete-region + (point) + (progn + (skip-chars-backward + " \t" (if (>= (point) point-pos) point-pos)) + (point))) + (indent-to column)) + + ((and (= col column) + (memq (char-before) '(?\ ?\t)))) + + ((progn + (setq end (point)) + (or (/= (skip-chars-backward + " \t" (if (>= (point) point-pos) point-pos)) + -1) + (/= (char-after) ?\ ))) + (delete-region (point) end) + (indent-to column 1))) + + (zerop (forward-line 1))) + (bolp))) ; forward-line has funny behavior at eob. + + ;; Make sure there are backslashes with at least one space in + ;; front of them. + (while + (and + (<= (point) to-mark) + + (let ((start (point))) + (end-of-line) + (setq state (parse-partial-sexp + start (point) nil nil state)) + + (if (eq (char-before) ?\\) + (unless (nth 3 state) + (backward-char) + (unless (and (memq (char-before) '(?\ ?\t)) + (/= (point) point-pos)) + (insert ?\ ))) + + (if (and (memq (char-before) '(?\ ?\t)) + (/= (point) point-pos)) + (insert ?\\) + (insert ?\ ?\\))) + + (zerop (forward-line 1))) + (bolp)))))) ; forward-line has funny behavior at eob. + +(defun c-delete-backslashes-forward (to-mark point-pos) + (while + (and (<= (point) to-mark) + (progn + (end-of-line) + (if (eq (char-before) ?\\) + (delete-region + (point) + (progn (backward-char) + (skip-chars-backward " \t" (if (>= (point) point-pos) + point-pos)) + (point)))) + (zerop (forward-line 1))) + (bolp)))) ; forward-line has funny behavior at eob. + + + +;;; Line breaking and paragraph filling. + +(defvar c-auto-fill-prefix t) +(defvar c-lit-limits nil) +(defvar c-lit-type nil) + +;; The filling code is based on a simple theory; leave the intricacies +;; of the text handling to the currently active mode for that +;; (e.g. adaptive-fill-mode or filladapt-mode) and do as little as +;; possible to make them work correctly wrt the comment and string +;; separators, one-line paragraphs etc. Unfortunately, when it comes +;; to it, there's quite a lot of special cases to handle which makes +;; the code anything but simple. The intention is that it will work +;; with any well-written text filling package that preserves a fill +;; prefix. +;; +;; We temporarily mask comment starters and enders as necessary for +;; the filling code to do its job on a seemingly normal text block. +;; We do _not_ mask the fill prefix, so it's up to the filling code to +;; preserve it correctly (especially important when filling C++ style +;; line comments). By default, we set up and use adaptive-fill-mode, +;; which is standard in all supported Emacs flavors. + +(defun c-guess-fill-prefix (lit-limits lit-type) + ;; Determine the appropriate comment fill prefix for a block or line + ;; comment. Return a cons of the prefix string and the column where + ;; it ends. If fill-prefix is set, it'll override. Note that this + ;; function also uses the value of point in some heuristics. + ;; + ;; This function might do hidden buffer changes. + + (let* ((here (point)) + (prefix-regexp (concat "[ \t]*\\(" + c-current-comment-prefix + "\\)[ \t]*")) + (comment-start-regexp (if (eq lit-type 'c++) + prefix-regexp + comment-start-skip)) + prefix-line comment-prefix res comment-text-end) + + (cond + (fill-prefix + (setq res (cons fill-prefix + ;; Ugly way of getting the column after the fill + ;; prefix; it'd be nice with a current-column + ;; that works on strings.. + (let ((start (point))) + (unwind-protect + (progn + (insert-and-inherit "\n" fill-prefix) + (current-column)) + (delete-region start (point))))))) + + ((eq lit-type 'c++) + (save-excursion + ;; Set fallback for comment-prefix if none is found. + (setq comment-prefix "// " + comment-text-end (cdr lit-limits)) + + (beginning-of-line) + (if (> (point) (car lit-limits)) + ;; The current line is not the comment starter, so the + ;; comment has more than one line, and it can therefore be + ;; used to find the comment fill prefix. + (setq prefix-line (point)) + + (goto-char (car lit-limits)) + (if (and (= (forward-line 1) 0) + (< (point) (cdr lit-limits))) + ;; The line after the comment starter is inside the + ;; comment, so we can use it. + (setq prefix-line (point)) + + ;; The comment is only one line. Take the comment prefix + ;; from it and keep the indentation. + (goto-char (car lit-limits)) + (if (looking-at prefix-regexp) + (goto-char (match-end 0)) + (forward-char 2) + (skip-chars-forward " \t")) + + (let (str col) + (if (eq (c-point 'boi) (car lit-limits)) + ;; There is only whitespace before the comment + ;; starter; take the prefix straight from this line. + (setq str (buffer-substring-no-properties + (c-point 'bol) (point)) + col (current-column)) + + ;; There is code before the comment starter, so we + ;; have to temporarily insert and indent a new line to + ;; get the right space/tab mix in the indentation. + (let ((prefix-len (- (point) (car lit-limits))) + tmp) + (unwind-protect + (progn + (goto-char (car lit-limits)) + (indent-to (prog1 (current-column) + (insert ?\n))) + (setq tmp (point)) + (forward-char prefix-len) + (setq str (buffer-substring-no-properties + (c-point 'bol) (point)) + col (current-column))) + (delete-region (car lit-limits) tmp)))) + + (setq res + (if (or (string-match "\\s \\'" str) (not (eolp))) + (cons str col) + ;; The prefix ends the line with no whitespace + ;; after it. Default to a single space. + (cons (concat str " ") (1+ col)))) + ))))) + + (t + (setq comment-text-end + (save-excursion + (goto-char (- (cdr lit-limits) 2)) + (if (looking-at "\\*/") (point) (cdr lit-limits)))) + + (save-excursion + (beginning-of-line) + (if (and (> (point) (car lit-limits)) + (not (and (looking-at "[ \t]*\\*/") + (eq (cdr lit-limits) (match-end 0))))) + ;; The current line is not the comment starter and + ;; contains more than just the ender, so it's good enough + ;; to be used for the comment fill prefix. + (setq prefix-line (point)) + (goto-char (car lit-limits)) + + (cond ((or (/= (forward-line 1) 0) + (>= (point) (cdr lit-limits)) + (and (looking-at "[ \t]*\\*/") + (eq (cdr lit-limits) (match-end 0))) + (and (looking-at prefix-regexp) + (<= (1- (cdr lit-limits)) (match-end 0)))) + ;; The comment is either one line or the next line contains + ;; just the comment ender. In this case we have no + ;; information about a suitable comment prefix, so we resort + ;; to c-block-comment-prefix. + (setq comment-prefix (or c-block-comment-prefix ""))) + + ((< here (point)) + ;; The point was on the comment opener line, so we might want + ;; to treat this as a not yet closed comment. + + (if (and (match-beginning 1) + (/= (match-beginning 1) (match-end 1))) + ;; Above `prefix-regexp' matched a nonempty prefix on the + ;; second line, so let's use it. Normally it should do + ;; to set `prefix-line' and let the code below pick up + ;; the whole prefix, but if there's no text after the + ;; match then it will probably fall back to no prefix at + ;; all if the comment isn't closed yet, so in that case + ;; it's better to force use of the prefix matched now. + (if (= (match-end 0) (c-point 'eol)) + (setq comment-prefix (match-string 1)) + (setq prefix-line (point))) + + ;; There's no nonempty prefix on the line after the + ;; comment opener. If the line is empty, or if the + ;; text on it has less or equal indentation than the + ;; comment starter we assume it's an unclosed + ;; comment starter, i.e. that + ;; `c-block-comment-prefix' should be used. + ;; Otherwise we assume it's a closed comment where + ;; the prefix really is the empty string. + ;; E.g. this is an unclosed comment: + ;; + ;; /* + ;; foo + ;; + ;; But this is not: + ;; + ;; /* + ;; foo + ;; */ + ;; + ;; (Looking for the presence of the comment closer + ;; rarely works since it's probably the closer of + ;; some comment further down when the comment + ;; really is unclosed.) + (if (<= (save-excursion (back-to-indentation) + (current-column)) + (save-excursion (goto-char (car lit-limits)) + (current-column))) + (setq comment-prefix (or c-block-comment-prefix "")) + (setq prefix-line (point))))) + + (t + ;; Otherwise the line after the comment starter is good + ;; enough to find the prefix in. + (setq prefix-line (point)))) + + (when comment-prefix + ;; Haven't got the comment prefix on any real line that we + ;; can take it from, so we have to temporarily insert + ;; `comment-prefix' on a line and indent it to find the + ;; correct column and the correct mix of tabs and spaces. + (setq res + (let (tmp-pre tmp-post) + (unwind-protect + (progn + + (goto-char (car lit-limits)) + (if (looking-at comment-start-regexp) + (goto-char (min (match-end 0) + comment-text-end)) + (forward-char 2) + (skip-chars-forward " \t")) + + (when (eq (char-syntax (char-before)) ?\ ) + ;; If there's ws on the current line, we'll use it + ;; instead of what's ending comment-prefix. + (setq comment-prefix + (concat (substring comment-prefix + 0 (string-match + "\\s *\\'" + comment-prefix)) + (buffer-substring-no-properties + (save-excursion + (skip-chars-backward " \t") + (point)) + (point))))) + + (setq tmp-pre (point-marker)) + + ;; We insert an extra non-whitespace character + ;; before the line break and after comment-prefix in + ;; case it's "" or ends with whitespace. + (insert-and-inherit "x\n" comment-prefix "x") + (setq tmp-post (point-marker)) + + (indent-according-to-mode) + + (goto-char (1- tmp-post)) + (cons (buffer-substring-no-properties + (c-point 'bol) (point)) + (current-column))) + + (when tmp-post + (delete-region tmp-pre tmp-post) + (set-marker tmp-pre nil) + (set-marker tmp-post nil)))))))))) + + (or res ; Found a good prefix above. + + (save-excursion + ;; prefix-line is the bol of a line on which we should try + ;; to find the prefix. + (let* (fb-string fb-endpos ; Contains any fallback prefix found. + (test-line + (lambda () + (when (and (looking-at prefix-regexp) + (<= (match-end 0) comment-text-end)) + (unless (eq (match-end 0) (c-point 'eol)) + ;; The match is fine if there's text after it. + (throw 'found (cons (buffer-substring-no-properties + (match-beginning 0) (match-end 0)) + (progn (goto-char (match-end 0)) + (current-column))))) + (unless fb-string + ;; This match is better than nothing, so let's + ;; remember it in case nothing better is found + ;; on another line. + (setq fb-string (buffer-substring-no-properties + (match-beginning 0) (match-end 0)) + fb-endpos (match-end 0))) + t)))) + + (or (catch 'found + ;; Search for a line which has text after the prefix + ;; so that we get the proper amount of whitespace + ;; after it. We start with the current line, then + ;; search backwards, then forwards. + + (goto-char prefix-line) + (when (and (funcall test-line) + (or (/= (match-end 1) (match-end 0)) + ;; The whitespace is sucked up by the + ;; first [ \t]* glob if the prefix is empty. + (and (= (match-beginning 1) (match-end 1)) + (/= (match-beginning 0) (match-end 0))))) + ;; If the current line doesn't have text but do + ;; have whitespace after the prefix, we'll use it. + (throw 'found (cons fb-string + (progn (goto-char fb-endpos) + (current-column))))) + + (if (eq lit-type 'c++) + ;; For line comments we can search up to and + ;; including the first line. + (while (and (zerop (forward-line -1)) + (>= (point) (car lit-limits))) + (funcall test-line)) + ;; For block comments we must stop before the + ;; block starter. + (while (and (zerop (forward-line -1)) + (> (point) (car lit-limits))) + (funcall test-line))) + + (goto-char prefix-line) + (while (and (zerop (forward-line 1)) + (< (point) (cdr lit-limits))) + (funcall test-line)) + + (goto-char prefix-line) + nil) + + (when fb-string + ;; A good line wasn't found, but at least we have a + ;; fallback that matches the comment prefix regexp. + (cond ((or (string-match "\\s \\'" fb-string) + (progn + (goto-char fb-endpos) + (not (eolp)))) + ;; There are ws or text after the prefix, so + ;; let's use it. + (cons fb-string (current-column))) + + ((progn + ;; Check if there's any whitespace padding + ;; on the comment start line that we can + ;; use after the prefix. + (goto-char (car lit-limits)) + (if (looking-at comment-start-regexp) + (goto-char (match-end 0)) + (forward-char 2) + (skip-chars-forward " \t")) + (or (not (eolp)) + (eq (char-syntax (char-before)) ?\ ))) + + (setq fb-string (buffer-substring-no-properties + (save-excursion + (skip-chars-backward " \t") + (point)) + (point))) + (goto-char fb-endpos) + (skip-chars-backward " \t") + + (let ((tmp (point))) + ;; Got to mess in the buffer once again to + ;; ensure the column gets correct. :P + (unwind-protect + (progn + (insert-and-inherit fb-string) + (cons (buffer-substring-no-properties + (c-point 'bol) + (point)) + (current-column))) + (delete-region tmp (point))))) + + (t + ;; Last resort: Just add a single space after + ;; the prefix. + (cons (concat fb-string " ") + (progn (goto-char fb-endpos) + (1+ (current-column))))))) + + ;; The line doesn't match the comment prefix regexp. + (if comment-prefix + ;; We have a fallback for line comments that we must use. + (cons (concat (buffer-substring-no-properties + prefix-line (c-point 'boi)) + comment-prefix) + (progn (back-to-indentation) + (+ (current-column) (length comment-prefix)))) + + ;; Assume we are dealing with a "free text" block + ;; comment where the lines doesn't have any comment + ;; prefix at all and we should just fill it as + ;; normal text. + '("" . 0)))))) + )) + +(defun c-mask-paragraph (fill-paragraph apply-outside-literal fun &rest args) + ;; Calls FUN with ARGS ar arguments while the current paragraph is + ;; masked to allow adaptive filling to work correctly. That + ;; includes narrowing the buffer and, if point is inside a comment, + ;; masking the comment starter and ender appropriately. + ;; + ;; FILL-PARAGRAPH is non-nil if called for whole paragraph filling. + ;; The position of point is then less significant when doing masking + ;; and narrowing. + ;; + ;; If APPLY-OUTSIDE-LITERAL is nil then the function will be called + ;; only if the point turns out to be inside a comment or a string. + ;; + ;; Note that this function does not do any hidden buffer changes. + + (let (fill + ;; beg and end limit the region to narrow. end is a marker. + beg end + ;; tmp-pre and tmp-post mark strings that are temporarily + ;; inserted at the start and end of the region. tmp-pre is a + ;; cons of the positions of the prepended string. tmp-post is + ;; a marker pointing to the single character of the appended + ;; string. + tmp-pre tmp-post + ;; If hang-ender-stuck isn't nil, the comment ender is + ;; hanging. In that case it's set to the number of spaces + ;; that should be between the text and the ender. + hang-ender-stuck + ;; auto-fill-spaces is the exact sequence of whitespace between a + ;; comment's last word and the comment ender, temporarily replaced + ;; with 'x's before calling FUN when FILL-PARAGRAPH is nil. + auto-fill-spaces + (here (point)) + (c-lit-limits c-lit-limits) + (c-lit-type c-lit-type)) + + ;; Restore point on undo. It's necessary since we do a lot of + ;; hidden inserts and deletes below that should be as transparent + ;; as possible. + (if (and buffer-undo-list (not (eq buffer-undo-list t))) + (setq buffer-undo-list (cons (point) buffer-undo-list))) + + ;; Determine the limits and type of the containing literal (if any): + ;; C-LIT-LIMITS, C-LIT-TYPE; and the limits of the current paragraph: + ;; BEG and END. + (c-save-buffer-state () + (save-restriction + ;; Widen to catch comment limits correctly. + (widen) + (unless c-lit-limits + (setq c-lit-limits (c-literal-limits nil fill-paragraph))) + (setq c-lit-limits (c-collect-line-comments c-lit-limits)) + (unless c-lit-type + (setq c-lit-type (c-literal-type c-lit-limits)))) + + (save-excursion + (unless (c-safe (backward-char) + (forward-paragraph) + (>= (point) here)) + (goto-char here) + (forward-paragraph)) + (setq end (point-marker))) + (save-excursion + (unless (c-safe (forward-char) + (backward-paragraph) + (<= (point) here)) + (goto-char here) + (backward-paragraph)) + (setq beg (point)))) + + (unwind-protect + (progn + ;; For each of the possible types of text (string, C comment ...) + ;; determine BEG and END, the region we will narrow to. If we're in + ;; a literal, constrain BEG and END to the limits of this literal. + ;; + ;; For some of these text types, particularly a block comment, we + ;; may need to massage whitespace near literal delimiters, so that + ;; these don't get filled inappropriately. + (cond + + ((eq c-lit-type 'c++) ; Line comment. + (save-excursion + ;; Limit to the comment or paragraph end, whichever + ;; comes first. + (set-marker end (min end (cdr c-lit-limits))) + + (when (<= beg (car c-lit-limits)) + ;; The region includes the comment starter, so we must + ;; check it. + (goto-char (car c-lit-limits)) + (back-to-indentation) + (if (eq (point) (car c-lit-limits)) + ;; Include the first line in the region. + (setq beg (c-point 'bol)) + ;; The first line contains code before the + ;; comment. We must fake a line that doesn't. + (setq tmp-pre t)))) + + (setq apply-outside-literal t)) + + ((eq c-lit-type 'c) ; Block comment. + (when + (or (> end (cdr c-lit-limits)) + (and (= end (cdr c-lit-limits)) + (eq (char-before end) ?/) + (eq (char-before (1- end)) ?*) + ;; disallow "/*/" + (> (- (cdr c-lit-limits) (car c-lit-limits)) 3))) + ;; There is a comment ender, and the region includes it. If + ;; it's on its own line, it stays on its own line. If it's got + ;; company on the line, it keeps (at least one word of) it. + ;; "=====*/" counts as a comment ender here, but "===== */" + ;; doesn't and "foo*/" doesn't. + (unless + (save-excursion + (goto-char (cdr c-lit-limits)) + (beginning-of-line) + ;; The following conjunct was added to avoid an + ;; "Invalid search bound (wrong side of point)" + ;; error in the subsequent re-search. Maybe + ;; another fix would be needed (2007-12-08). +; (or (<= (- (cdr c-lit-limits) 2) (point)) +; 2010-10-17 Construct removed. +; (or (< (- (cdr c-lit-limits) 2) (point)) + (and + (search-forward-regexp + (concat "\\=[ \t]*\\(" c-current-comment-prefix "\\)") + (- (cdr c-lit-limits) 2) t) + (not (search-forward-regexp + "\\(\\s \\|\\sw\\)" + (- (cdr c-lit-limits) 2) 'limit)) + ;; The comment ender IS on its own line. Exclude this + ;; line from the filling. + (set-marker end (c-point 'bol))));) + + ;; The comment ender is hanging. Replace all space between it + ;; and the last word either by one or two 'x's (when + ;; FILL-PARAGRAPH is non-nil), or a row of x's the same width + ;; as the whitespace (when auto filling), and include it in + ;; the region. We'll change them back to whitespace + ;; afterwards. The effect of this is to glue the comment + ;; ender to the last word in the comment during filling. + (let* ((ender-start (save-excursion + (goto-char (cdr c-lit-limits)) + (skip-syntax-backward "^w ") + (point))) + (ender-column (save-excursion + (goto-char ender-start) + (current-column))) + (point-rel (- ender-start here)) + (sentence-ends-comment + (save-excursion + (goto-char ender-start) + (and (search-backward-regexp + (c-sentence-end) (c-point 'bol) t) + (goto-char (match-end 0)) + (looking-at "[ \t]*") + (= (match-end 0) ender-start)))) + spaces) + + (save-excursion + ;; Insert a CR after the "*/", adjust END + (goto-char (cdr c-lit-limits)) + (setq tmp-post (point-marker)) + (insert ?\n) + (set-marker end (point)) + + (forward-line -1) ; last line of the comment + (if (and (looking-at (concat "[ \t]*\\(\\(" + c-current-comment-prefix + "\\)[ \t]*\\)")) + (eq ender-start (match-end 0))) + ;; The comment ender is prefixed by nothing but a + ;; comment line prefix. IS THIS POSSIBLE? (ACM, + ;; 2006/4/28). Remove it along with surrounding ws. + (setq spaces (- (match-end 1) (match-end 2))) + (goto-char ender-start)) + (skip-chars-backward " \t\r\n") ; Surely this can be + ; " \t"? "*/" is NOT alone on the line (ACM, 2005/8/18) + + ;; What's being tested here? 2006/4/20. FIXME!!! + (if (/= (point) ender-start) + (progn + (if (<= here (point)) + ;; Don't adjust point below if it's + ;; before the string we replace. + (setq point-rel -1)) + ;; Keep one or two spaces between the + ;; text and the ender, depending on how + ;; many there are now. + (unless spaces + (setq spaces (- ender-column (current-column)))) + (setq auto-fill-spaces (c-delete-and-extract-region + (point) ender-start)) + ;; paragraph filling condenses multiple spaces to + ;; single or double spaces. auto-fill doesn't. + (if fill-paragraph + (setq spaces + (max + (min spaces + (if (and sentence-ends-comment + sentence-end-double-space) + 2 1)) + 1))) + ;; Insert the filler first to keep marks right. + (insert-char ?x spaces t) + (setq hang-ender-stuck spaces) + (setq point-rel + (and (>= point-rel 0) + (- (point) (min point-rel spaces))))) + (setq point-rel nil))) + + (if point-rel + ;; Point was in the middle of the string we + ;; replaced above, so put it back in the same + ;; relative position, counting from the end. + (goto-char point-rel))) + )) + + (when (<= beg (car c-lit-limits)) + ;; The region includes the comment starter. + (save-excursion + (goto-char (car c-lit-limits)) + (if (looking-at (concat "\\(" comment-start-skip "\\)$")) + ;; Begin with the next line. + (setq beg (c-point 'bonl)) + ;; Fake the fill prefix in the first line. + (setq tmp-pre t)))) + + (setq apply-outside-literal t)) + + ((eq c-lit-type 'string) ; String. + (save-excursion + (when (>= end (cdr c-lit-limits)) + (goto-char (1- (cdr c-lit-limits))) + (setq tmp-post (point-marker)) + (insert ?\n) + (set-marker end (point))) + (when (<= beg (car c-lit-limits)) + (goto-char (1+ (car c-lit-limits))) + (setq beg (if (looking-at "\\\\$") + ;; Leave the start line if it's + ;; nothing but an escaped newline. + (1+ (match-end 0)) + (point))))) + (setq apply-outside-literal t)) + + ((eq c-lit-type 'pound) ; Macro + ;; Narrow to the macro limits if they are nearer than the + ;; paragraph limits. Don't know if this is necessary but + ;; do it for completeness sake (doing auto filling at all + ;; inside macros is bogus to begin with since the line + ;; continuation backslashes aren't handled). + (save-excursion + (c-save-buffer-state () + (c-beginning-of-macro) + (beginning-of-line) + (if (> (point) beg) + (setq beg (point))) + (c-end-of-macro) + (forward-line) + (if (< (point) end) + (set-marker end (point)))))) + + (t ; Other code. + ;; Try to avoid comments and macros in the paragraph to + ;; avoid that the adaptive fill mode gets the prefix from + ;; them. + (c-save-buffer-state nil + (save-excursion + (goto-char beg) + (c-forward-syntactic-ws end) + (beginning-of-line) + (setq beg (point)) + (goto-char end) + (c-backward-syntactic-ws beg) + (forward-line) + (set-marker end (point)))))) + + (when tmp-pre + ;; Temporarily insert the fill prefix after the comment + ;; starter so that the first line looks like any other + ;; comment line in the narrowed region. + (setq fill (c-save-buffer-state nil + (c-guess-fill-prefix c-lit-limits c-lit-type))) + (unless (string-match (concat "\\`[ \t]*\\(" + c-current-comment-prefix + "\\)[ \t]*\\'") + (car fill)) + ;; Oops, the prefix doesn't match the comment prefix + ;; regexp. This could produce very confusing + ;; results with adaptive fill packages together with + ;; the insert prefix magic below, since the prefix + ;; often doesn't appear at all. So let's warn about + ;; it. + (message "\ +Warning: Regexp from `c-comment-prefix-regexp' doesn't match the comment prefix %S" + (car fill))) + ;; Find the right spot on the line, break it, insert + ;; the fill prefix and make sure we're back in the + ;; same column by temporarily prefixing the first word + ;; with a number of 'x'. + (save-excursion + (goto-char (car c-lit-limits)) + (if (looking-at (if (eq c-lit-type 'c++) + c-current-comment-prefix + comment-start-skip)) + (goto-char (match-end 0)) + (forward-char 2) + (skip-chars-forward " \t")) + (while (and (< (current-column) (cdr fill)) + (not (eolp))) + (forward-char 1)) + (let ((col (current-column))) + (setq beg (1+ (point)) + tmp-pre (list (point))) + (unwind-protect + (progn + (insert-and-inherit "\n" (car fill)) + (insert-char ?x (- col (current-column)) t)) + (setcdr tmp-pre (point)))))) + + (when apply-outside-literal + ;; `apply-outside-literal' is always set to t here if + ;; we're inside a literal. + + (let ((fill-prefix + (or fill-prefix + ;; Kludge: If the function that adapts the fill prefix + ;; doesn't produce the required comment starter for + ;; line comments, then force it by setting fill-prefix. + (when (and (eq c-lit-type 'c++) + ;; Kludge the kludge: filladapt-mode doesn't + ;; have this problem, but it currently + ;; doesn't override fill-context-prefix + ;; (version 2.12). + (not (and (boundp 'filladapt-mode) + filladapt-mode)) + (not (string-match + "\\`[ \t]*//" + (or (fill-context-prefix beg end) + "")))) + (c-save-buffer-state nil + (car (or fill (c-guess-fill-prefix + c-lit-limits c-lit-type))))))) + + ;; Save the relative position of point if it's outside the + ;; region we're going to narrow. Want to restore it in that + ;; case, but otherwise it should be moved according to the + ;; called function. + (point-rel (cond ((< (point) beg) (- (point) beg)) + ((> (point) end) (- (point) end))))) + + ;; Preparations finally done! Now we can call the + ;; actual function. + (prog1 + (save-restriction + (narrow-to-region beg end) + (apply fun args)) + (if point-rel + ;; Restore point if it was outside the region. + (if (< point-rel 0) + (goto-char (+ beg point-rel)) + (goto-char (+ end point-rel)))))))) + + (when (consp tmp-pre) + (delete-region (car tmp-pre) (cdr tmp-pre))) + + (when tmp-post + (save-excursion + (goto-char tmp-post) + (delete-char 1)) + (when hang-ender-stuck + ;; Preserve point even if it's in the middle of the string + ;; we replace; save-excursion doesn't work in that case. + (setq here (point)) + (goto-char tmp-post) + (skip-syntax-backward "^w ") + (forward-char (- hang-ender-stuck)) + (if (or fill-paragraph (not auto-fill-spaces)) + (insert-char ?\ hang-ender-stuck t) + (insert auto-fill-spaces) + ;; (setq here (- here (- hang-ender-stuck (length auto-fill-spaces)))) + ) + (delete-char hang-ender-stuck) + (goto-char here)) + (set-marker tmp-post nil)) + + (set-marker end nil)))) + +(defun c-fill-paragraph (&optional arg) + "Like \\[fill-paragraph] but handles C and C++ style comments. +If any of the current line is a comment or within a comment, fill the +comment or the paragraph of it that point is in, preserving the +comment indentation or line-starting decorations (see the +`c-comment-prefix-regexp' and `c-block-comment-prefix' variables for +details). + +If point is inside multiline string literal, fill it. This currently +does not respect escaped newlines, except for the special case when it +is the very first thing in the string. The intended use for this rule +is in situations like the following: + +char description[] = \"\\ +A very long description of something that you want to fill to make +nicely formatted output.\"\; + +If point is in any other situation, i.e. in normal code, do nothing. + +Optional prefix ARG means justify paragraph as well." + (interactive "*P") + (let ((fill-paragraph-function + ;; Avoid infinite recursion. + (if (not (eq fill-paragraph-function 'c-fill-paragraph)) + fill-paragraph-function))) + (c-mask-paragraph t nil 'fill-paragraph arg)) + ;; Always return t. This has the effect that if filling isn't done + ;; above, it isn't done at all, and it's therefore effectively + ;; disabled in normal code. + t) + +(defun c-do-auto-fill () + ;; Do automatic filling if not inside a context where it should be + ;; ignored. + (let ((c-auto-fill-prefix + ;; The decision whether the line should be broken is actually + ;; done in c-indent-new-comment-line, which do-auto-fill + ;; calls to break lines. We just set this special variable + ;; so that we'll know when we're called from there. It's + ;; also used to detect whether fill-prefix is user set or + ;; generated automatically by do-auto-fill. + fill-prefix)) + (c-mask-paragraph nil t 'do-auto-fill))) + +(defun c-indent-new-comment-line (&optional soft allow-auto-fill) + "Break line at point and indent, continuing comment or macro if within one. +If inside a comment and `comment-multi-line' is non-nil, the +indentation and line prefix are preserved (see the +`c-comment-prefix-regexp' and `c-block-comment-prefix' variables for +details). If inside a single line comment and `comment-multi-line' is +nil, a new comment of the same type is started on the next line and +indented as appropriate for comments. If inside a macro, a line +continuation backslash is inserted and aligned as appropriate, and the +new line is indented according to `c-syntactic-indentation'. + +If a fill prefix is specified, it overrides all the above." + ;; allow-auto-fill is used from c-context-line-break to allow auto + ;; filling to break the line more than once. Since this function is + ;; used from auto-fill itself, that's normally disabled to avoid + ;; unnecessary recursion. + (interactive) + (let ((fill-prefix fill-prefix) + (do-line-break + (lambda () + (delete-horizontal-space) + (if soft + (insert-and-inherit ?\n) + (newline (if allow-auto-fill nil 1))))) + ;; Already know the literal type and limits when called from + ;; c-context-line-break. + (c-lit-limits c-lit-limits) + (c-lit-type c-lit-type) + (c-macro-start c-macro-start)) + + (c-save-buffer-state () + (when (not (eq c-auto-fill-prefix t)) + ;; Called from do-auto-fill. + (unless c-lit-limits + (setq c-lit-limits (c-literal-limits nil nil t))) + (unless c-lit-type + (setq c-lit-type (c-literal-type c-lit-limits))) + (if (memq (cond ((c-query-and-set-macro-start) 'cpp) + ((null c-lit-type) 'code) + (t c-lit-type)) + c-ignore-auto-fill) + (setq fill-prefix t) ; Used as flag in the cond. + (if (and (null c-auto-fill-prefix) + (eq c-lit-type 'c) + (<= (c-point 'bol) (car c-lit-limits))) + ;; The adaptive fill function has generated a prefix, but + ;; we're on the first line in a block comment so it'll be + ;; wrong. Ignore it to guess a better one below. + (setq fill-prefix nil) + (when (and (eq c-lit-type 'c++) + (not (string-match (concat "\\`[ \t]*" + c-line-comment-starter) + (or fill-prefix "")))) + ;; Kludge: If the function that adapted the fill prefix + ;; doesn't produce the required comment starter for line + ;; comments, then we ignore it. + (setq fill-prefix nil))) + ))) + + (cond ((eq fill-prefix t) + ;; A call from do-auto-fill which should be ignored. + ) + (fill-prefix + ;; A fill-prefix overrides anything. + (funcall do-line-break) + (insert-and-inherit fill-prefix)) + ((c-save-buffer-state () + (unless c-lit-limits + (setq c-lit-limits (c-literal-limits))) + (unless c-lit-type + (setq c-lit-type (c-literal-type c-lit-limits))) + (memq c-lit-type '(c c++))) + ;; Some sort of comment. + (if (or comment-multi-line + (save-excursion + (goto-char (car c-lit-limits)) + (end-of-line) + (< (point) (cdr c-lit-limits)))) + ;; Inside a comment that should be continued. + (let ((fill (c-save-buffer-state nil + (c-guess-fill-prefix + (setq c-lit-limits + (c-collect-line-comments c-lit-limits)) + c-lit-type))) + (pos (point)) + (start-col (current-column)) + (comment-text-end + (or (and (eq c-lit-type 'c) + (save-excursion + (goto-char (- (cdr c-lit-limits) 2)) + (if (looking-at "\\*/") (point)))) + (cdr c-lit-limits)))) + ;; Skip forward past the fill prefix in case + ;; we're standing in it. + ;; + ;; FIXME: This doesn't work well in cases like + ;; + ;; /* Bla bla bla bla bla + ;; bla bla + ;; + ;; If point is on the 'B' then the line will be + ;; broken after "Bla b". + ;; + ;; If we have an empty comment, /* */, the next + ;; lot of code pushes point to the */. We fix + ;; this by never allowing point to end up to the + ;; right of where it started. + (while (and (< (current-column) (cdr fill)) + (not (eolp))) + (forward-char 1)) + (if (and (> (point) comment-text-end) + (> (c-point 'bol) (car c-lit-limits))) + (progn + ;; The skip takes us out of the (block) + ;; comment; insert the fill prefix at bol + ;; instead and keep the position. + (setq pos (copy-marker pos t)) + (beginning-of-line) + (insert-and-inherit (car fill)) + (if soft (insert-and-inherit ?\n) (newline 1)) + (goto-char pos) + (set-marker pos nil)) + ;; Don't break in the middle of a comment starter + ;; or ender. + (cond ((> (point) comment-text-end) + (goto-char comment-text-end)) + ((< (point) (+ (car c-lit-limits) 2)) + (goto-char (+ (car c-lit-limits) 2)))) + (funcall do-line-break) + (insert-and-inherit (car fill)) + (if (> (current-column) start-col) + (move-to-column start-col)))) ; can this hit the + ; middle of a TAB? + ;; Inside a comment that should be broken. + (let ((comment-start comment-start) + (comment-end comment-end) + col) + (if (eq c-lit-type 'c) + (unless (string-match "[ \t]*/\\*" comment-start) + (setq comment-start "/* " comment-end " */")) + (unless (string-match "[ \t]*//" comment-start) + (setq comment-start "// " comment-end ""))) + (setq col (save-excursion + (back-to-indentation) + (current-column))) + (funcall do-line-break) + (when (and comment-end (not (equal comment-end ""))) + (forward-char -1) + (insert-and-inherit comment-end) + (forward-char 1)) + ;; c-comment-indent may look at the current + ;; indentation, so let's start out with the same + ;; indentation as the previous one. + (indent-to col) + (insert-and-inherit comment-start) + (indent-for-comment)))) + ((c-query-and-set-macro-start) + ;; In a macro. + (unless (looking-at "[ \t]*\\\\$") + ;; Do not clobber the alignment of the line continuation + ;; slash; c-backslash-region might look at it. + (delete-horizontal-space)) + ;; Got an asymmetry here: In normal code this command + ;; doesn't indent the next line syntactically, and otoh a + ;; normal syntactically indenting newline doesn't continue + ;; the macro. + (c-newline-and-indent (if allow-auto-fill nil 1))) + (t + ;; Somewhere else in the code. + (let ((col (save-excursion + (beginning-of-line) + (while (and (looking-at "[ \t]*\\\\?$") + (= (forward-line -1) 0))) + (current-indentation)))) + (funcall do-line-break) + (indent-to col)))))) + +(defalias 'c-comment-line-break-function 'c-indent-new-comment-line) +(make-obsolete 'c-comment-line-break-function 'c-indent-new-comment-line nil) + +;; advice for indent-new-comment-line for older Emacsen +(unless (boundp 'comment-line-break-function) + (defvar c-inside-line-break-advice nil) + (defadvice indent-new-comment-line (around c-line-break-advice + activate preactivate) + "Call `c-indent-new-comment-line' if in CC Mode." + (if (or c-inside-line-break-advice + (not c-buffer-is-cc-mode)) + ad-do-it + (let ((c-inside-line-break-advice t)) + (c-indent-new-comment-line (ad-get-arg 0)))))) + +(defun c-context-line-break () + "Do a line break suitable to the context. + +When point is outside a comment or macro, insert a newline and indent +according to the syntactic context, unless `c-syntactic-indentation' +is nil, in which case the new line is indented as the previous +non-empty line instead. + +When point is inside the content of a preprocessor directive, a line +continuation backslash is inserted before the line break and aligned +appropriately. The end of the cpp directive doesn't count as inside +it. + +When point is inside a comment, continue it with the appropriate +comment prefix (see the `c-comment-prefix-regexp' and +`c-block-comment-prefix' variables for details). The end of a +C++-style line comment doesn't count as inside it. + +When point is inside a string, only insert a backslash when it is also +inside a preprocessor directive." + + (interactive "*") + (let* (c-lit-limits c-lit-type + (c-macro-start c-macro-start) + case-fold-search) + + (c-save-buffer-state () + (setq c-lit-limits (c-literal-limits nil nil t) + c-lit-type (c-literal-type c-lit-limits)) + (when (eq c-lit-type 'c++) + (setq c-lit-limits (c-collect-line-comments c-lit-limits))) + (c-query-and-set-macro-start)) + + (cond + ((or (eq c-lit-type 'c) + (and (eq c-lit-type 'c++) ; C++ comment, but not at the very end of it. + (< (save-excursion + (skip-chars-forward " \t") + (point)) + (1- (cdr c-lit-limits)))) + (and (numberp c-macro-start) ; Macro, but not at the very end of + ; it, not in a string, and not in the + ; cpp keyword. + (not (eq c-lit-type 'string)) + (or (not (looking-at "\\s *$")) + (eq (char-before) ?\\)) + (<= (save-excursion + (goto-char c-macro-start) + (if (looking-at c-opt-cpp-start) + (goto-char (match-end 0))) + (point)) + (point)))) + (let ((comment-multi-line t) + (fill-prefix nil)) + (c-indent-new-comment-line nil t))) + + ((eq c-lit-type 'string) + (if (and (numberp c-macro-start) + (not (eq (char-before) ?\\))) + (insert ?\\)) + (newline)) + + (t (delete-horizontal-space) + (newline) + ;; c-indent-line may look at the current indentation, so let's + ;; start out with the same indentation as the previous line. + (let ((col (save-excursion + (backward-char) + (forward-line 0) + (while (and (looking-at "[ \t]*\\\\?$") + (= (forward-line -1) 0))) + (current-indentation)))) + (indent-to col)) + (indent-according-to-mode))))) + +(defun c-context-open-line () + "Insert a line break suitable to the context and leave point before it. +This is the `c-context-line-break' equivalent to `open-line', which is +normally bound to C-o. See `c-context-line-break' for the details." + (interactive "*") + (let ((here (point))) + (unwind-protect + (progn + ;; Temporarily insert a non-whitespace char to keep any + ;; preceding whitespace intact. + (insert ?x) + (c-context-line-break)) + (goto-char here) + (delete-char 1)))) + + +(cc-provide 'cc-cmds) + +;;; arch-tag: bf0611dc-d1f4-449e-9e45-4ec7c6936677 +;;; cc-cmds.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-compat.el b/site-lisp/cc-mode/5.32.3/cc-compat.el new file mode 100644 index 0000000..3c3f345 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-compat.el @@ -0,0 +1,166 @@ +;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 1998- Martin Stjernholm +;; 1994-1999 Barry A. Warsaw +;; Maintainer: bug-cc-mode@gnu.org +;; Created: August 1994, split from cc-mode.el +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: +;; +;; Boring old c-mode.el (BOCM) is confusion and brain melt. cc-mode.el +;; is clarity of thought and purity of chi. If you are still unwilling +;; to accept enlightenment, this might help, or it may prolong your +;; agony. +;; +;; To use, add the following to your c-mode-hook: +;; +;; (require 'cc-compat) +;; (c-set-style "BOCM") +;; +;; This file is completely unsupported! Although it has been patched +;; superficially to keep pace with the rest of CC Mode, it hasn't been +;; tested for a long time. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-styles) +(cc-require 'cc-engine) + + +;; In case c-mode.el isn't loaded +(defvar c-indent-level 2 + "*Indentation of C statements with respect to containing block.") +(defvar c-brace-imaginary-offset 0 + "*Imagined indentation of a C open brace that actually follows a statement.") +(defvar c-brace-offset 0 + "*Extra indentation for braces, compared with other text in same context.") +(defvar c-argdecl-indent 5 + "*Indentation level of declarations of C function arguments.") +(defvar c-label-offset -2 + "*Offset of C label lines and case statements relative to usual indentation.") +(defvar c-continued-statement-offset 2 + "*Extra indent for lines not starting new statements.") +(defvar c-continued-brace-offset 0 + "*Extra indent for substatements that start with open-braces. +This is in addition to c-continued-statement-offset.") + + + +;; these offsets are taken by brute force testing c-mode.el, since +;; there's no logic to what it does. +(let* ((offsets '(c-offsets-alist . + ((defun-block-intro . cc-block-intro-offset) + (statement-block-intro . cc-block-intro-offset) + (defun-open . 0) + (class-open . 0) + (inline-open . c-brace-offset) + (block-open . c-brace-offset) + (block-close . cc-block-close-offset) + (brace-list-open . c-brace-offset) + (substatement-open . cc-substatement-open-offset) + (substatement . c-continued-statement-offset) + (knr-argdecl-intro . c-argdecl-indent) + (case-label . c-label-offset) + (access-label . c-label-offset) + (label . c-label-offset) + )))) + (c-add-style "BOCM" offsets)) + + +(defun cc-block-intro-offset (langelem) + ;; taken directly from calculate-c-indent confusion + (save-excursion + (c-backward-syntactic-ws) + (if (eq (char-before) ?{) + (forward-char -1) + (goto-char (cdr langelem))) + (let* ((curcol (save-excursion + (goto-char (cdr langelem)) + (current-column))) + (bocm-lossage + ;; If no previous statement, indent it relative to line + ;; brace is on. For open brace in column zero, don't let + ;; statement start there too. If c-indent-level is zero, + ;; use c-brace-offset + c-continued-statement-offset + ;; instead. For open-braces not the first thing in a line, + ;; add in c-brace-imaginary-offset. + (+ (if (and (bolp) (zerop c-indent-level)) + (+ c-brace-offset c-continued-statement-offset) + c-indent-level) + ;; Move back over whitespace before the openbrace. If + ;; openbrace is not first nonwhite thing on the line, + ;; add the c-brace-imaginary-offset. + (progn (skip-chars-backward " \t") + (if (bolp) 0 c-brace-imaginary-offset)) + ;; If the openbrace is preceded by a parenthesized exp, + ;; move to the beginning of that; possibly a different + ;; line + (progn + (if (eq (char-before) ?\)) + (c-forward-sexp -1)) + ;; Get initial indentation of the line we are on. + (current-indentation))))) + (- bocm-lossage curcol)))) + + +(defun cc-block-close-offset (langelem) + (save-excursion + (let* ((here (point)) + bracep + (curcol (progn + (goto-char (cdr langelem)) + (current-column))) + (bocm-lossage (progn + (goto-char (cdr langelem)) + (if (eq (char-after) ?{) + (setq bracep t) + (goto-char here) + (beginning-of-line) + (backward-up-list 1) + (forward-char 1) + (c-forward-syntactic-ws)) + (current-column)))) + (- bocm-lossage curcol + (if bracep 0 c-indent-level))))) + + +(defun cc-substatement-open-offset (langelem) + (+ c-continued-statement-offset c-continued-brace-offset)) + + +(cc-provide 'cc-compat) + +;;; arch-tag: 564dab2f-e6ad-499c-a4a3-fedec3ecc192 +;;; cc-compat.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-defs.el b/site-lisp/cc-mode/5.32.3/cc-defs.el new file mode 100644 index 0000000..531f3ad --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-defs.el @@ -0,0 +1,2446 @@ +;;; cc-defs.el --- compile time definitions for CC Mode + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2003- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 22-Apr-1997 (split from cc-mode.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; This file contains macros, defsubsts, and various other things that +;; must be loaded early both during compilation and at runtime. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-external-require 'cl) +(cc-external-require 'regexp-opt) + +;; Silence the compiler. +(cc-bytecomp-defvar c-enable-xemacs-performance-kludge-p) ; In cc-vars.el +(cc-bytecomp-defun buffer-syntactic-context-depth) ; XEmacs +(cc-bytecomp-defun region-active-p) ; XEmacs +(cc-bytecomp-defvar zmacs-region-stays) ; XEmacs +(cc-bytecomp-defvar zmacs-regions) ; XEmacs +(cc-bytecomp-defvar mark-active) ; Emacs +(cc-bytecomp-defvar deactivate-mark) ; Emacs +(cc-bytecomp-defvar inhibit-point-motion-hooks) ; Emacs +(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs +(cc-bytecomp-defvar text-property-default-nonsticky) ; Emacs 21 +(cc-bytecomp-defvar lookup-syntax-properties) ; XEmacs +(cc-bytecomp-defun string-to-syntax) ; Emacs 21 + + +;; cc-fix.el contains compatibility macros that should be used if +;; needed. +(eval-and-compile + (if (or (/= (regexp-opt-depth "\\(\\(\\)\\)") 2) + (not (fboundp 'push))) + (cc-load "cc-fix"))) + +(eval-after-load "font-lock" + '(if (and (not (featurep 'cc-fix)) ; only load the file once. + (featurep 'xemacs) ; There is now (2005/12) code in GNU Emacs CVS + ; to make the call to f-l-c-k throw an error. + (let (font-lock-keywords) + (font-lock-compile-keywords '("\\<\\>")) + font-lock-keywords)) ; did the previous call foul this up? + (load "cc-fix"))) + +;; The above takes care of the delayed loading, but this is necessary +;; to ensure correct byte compilation. +(eval-when-compile + (if (and (featurep 'xemacs) + (not (featurep 'cc-fix)) + (progn + (require 'font-lock) + (let (font-lock-keywords) + (font-lock-compile-keywords '("\\<\\>")) + font-lock-keywords))) + (cc-load "cc-fix"))) + +;; XEmacs 21.4 doesn't have `delete-dups'. +(eval-and-compile + (if (and (not (fboundp 'delete-dups)) + (not (featurep 'cc-fix))) + (cc-load "cc-fix"))) + +;;; Variables also used at compile time. + +(defconst c-version "5.32.3" + "CC Mode version number.") + +(defconst c-version-sym (intern c-version)) +;; A little more compact and faster in comparisons. + +(defvar c-buffer-is-cc-mode nil + "Non-nil for all buffers with a major mode derived from CC Mode. +Otherwise, this variable is nil. I.e. this variable is non-nil for +`c-mode', `c++-mode', `objc-mode', `java-mode', `idl-mode', +`pike-mode', `awk-mode', and any other non-CC Mode mode that calls +`c-initialize-cc-mode'. The value is the mode symbol itself +\(i.e. `c-mode' etc) of the original CC Mode mode, or just t if it's +not known.") +(make-variable-buffer-local 'c-buffer-is-cc-mode) + +;; Have to make `c-buffer-is-cc-mode' permanently local so that it +;; survives the initialization of the derived mode. +(put 'c-buffer-is-cc-mode 'permanent-local t) + + +;; The following is used below during compilation. +(eval-and-compile + (defvar c-inside-eval-when-compile nil) + + (defmacro cc-eval-when-compile (&rest body) + "Like `progn', but evaluates the body at compile time. +The result of the body appears to the compiler as a quoted constant. + +This variant works around bugs in `eval-when-compile' in various +\(X)Emacs versions. See cc-defs.el for details." + + (if c-inside-eval-when-compile + ;; XEmacs 21.4.6 has a bug in `eval-when-compile' in that it + ;; evaluates its body at macro expansion time if it's nested + ;; inside another `eval-when-compile'. So we use a dynamically + ;; bound variable to avoid nesting them. + `(progn ,@body) + + `(eval-when-compile + ;; In all (X)Emacsen so far, `eval-when-compile' byte compiles + ;; its contents before evaluating it. That can cause forms to + ;; be compiled in situations they aren't intended to be + ;; compiled. + ;; + ;; Example: It's not possible to defsubst a primitive, e.g. the + ;; following will produce an error (in any emacs flavor), since + ;; `nthcdr' is a primitive function that's handled specially by + ;; the byte compiler and thus can't be redefined: + ;; + ;; (defsubst nthcdr (val) val) + ;; + ;; `defsubst', like `defmacro', needs to be evaluated at + ;; compile time, so this will produce an error during byte + ;; compilation. + ;; + ;; CC Mode occasionally needs to do things like this for + ;; cross-emacs compatibility. It therefore uses the following + ;; to conditionally do a `defsubst': + ;; + ;; (eval-when-compile + ;; (if (not (fboundp 'foo)) + ;; (defsubst foo ...))) + ;; + ;; But `eval-when-compile' byte compiles its contents and + ;; _then_ evaluates it (in all current emacs versions, up to + ;; and including Emacs 20.6 and XEmacs 21.1 as of this + ;; writing). So this will still produce an error, since the + ;; byte compiler will get to the defsubst anyway. That's + ;; arguably a bug because the point with `eval-when-compile' is + ;; that it should evaluate rather than compile its contents. + ;; + ;; We get around it by expanding the body to a quoted + ;; constant that we eval. That otoh introduce a problem in + ;; that a returned lambda expression doesn't get byte + ;; compiled (even if `function' is used). + (eval '(let ((c-inside-eval-when-compile t)) ,@body))))) + + (put 'cc-eval-when-compile 'lisp-indent-hook 0)) + + +;;; Macros. + +(defmacro c-point (position &optional point) + "Return the value of certain commonly referenced POSITIONs relative to POINT. +The current point is used if POINT isn't specified. POSITION can be +one of the following symbols: + +`bol' -- beginning of line +`eol' -- end of line +`bod' -- beginning of defun +`eod' -- end of defun +`boi' -- beginning of indentation +`ionl' -- indentation of next line +`iopl' -- indentation of previous line +`bonl' -- beginning of next line +`eonl' -- end of next line +`bopl' -- beginning of previous line +`eopl' -- end of previous line +`bosws' -- beginning of syntactic whitespace +`eosws' -- end of syntactic whitespace + +If the referenced position doesn't exist, the closest accessible point +to it is returned. This function does not modify the point or the mark." + + (if (eq (car-safe position) 'quote) + (let ((position (eval position))) + (cond + + ((eq position 'bol) + (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point)) + `(line-beginning-position) + `(save-excursion + ,@(if point `((goto-char ,point))) + (beginning-of-line) + (point)))) + + ((eq position 'eol) + (if (and (cc-bytecomp-fboundp 'line-end-position) (not point)) + `(line-end-position) + `(save-excursion + ,@(if point `((goto-char ,point))) + (end-of-line) + (point)))) + + ((eq position 'boi) + `(save-excursion + ,@(if point `((goto-char ,point))) + (back-to-indentation) + (point))) + + ((eq position 'bod) + `(save-excursion + ,@(if point `((goto-char ,point))) + (c-beginning-of-defun-1) + (point))) + + ((eq position 'eod) + `(save-excursion + ,@(if point `((goto-char ,point))) + (c-end-of-defun-1) + (point))) + + ((eq position 'bopl) + (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point)) + `(line-beginning-position 0) + `(save-excursion + ,@(if point `((goto-char ,point))) + (forward-line -1) + (point)))) + + ((eq position 'bonl) + (if (and (cc-bytecomp-fboundp 'line-beginning-position) (not point)) + `(line-beginning-position 2) + `(save-excursion + ,@(if point `((goto-char ,point))) + (forward-line 1) + (point)))) + + ((eq position 'eopl) + (if (and (cc-bytecomp-fboundp 'line-end-position) (not point)) + `(line-end-position 0) + `(save-excursion + ,@(if point `((goto-char ,point))) + (beginning-of-line) + (or (bobp) (backward-char)) + (point)))) + + ((eq position 'eonl) + (if (and (cc-bytecomp-fboundp 'line-end-position) (not point)) + `(line-end-position 2) + `(save-excursion + ,@(if point `((goto-char ,point))) + (forward-line 1) + (end-of-line) + (point)))) + + ((eq position 'iopl) + `(save-excursion + ,@(if point `((goto-char ,point))) + (forward-line -1) + (back-to-indentation) + (point))) + + ((eq position 'ionl) + `(save-excursion + ,@(if point `((goto-char ,point))) + (forward-line 1) + (back-to-indentation) + (point))) + + ((eq position 'bosws) + `(save-excursion + ,@(if point `((goto-char ,point))) + (c-backward-syntactic-ws) + (point))) + + ((eq position 'eosws) + `(save-excursion + ,@(if point `((goto-char ,point))) + (c-forward-syntactic-ws) + (point))) + + (t (error "Unknown buffer position requested: %s" position)))) + + ;; The bulk of this should perhaps be in a function to avoid large + ;; expansions, but this case is not used anywhere in CC Mode (and + ;; probably not anywhere else either) so we only have it to be on + ;; the safe side. + (message "Warning: c-point long expansion") + `(save-excursion + ,@(if point `((goto-char ,point))) + (let ((position ,position)) + (cond + ((eq position 'bol) (beginning-of-line)) + ((eq position 'eol) (end-of-line)) + ((eq position 'boi) (back-to-indentation)) + ((eq position 'bod) (c-beginning-of-defun-1)) + ((eq position 'eod) (c-end-of-defun-1)) + ((eq position 'bopl) (forward-line -1)) + ((eq position 'bonl) (forward-line 1)) + ((eq position 'eopl) (progn + (beginning-of-line) + (or (bobp) (backward-char)))) + ((eq position 'eonl) (progn + (forward-line 1) + (end-of-line))) + ((eq position 'iopl) (progn + (forward-line -1) + (back-to-indentation))) + ((eq position 'ionl) (progn + (forward-line 1) + (back-to-indentation))) + ((eq position 'bosws) (c-backward-syntactic-ws)) + ((eq position 'eosws) (c-forward-syntactic-ws)) + (t (error "Unknown buffer position requested: %s" position)))) + (point)))) + +(defmacro c-next-single-property-change (position prop &optional object limit) + ;; See the doc string for either of the defuns expanded to. + (if (and c-use-extents + (fboundp 'next-single-char-property-change)) + ;; XEmacs >= 2005-01-25 + `(next-single-char-property-change ,position ,prop ,object ,limit) + ;; Emacs and earlier XEmacs + `(next-single-property-change ,position ,prop ,object ,limit))) + +(defmacro c-region-is-active-p () + ;; Return t when the region is active. The determination of region + ;; activeness is different in both Emacs and XEmacs. + (if (cc-bytecomp-fboundp 'region-active-p) + ;; XEmacs. + '(region-active-p) + ;; Emacs. + 'mark-active)) + +(defmacro c-set-region-active (activate) + ;; Activate the region if ACTIVE is non-nil, deactivate it + ;; otherwise. Covers the differences between Emacs and XEmacs. + (if (cc-bytecomp-fboundp 'zmacs-activate-region) + ;; XEmacs. + `(if ,activate + (zmacs-activate-region) + (zmacs-deactivate-region)) + ;; Emacs. + `(setq mark-active ,activate))) + +(defmacro c-delete-and-extract-region (start end) + "Delete the text between START and END and return it." + (if (cc-bytecomp-fboundp 'delete-and-extract-region) + ;; Emacs 21.1 and later + `(delete-and-extract-region ,start ,end) + ;; XEmacs and Emacs 20.x + `(prog1 + (buffer-substring ,start ,end) + (delete-region ,start ,end)))) + +(defmacro c-safe (&rest body) + ;; safely execute BODY, return nil if an error occurred + `(condition-case nil + (progn ,@body) + (error nil))) +(put 'c-safe 'lisp-indent-function 0) + +(defmacro c-int-to-char (integer) + ;; In GNU Emacs, a character is an integer. In XEmacs, a character is a + ;; type distinct from an integer. Sometimes we need to convert integers to + ;; characters. `c-int-to-char' makes this conversion, if necessary. + (if (fboundp 'int-to-char) + `(int-to-char ,integer) + integer)) + +(defmacro c-sentence-end () + ;; Get the regular expression `sentence-end'. + (if (cc-bytecomp-fboundp 'sentence-end) + ;; Emacs 22: + `(sentence-end) + ;; Emacs <22 + XEmacs + `sentence-end)) + +(defmacro c-default-value-sentence-end () + ;; Get the default value of the variable sentence end. + (if (cc-bytecomp-fboundp 'sentence-end) + ;; Emacs 22: + `(let (sentence-end) (sentence-end)) + ;; Emacs <22 + XEmacs + `(default-value 'sentence-end))) + +;; The following is essentially `save-buffer-state' from lazy-lock.el. +;; It ought to be a standard macro. +(defmacro c-save-buffer-state (varlist &rest body) + "Bind variables according to VARLIST (in `let*' style) and eval BODY, +then restore the buffer state under the assumption that no significant +modification has been made in BODY. A change is considered +significant if it affects the buffer text in any way that isn't +completely restored again. Changes in text properties like `face' or +`syntax-table' are considered insignificant. This macro allows text +properties to be changed, even in a read-only buffer. + +This macro should be placed around all calculations which set +\"insignificant\" text properties in a buffer, even when the buffer is +known to be writeable. That way, these text properties remain set +even if the user undoes the command which set them. + +This macro should ALWAYS be placed around \"temporary\" internal buffer +changes \(like adding a newline to calculate a text-property then +deleting it again\), so that the user never sees them on his +`buffer-undo-list'. See also `c-tentative-buffer-changes'. + +However, any user-visible changes to the buffer \(like auto-newlines\) +must not be within a `c-save-buffer-state', since the user then +wouldn't be able to undo them. + +The return value is the value of the last form in BODY." + `(let* ((modified (buffer-modified-p)) (buffer-undo-list t) + (inhibit-read-only t) (inhibit-point-motion-hooks t) + before-change-functions after-change-functions + deactivate-mark + buffer-file-name buffer-file-truename ; Prevent primitives checking + ; for file modification + ,@varlist) + (unwind-protect + (progn ,@body) + (and (not modified) + (buffer-modified-p) + (set-buffer-modified-p nil))))) +(put 'c-save-buffer-state 'lisp-indent-function 1) + +(defmacro c-tentative-buffer-changes (&rest body) + "Eval BODY and optionally restore the buffer contents to the state it +was in before BODY. Any changes are kept if the last form in BODY +returns non-nil. Otherwise it's undone using the undo facility, and +various other buffer state that might be affected by the changes is +restored. That includes the current buffer, point, mark, mark +activation \(similar to `save-excursion'), and the modified state. +The state is also restored if BODY exits nonlocally. + +If BODY makes a change that unconditionally is undone then wrap this +macro inside `c-save-buffer-state'. That way the change can be done +even when the buffer is read-only, and without interference from +various buffer change hooks." + `(let (-tnt-chng-keep + -tnt-chng-state) + (unwind-protect + ;; Insert an undo boundary for use with `undo-more'. We + ;; don't use `undo-boundary' since it doesn't insert one + ;; unconditionally. + (setq buffer-undo-list (cons nil buffer-undo-list) + -tnt-chng-state (c-tnt-chng-record-state) + -tnt-chng-keep (progn ,@body)) + (c-tnt-chng-cleanup -tnt-chng-keep -tnt-chng-state)))) +(put 'c-tentative-buffer-changes 'lisp-indent-function 0) + +(defun c-tnt-chng-record-state () + ;; Used internally in `c-tentative-buffer-changes'. + (vector buffer-undo-list ; 0 + (current-buffer) ; 1 + ;; No need to use markers for the point and mark; if the + ;; undo got out of synch we're hosed anyway. + (point) ; 2 + (mark t) ; 3 + (c-region-is-active-p) ; 4 + (buffer-modified-p))) ; 5 + +(defun c-tnt-chng-cleanup (keep saved-state) + ;; Used internally in `c-tentative-buffer-changes'. + + (let ((saved-undo-list (elt saved-state 0))) + (if (eq buffer-undo-list saved-undo-list) + ;; No change was done afterall. + (setq buffer-undo-list (cdr saved-undo-list)) + + (if keep + ;; Find and remove the undo boundary. + (let ((p buffer-undo-list)) + (while (not (eq (cdr p) saved-undo-list)) + (setq p (cdr p))) + (setcdr p (cdr saved-undo-list))) + + ;; `primitive-undo' will remove the boundary. + (setq saved-undo-list (cdr saved-undo-list)) + (let ((undo-in-progress t)) + (while (not (eq (setq buffer-undo-list + (primitive-undo 1 buffer-undo-list)) + saved-undo-list)))) + + (when (buffer-live-p (elt saved-state 1)) + (set-buffer (elt saved-state 1)) + (goto-char (elt saved-state 2)) + (set-mark (elt saved-state 3)) + (c-set-region-active (elt saved-state 4)) + (and (not (elt saved-state 5)) + (buffer-modified-p) + (set-buffer-modified-p nil))))))) + +(defmacro c-forward-syntactic-ws (&optional limit) + "Forward skip over syntactic whitespace. +Syntactic whitespace is defined as whitespace characters, comments, +and preprocessor directives. However if point starts inside a comment +or preprocessor directive, the content of it is not treated as +whitespace. + +LIMIT sets an upper limit of the forward movement, if specified. If +LIMIT or the end of the buffer is reached inside a comment or +preprocessor directive, the point will be left there. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (if limit + `(save-restriction + (narrow-to-region (point-min) (or ,limit (point-max))) + (c-forward-sws)) + '(c-forward-sws))) + +(defmacro c-backward-syntactic-ws (&optional limit) + "Backward skip over syntactic whitespace. +Syntactic whitespace is defined as whitespace characters, comments, +and preprocessor directives. However if point starts inside a comment +or preprocessor directive, the content of it is not treated as +whitespace. + +LIMIT sets a lower limit of the backward movement, if specified. If +LIMIT is reached inside a line comment or preprocessor directive then +the point is moved into it past the whitespace at the end. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (if limit + `(save-restriction + (narrow-to-region (or ,limit (point-min)) (point-max)) + (c-backward-sws)) + '(c-backward-sws))) + +(defmacro c-forward-sexp (&optional count) + "Move forward across COUNT balanced expressions. +A negative COUNT means move backward. Signal an error if the move +fails for any reason. + +This is like `forward-sexp' except that it isn't interactive and does +not do any user friendly adjustments of the point and that it isn't +susceptible to user configurations such as disabling of signals in +certain situations." + (or count (setq count 1)) + `(goto-char (scan-sexps (point) ,count))) + +(defmacro c-backward-sexp (&optional count) + "See `c-forward-sexp' and reverse directions." + (or count (setq count 1)) + `(c-forward-sexp ,(if (numberp count) (- count) `(- ,count)))) + +(defmacro c-safe-scan-lists (from count depth &optional limit) + "Like `scan-lists' but returns nil instead of signalling errors +for unbalanced parens. + +A limit for the search may be given. FROM is assumed to be on the +right side of it." + (let ((res (if (featurep 'xemacs) + `(scan-lists ,from ,count ,depth nil t) + `(c-safe (scan-lists ,from ,count ,depth))))) + (if limit + `(save-restriction + ,(if (numberp count) + (if (< count 0) + `(narrow-to-region ,limit (point-max)) + `(narrow-to-region (point-min) ,limit)) + `(if (< ,count 0) + (narrow-to-region ,limit (point-max)) + (narrow-to-region (point-min) ,limit))) + ,res) + res))) + + +;; Wrappers for common scan-lists cases, mainly because it's almost +;; impossible to get a feel for how that function works. + +(defmacro c-go-list-forward () + "Move backward across one balanced group of parentheses. + +Return POINT when we succeed, NIL when we fail. In the latter case, leave +point unmoved." + `(c-safe (let ((endpos (scan-lists (point) 1 0))) + (goto-char endpos) + endpos))) + +(defmacro c-go-list-backward () + "Move backward across one balanced group of parentheses. + +Return POINT when we succeed, NIL when we fail. In the latter case, leave +point unmoved." + `(c-safe (let ((endpos (scan-lists (point) -1 0))) + (goto-char endpos) + endpos))) + +(defmacro c-up-list-forward (&optional pos limit) + "Return the first position after the list sexp containing POS, +or nil if no such position exists. The point is used if POS is left out. + +A limit for the search may be given. The start position is assumed to +be before it." + `(c-safe-scan-lists ,(or pos `(point)) 1 1 ,limit)) + +(defmacro c-up-list-backward (&optional pos limit) + "Return the position of the start of the list sexp containing POS, +or nil if no such position exists. The point is used if POS is left out. + +A limit for the search may be given. The start position is assumed to +be after it." + `(c-safe-scan-lists ,(or pos `(point)) -1 1 ,limit)) + +(defmacro c-down-list-forward (&optional pos limit) + "Return the first position inside the first list sexp after POS, +or nil if no such position exists. The point is used if POS is left out. + +A limit for the search may be given. The start position is assumed to +be before it." + `(c-safe-scan-lists ,(or pos `(point)) 1 -1 ,limit)) + +(defmacro c-down-list-backward (&optional pos limit) + "Return the last position inside the last list sexp before POS, +or nil if no such position exists. The point is used if POS is left out. + +A limit for the search may be given. The start position is assumed to +be after it." + `(c-safe-scan-lists ,(or pos `(point)) -1 -1 ,limit)) + +(defmacro c-go-up-list-forward (&optional pos limit) + "Move the point to the first position after the list sexp containing POS, +or containing the point if POS is left out. Return t if such a +position exists, otherwise nil is returned and the point isn't moved. + +A limit for the search may be given. The start position is assumed to +be before it." + (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 1)) t))) + (if limit + `(save-restriction + (narrow-to-region (point-min) ,limit) + ,res) + res))) + +(defmacro c-go-up-list-backward (&optional pos limit) + "Move the point to the position of the start of the list sexp containing POS, +or containing the point if POS is left out. Return t if such a +position exists, otherwise nil is returned and the point isn't moved. + +A limit for the search may be given. The start position is assumed to +be after it." + (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 1)) t))) + (if limit + `(save-restriction + (narrow-to-region ,limit (point-max)) + ,res) + res))) + +(defmacro c-go-down-list-forward (&optional pos limit) + "Move the point to the first position inside the first list sexp after POS, +or before the point if POS is left out. Return t if such a position +exists, otherwise nil is returned and the point isn't moved. + +A limit for the search may be given. The start position is assumed to +be before it." + (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) 1 -1)) t))) + (if limit + `(save-restriction + (narrow-to-region (point-min) ,limit) + ,res) + res))) + +(defmacro c-go-down-list-backward (&optional pos limit) + "Move the point to the last position inside the last list sexp before POS, +or before the point if POS is left out. Return t if such a position +exists, otherwise nil is returned and the point isn't moved. + +A limit for the search may be given. The start position is assumed to +be after it." + (let ((res `(c-safe (goto-char (scan-lists ,(or pos `(point)) -1 -1)) t))) + (if limit + `(save-restriction + (narrow-to-region ,limit (point-max)) + ,res) + res))) + + +(defmacro c-beginning-of-defun-1 () + ;; Wrapper around beginning-of-defun. + ;; + ;; NOTE: This function should contain the only explicit use of + ;; beginning-of-defun in CC Mode. Eventually something better than + ;; b-o-d will be available and this should be the only place the + ;; code needs to change. Everything else should use + ;; (c-beginning-of-defun-1) + ;; + ;; This is really a bit too large to be a macro but that isn't a + ;; problem as long as it only is used in one place in + ;; `c-parse-state'. + + `(progn + (if (and ,(cc-bytecomp-fboundp 'buffer-syntactic-context-depth) + c-enable-xemacs-performance-kludge-p) + ,(when (cc-bytecomp-fboundp 'buffer-syntactic-context-depth) + ;; XEmacs only. This can improve the performance of + ;; c-parse-state to between 3 and 60 times faster when + ;; braces are hung. It can also degrade performance by + ;; about as much when braces are not hung. + '(let (beginning-of-defun-function end-of-defun-function + pos) + (while (not pos) + (save-restriction + (widen) + (setq pos (c-safe-scan-lists + (point) -1 (buffer-syntactic-context-depth)))) + (cond + ((bobp) (setq pos (point-min))) + ((not pos) + (let ((distance (skip-chars-backward "^{"))) + ;; unbalanced parenthesis, while invalid C code, + ;; shouldn't cause an infloop! See unbal.c + (when (zerop distance) + ;; Punt! + (beginning-of-defun) + (setq pos (point))))) + ((= pos 0)) + ((not (eq (char-after pos) ?{)) + (goto-char pos) + (setq pos nil)) + )) + (goto-char pos))) + ;; Emacs, which doesn't have buffer-syntactic-context-depth + (let (beginning-of-defun-function end-of-defun-function) + (beginning-of-defun))) + ;; if defun-prompt-regexp is non-nil, b-o-d won't leave us at the + ;; open brace. + (and defun-prompt-regexp + (looking-at defun-prompt-regexp) + (goto-char (match-end 0))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; V i r t u a l S e m i c o l o n s +;; +;; In most CC Mode languages, statements are terminated explicitly by +;; semicolons or closing braces. In some of the CC modes (currently AWK Mode +;; and certain user-specified #define macros in C, C++, etc. (November 2008)), +;; statements are (or can be) terminated by EOLs. Such a statement is said to +;; be terminated by a "virtual semicolon" (VS). A statement terminated by an +;; actual semicolon or brace is never considered to have a VS. +;; +;; The indentation engine (or whatever) tests for a VS at a specific position +;; by invoking the macro `c-at-vsemi-p', which in its turn calls the mode +;; specific function (if any) which is the value of the language variable +;; `c-at-vsemi-p-fn'. This function should only use "low-level" features of +;; CC Mode, i.e. features which won't trigger infinite recursion. ;-) The +;; actual details of what constitutes a VS in a language are thus encapsulated +;; in code specific to that language (e.g. cc-awk.el). `c-at-vsemi-p' returns +;; non-nil if point (or the optional parameter POS) is at a VS, nil otherwise. +;; +;; The language specific function might well do extensive analysis of the +;; source text, and may use a cacheing scheme to speed up repeated calls. +;; +;; The "virtual semicolon" lies just after the last non-ws token on the line. +;; Like POINT, it is considered to lie between two characters. For example, +;; at the place shown in the following AWK source line: +;; +;; kbyte = 1024 # 1000 if you're not picky +;; ^ +;; | +;; Virtual Semicolon +;; +;; In addition to `c-at-vsemi-p-fn', a mode may need to supply a function for +;; `c-vsemi-status-unknown-p-fn'. The macro `c-vsemi-status-unknown-p' is a +;; rather recondite kludge. It exists because the function +;; `c-beginning-of-statement-1' sometimes tests for VSs as an optimisation, +;; but `c-at-vsemi-p' might well need to call `c-beginning-of-statement-1' in +;; its calculations, thus potentially leading to infinite recursion. +;; +;; The macro `c-vsemi-status-unknown-p' resolves this problem; it may return +;; non-nil at any time; returning nil is a guarantee that an immediate +;; invocation of `c-at-vsemi-p' at point will NOT call +;; `c-beginning-of-statement-1'. `c-vsemi-status-unknown-p' may not itself +;; call `c-beginning-of-statement-1'. +;; +;; The macro `c-vsemi-status-unknown-p' will typically check the cacheing +;; scheme used by the `c-at-vsemi-p-fn', hence the name - the status is +;; "unknown" if there is no cache entry current for the line. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defmacro c-at-vsemi-p (&optional pos) + ;; Is there a virtual semicolon (not a real one or a }) at POS (defaults to + ;; point)? Always returns nil for languages which don't have Virtual + ;; semicolons. + ;; This macro might do hidden buffer changes. + `(if c-at-vsemi-p-fn + (funcall c-at-vsemi-p-fn ,@(if pos `(,pos))))) + +(defmacro c-vsemi-status-unknown-p () + ;; Return NIL only if it can be guaranteed that an immediate + ;; (c-at-vsemi-p) will NOT call c-beginning-of-statement-1. Otherwise, + ;; return non-nil. (See comments above). The function invoked by this + ;; macro MUST NOT UNDER ANY CIRCUMSTANCES itself call + ;; c-beginning-of-statement-1. + ;; Languages which don't have EOL terminated statements always return NIL + ;; (they _know_ there's no vsemi ;-). + `(if c-vsemi-status-unknown-p-fn (funcall c-vsemi-status-unknown-p-fn))) + + +(defmacro c-benign-error (format &rest args) + ;; Formats an error message for the echo area and dings, i.e. like + ;; `error' but doesn't abort. + `(progn + (message ,format ,@args) + (ding))) + +(defmacro c-with-syntax-table (table &rest code) + ;; Temporarily switches to the specified syntax table in a failsafe + ;; way to execute code. + `(let ((c-with-syntax-table-orig-table (syntax-table))) + (unwind-protect + (progn + (set-syntax-table ,table) + ,@code) + (set-syntax-table c-with-syntax-table-orig-table)))) +(put 'c-with-syntax-table 'lisp-indent-function 1) + +(defmacro c-skip-ws-forward (&optional limit) + "Skip over any whitespace following point. +This function skips over horizontal and vertical whitespace and line +continuations." + (if limit + `(let ((limit (or ,limit (point-max)))) + (while (progn + ;; skip-syntax-* doesn't count \n as whitespace.. + (skip-chars-forward " \t\n\r\f\v" limit) + (when (and (eq (char-after) ?\\) + (< (point) limit)) + (forward-char) + (or (eolp) + (progn (backward-char) nil)))))) + '(while (progn + (skip-chars-forward " \t\n\r\f\v") + (when (eq (char-after) ?\\) + (forward-char) + (or (eolp) + (progn (backward-char) nil))))))) + +(defmacro c-skip-ws-backward (&optional limit) + "Skip over any whitespace preceding point. +This function skips over horizontal and vertical whitespace and line +continuations." + (if limit + `(let ((limit (or ,limit (point-min)))) + (while (progn + ;; skip-syntax-* doesn't count \n as whitespace.. + (skip-chars-backward " \t\n\r\f\v" limit) + (and (eolp) + (eq (char-before) ?\\) + (> (point) limit))) + (backward-char))) + '(while (progn + (skip-chars-backward " \t\n\r\f\v") + (and (eolp) + (eq (char-before) ?\\))) + (backward-char)))) + +(eval-and-compile + (defvar c-langs-are-parametric nil)) + +(defmacro c-major-mode-is (mode) + "Return non-nil if the current CC Mode major mode is MODE. +MODE is either a mode symbol or a list of mode symbols." + + (if c-langs-are-parametric + ;; Inside a `c-lang-defconst'. + `(c-lang-major-mode-is ,mode) + + (if (eq (car-safe mode) 'quote) + (let ((mode (eval mode))) + (if (listp mode) + `(memq c-buffer-is-cc-mode ',mode) + `(eq c-buffer-is-cc-mode ',mode))) + + `(let ((mode ,mode)) + (if (listp mode) + (memq c-buffer-is-cc-mode mode) + (eq c-buffer-is-cc-mode mode)))))) + + +;; Macros/functions to handle so-called "char properties", which are +;; properties set on a single character and that never spread to any +;; other characters. + +(eval-and-compile + ;; Constant used at compile time to decide whether or not to use + ;; XEmacs extents. Check all the extent functions we'll use since + ;; some packages might add compatibility aliases for some of them in + ;; Emacs. + (defconst c-use-extents (and (cc-bytecomp-fboundp 'extent-at) + (cc-bytecomp-fboundp 'set-extent-property) + (cc-bytecomp-fboundp 'set-extent-properties) + (cc-bytecomp-fboundp 'make-extent) + (cc-bytecomp-fboundp 'extent-property) + (cc-bytecomp-fboundp 'delete-extent) + (cc-bytecomp-fboundp 'map-extents)))) + +(defconst c-<-as-paren-syntax '(4 . ?>)) +(put 'c-<-as-paren-syntax 'syntax-table c-<-as-paren-syntax) + +(defconst c->-as-paren-syntax '(5 . ?<)) +(put 'c->-as-paren-syntax 'syntax-table c->-as-paren-syntax) + +;; `c-put-char-property' is complex enough in XEmacs and Emacs < 21 to +;; make it a function. +(eval-and-compile + (defalias 'c-put-char-property-fun + (cc-eval-when-compile + (cond (c-use-extents + ;; XEmacs. + (byte-compile + (lambda (pos property value) + (let ((ext (extent-at pos nil property))) + (if ext + (set-extent-property ext property value) + (set-extent-properties (make-extent pos (1+ pos)) + (cons property + (cons value + '(start-open t + end-open t))))))))) + + ((not (cc-bytecomp-boundp 'text-property-default-nonsticky)) + ;; In Emacs < 21 we have to mess with the `rear-nonsticky' property. + (byte-compile + (lambda (pos property value) + (put-text-property pos (1+ pos) property value) + (let ((prop (get-text-property pos 'rear-nonsticky))) + (or (memq property prop) + (put-text-property pos (1+ pos) + 'rear-nonsticky + (cons property prop))))))))))) +(cc-bytecomp-defun c-put-char-property-fun) ; Make it known below. + +(eval-and-compile + (defmacro c-put-char-property (pos property value) + ;; Put the given property with the given value on the character at + ;; POS and make it front and rear nonsticky, or start and end open + ;; in XEmacs vocabulary. If the character already has the given + ;; property then the value is replaced, and the behavior is + ;; undefined if that property has been put by some other function. + ;; PROPERTY is assumed to be constant. + ;; + ;; If there's a `text-property-default-nonsticky' variable (Emacs + ;; 21) then it's assumed that the property is present on it. + ;; + ;; This macro does a hidden buffer change. + (setq property (eval property)) + (if (or c-use-extents + (not (cc-bytecomp-boundp 'text-property-default-nonsticky))) + ;; XEmacs and Emacs < 21. + `(c-put-char-property-fun ,pos ',property ,value) + ;; In Emacs 21 we got the `rear-nonsticky' property covered + ;; by `text-property-default-nonsticky'. + `(let ((-pos- ,pos)) + (put-text-property -pos- (1+ -pos-) ',property ,value))))) + +(eval-and-compile + ;; Constant to decide at compilation time whether to use category + ;; properties. Currently (2010-03) they're available only on GNU Emacs. + (defconst c-use-category + (let ((buf (generate-new-buffer " test")) + parse-sexp-lookup-properties lookup-syntax-properties) + (prog1 + (save-excursion + (set-buffer buf) + (setq parse-sexp-lookup-properties t) + (setq lookup-syntax-properties t) + (set-syntax-table (make-syntax-table)) + (insert "<()>") + (c-put-char-property (point-min) 'category 'c-<-as-paren-syntax) + (c-put-char-property (+ 3 (point-min)) 'category 'c->-as-paren-syntax) + (goto-char (point-min)) + (forward-sexp) + (= (point) (+ 4 (point-min)))) + (kill-buffer buf))))) + +(defmacro c-get-char-property (pos property) + ;; Get the value of the given property on the character at POS if + ;; it's been put there by `c-put-char-property'. PROPERTY is + ;; assumed to be constant. + (setq property (eval property)) + (if c-use-extents + ;; XEmacs. + `(let ((ext (extent-at ,pos nil ',property))) + (if ext (extent-property ext ',property))) + ;; Emacs. + `(get-text-property ,pos ',property))) + +;; `c-clear-char-property' is complex enough in Emacs < 21 to make it +;; a function, since we have to mess with the `rear-nonsticky' property. +(defalias 'c-clear-char-property-fun + (cc-eval-when-compile + (unless (or c-use-extents + (cc-bytecomp-boundp 'text-property-default-nonsticky)) + (byte-compile + (lambda (pos property) + (when (get-text-property pos property) + (remove-text-properties pos (1+ pos) (list property nil)) + (put-text-property pos (1+ pos) + 'rear-nonsticky + (delq property (get-text-property + pos 'rear-nonsticky))))))))) +(cc-bytecomp-defun c-clear-char-property-fun) ; Make it known below. + +(defmacro c-clear-char-property (pos property) + ;; Remove the given property on the character at POS if it's been put + ;; there by `c-put-char-property'. PROPERTY is assumed to be + ;; constant. + ;; + ;; This macro does a hidden buffer change. + (setq property (eval property)) + (cond (c-use-extents + ;; XEmacs. + `(let ((ext (extent-at ,pos nil ',property))) + (if ext (delete-extent ext)))) + ((cc-bytecomp-boundp 'text-property-default-nonsticky) + ;; In Emacs 21 we got the `rear-nonsticky' property covered + ;; by `text-property-default-nonsticky'. + `(let ((pos ,pos)) + (remove-text-properties pos (1+ pos) + '(,property nil)))) + (t + ;; Emacs < 21. + `(c-clear-char-property-fun ,pos ',property)))) + +(defmacro c-clear-char-properties (from to property) + ;; Remove all the occurences of the given property in the given + ;; region that has been put with `c-put-char-property'. PROPERTY is + ;; assumed to be constant. + ;; + ;; Note that this function does not clean up the property from the + ;; lists of the `rear-nonsticky' properties in the region, if such + ;; are used. Thus it should not be used for common properties like + ;; `syntax-table'. + ;; + ;; This macro does hidden buffer changes. + (setq property (eval property)) + (if c-use-extents + ;; XEmacs. + `(map-extents (lambda (ext ignored) + (delete-extent ext)) + nil ,from ,to nil nil ',property) + ;; Emacs. + `(remove-text-properties ,from ,to '(,property nil)))) + +(defmacro c-search-forward-char-property (property value &optional limit) + "Search forward for a text-property PROPERTY having value VALUE. +LIMIT bounds the search. The comparison is done with `equal'. + +Leave point just after the character, and set the match data on +this character, and return point. If VALUE isn't found, Return +nil; point is then left undefined." + `(let ((place (point))) + (while + (and + (< place ,(or limit '(point-max))) + (not (equal (c-get-char-property place ,property) ,value))) + (setq place (c-next-single-property-change + place ,property nil ,(or limit '(point-max))))) + (when (< place ,(or limit '(point-max))) + (goto-char place) + (search-forward-regexp ".") ; to set the match-data. + (point)))) + +(defmacro c-search-backward-char-property (property value &optional limit) + "Search backward for a text-property PROPERTY having value VALUE. +LIMIT bounds the search. The comparison is done with `equal'. + +Leave point just before the character, set the match data on this +character, and return point. If VALUE isn't found, Return nil; +point is then left undefined." + `(let ((place (point))) + (while + (and + (> place ,(or limit '(point-min))) + (not (equal (c-get-char-property (1- place) ,property) ,value))) + (setq place (,(if (and c-use-extents + (fboundp 'previous-single-char-property-change)) + ;; XEmacs > 2005-01-25. + 'previous-single-char-property-change + ;; Emacs and earlier XEmacs. + 'previous-single-property-change) + place ,property nil ,(or limit '(point-min))))) + (when (> place ,(or limit '(point-min))) + (goto-char place) + (search-backward-regexp ".") ; to set the match-data. + (point)))) + +(defun c-clear-char-property-with-value-function (from to property value) + "Remove all text-properties PROPERTY from the region (FROM, TO) +which have the value VALUE, as tested by `equal'. These +properties are assumed to be over individual characters, having +been put there by c-put-char-property. POINT remains unchanged." + (let ((place from) end-place) + (while ; loop round occurrances of (PROPERTY VALUE) + (progn + (while ; loop round changes in PROPERTY till we find VALUE + (and + (< place to) + (not (equal (get-text-property place property) value))) + (setq place (c-next-single-property-change place property nil to))) + (< place to)) + (setq end-place (c-next-single-property-change place property nil to)) + (remove-text-properties place end-place (cons property nil)) + ;; Do we have to do anything with stickiness here? + (setq place end-place)))) + +(defmacro c-clear-char-property-with-value (from to property value) + "Remove all text-properties PROPERTY from the region [FROM, TO) +which have the value VALUE, as tested by `equal'. These +properties are assumed to be over individual characters, having +been put there by c-put-char-property. POINT remains unchanged." + (if c-use-extents + ;; XEmacs + `(let ((-property- ,property)) + (map-extents (lambda (ext val) + (if (equal (extent-property ext -property-) val) + (delete-extent ext))) + nil ,from ,to ,value nil -property-)) + ;; Gnu Emacs + `(c-clear-char-property-with-value-function ,from ,to ,property ,value))) + +;; Macros to put overlays (Emacs) or extents (XEmacs) on buffer text. +;; For our purposes, these are characterized by being possible to +;; remove again without affecting the other text properties in the +;; buffer that got overridden when they were put. + +(defmacro c-put-overlay (from to property value) + ;; Put an overlay/extent covering the given range in the current + ;; buffer. It's currently undefined whether it's front/end sticky + ;; or not. The overlay/extent object is returned. + (if (cc-bytecomp-fboundp 'make-overlay) + ;; Emacs. + `(let ((ol (make-overlay ,from ,to))) + (overlay-put ol ,property ,value) + ol) + ;; XEmacs. + `(let ((ext (make-extent ,from ,to))) + (set-extent-property ext ,property ,value) + ext))) + +(defmacro c-delete-overlay (overlay) + ;; Deletes an overlay/extent object previously retrieved using + ;; `c-put-overlay'. + (if (cc-bytecomp-fboundp 'make-overlay) + ;; Emacs. + `(delete-overlay ,overlay) + ;; XEmacs. + `(delete-extent ,overlay))) + + +;; Make edebug understand the macros. +(eval-after-load "edebug" + '(progn + (def-edebug-spec cc-eval-when-compile t) + (def-edebug-spec c-point t) + (def-edebug-spec c-set-region-active t) + (def-edebug-spec c-safe t) + (def-edebug-spec c-save-buffer-state let*) + (def-edebug-spec c-tentative-buffer-changes t) + (def-edebug-spec c-forward-syntactic-ws t) + (def-edebug-spec c-backward-syntactic-ws t) + (def-edebug-spec c-forward-sexp t) + (def-edebug-spec c-backward-sexp t) + (def-edebug-spec c-up-list-forward t) + (def-edebug-spec c-up-list-backward t) + (def-edebug-spec c-down-list-forward t) + (def-edebug-spec c-down-list-backward t) + (def-edebug-spec c-add-syntax t) + (def-edebug-spec c-add-class-syntax t) + (def-edebug-spec c-benign-error t) + (def-edebug-spec c-with-syntax-table t) + (def-edebug-spec c-skip-ws-forward t) + (def-edebug-spec c-skip-ws-backward t) + (def-edebug-spec c-major-mode-is t) + (def-edebug-spec c-put-char-property t) + (def-edebug-spec c-get-char-property t) + (def-edebug-spec c-clear-char-property t) + (def-edebug-spec c-clear-char-properties t) + (def-edebug-spec c-put-overlay t) + (def-edebug-spec c-delete-overlay t))) + + +;;; Functions. + +;; Note: All these after the macros, to be on safe side in avoiding +;; bugs where macros are defined too late. These bugs often only show +;; when the files are compiled in a certain order within the same +;; session. + +(defsubst c-end-of-defun-1 () + ;; Replacement for end-of-defun that use c-beginning-of-defun-1. + (let ((start (point))) + ;; Skip forward into the next defun block. Don't bother to avoid + ;; comments, literals etc, since beginning-of-defun doesn't do that + ;; anyway. + (skip-chars-forward "^}") + (c-beginning-of-defun-1) + (if (eq (char-after) ?{) + (c-forward-sexp)) + (if (< (point) start) + (goto-char (point-max))))) + +(defmacro c-mark-<-as-paren (pos) + ;; Mark the "<" character at POS as a template opener using the + ;; `syntax-table' property either directly (XEmacs) or via a `category' + ;; property (GNU Emacs). + ;; + ;; This function does a hidden buffer change. Note that we use + ;; indirection through the `category' text property. This allows us to + ;; toggle the property in all template brackets simultaneously and + ;; cheaply. We use this, for instance, in `c-parse-state'. + (if c-use-category + `(c-put-char-property ,pos 'category 'c-<-as-paren-syntax) + `(c-put-char-property ,pos 'syntax-table c-<-as-paren-syntax))) + + +(defmacro c-mark->-as-paren (pos) + ;; Mark the ">" character at POS as an sexp list closer using the + ;; `syntax-table' property either directly (XEmacs) or via a `category' + ;; property (GNU Emacs). + ;; + ;; This function does a hidden buffer change. Note that we use + ;; indirection through the `category' text property. This allows us to + ;; toggle the property in all template brackets simultaneously and + ;; cheaply. We use this, for instance, in `c-parse-state'. + (if c-use-category + `(c-put-char-property ,pos 'category 'c->-as-paren-syntax) + `(c-put-char-property ,pos 'syntax-table c->-as-paren-syntax))) + +(defmacro c-unmark-<->-as-paren (pos) + ;; Unmark the "<" or "<" character at POS as an sexp list opener using the + ;; `syntax-table' property either directly or indirectly through a + ;; `category' text property. + ;; + ;; This function does a hidden buffer change. Note that we try to use + ;; indirection through the `category' text property. This allows us to + ;; toggle the property in all template brackets simultaneously and + ;; cheaply. We use this, for instance, in `c-parse-state'. + `(c-clear-char-property ,pos ,(if c-use-category ''category ''syntax-table))) + +(defsubst c-suppress-<->-as-parens () + ;; Suppress the syntactic effect of all marked < and > as parens. Note + ;; that this effect is NOT buffer local. You should probably not use + ;; this directly, but only through the macro + ;; `c-with-<->-as-parens-suppressed' + (put 'c-<-as-paren-syntax 'syntax-table nil) + (put 'c->-as-paren-syntax 'syntax-table nil)) + +(defsubst c-restore-<->-as-parens () + ;; Restore the syntactic effect of all marked s as parens. This + ;; has no effect on unmarked s + (put 'c-<-as-paren-syntax 'syntax-table c-<-as-paren-syntax) + (put 'c->-as-paren-syntax 'syntax-table c->-as-paren-syntax)) + +(defmacro c-with-<->-as-parens-suppressed (&rest forms) + ;; Like progn, except that the paren property is suppressed on all + ;; template brackets whilst they are running. This macro does a hidden + ;; buffer change. + `(unwind-protect + (progn + (c-suppress-<->-as-parens) + ,@forms) + (c-restore-<->-as-parens))) + +;;;;;;;;;;;;;;; + +(defconst c-cpp-delimiter '(14)) ; generic comment syntax +;; This is the value of the `category' text property placed on every # +;; which introduces a CPP construct and every EOL (or EOB, or character +;; preceding //, etc.) which terminates it. We can instantly "comment +;; out" all CPP constructs by giving `c-cpp-delimiter' a syntax-table +;; propery '(14) (generic comment delimiter). +(defmacro c-set-cpp-delimiters (beg end) + ;; This macro does a hidden buffer change. + `(progn + (c-put-char-property ,beg 'category 'c-cpp-delimiter) + (if (< ,end (point-max)) + (c-put-char-property ,end 'category 'c-cpp-delimiter)))) +(defmacro c-clear-cpp-delimiters (beg end) + ;; This macro does a hidden buffer change. + `(progn + (c-clear-char-property ,beg 'category) + (if (< ,end (point-max)) + (c-clear-char-property ,end 'category)))) + +(defsubst c-comment-out-cpps () + ;; Render all preprocessor constructs syntactically commented out. + (put 'c-cpp-delimiter 'syntax-table c-cpp-delimiter)) +(defsubst c-uncomment-out-cpps () + ;; Restore the syntactic visibility of preprocessor constructs. + (put 'c-cpp-delimiter 'syntax-table nil)) + +(defmacro c-with-cpps-commented-out (&rest forms) + ;; Execute FORMS... whilst the syntactic effect of all characters in + ;; all CPP regions is suppressed. In particular, this is to suppress + ;; the syntactic significance of parens/braces/brackets to functions + ;; such as `scan-lists' and `parse-partial-sexp'. + `(unwind-protect + (c-save-buffer-state () + (c-comment-out-cpps) + ,@forms) + (c-save-buffer-state () + (c-uncomment-out-cpps)))) + +(defmacro c-with-all-but-one-cpps-commented-out (beg end &rest forms) + ;; Execute FORMS... whilst the syntactic effect of all characters in + ;; every CPP region APART FROM THE ONE BETWEEN BEG and END is + ;; suppressed. + `(unwind-protect + (c-save-buffer-state () + (c-clear-cpp-delimiters ,beg ,end) + ,`(c-with-cpps-commented-out ,@forms)) + (c-save-buffer-state () + (c-set-cpp-delimiters ,beg ,end)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; The following macros are to be used only in `c-parse-state' and its +;; subroutines. Their main purpose is to simplify the handling of C++/Java +;; template delimiters and CPP macros. In GNU Emacs, this is done slickly by +;; the judicious use of 'category properties. These don't exist in XEmacs. +;; +;; Note: in the following macros, there is no special handling for parentheses +;; inside CPP constructs. That is because CPPs are always syntactically +;; balanced, thanks to `c-neutralize-CPP-line' in cc-mode.el. +(defmacro c-sc-scan-lists-no-category+1+1 (from) + ;; Do a (scan-lists FROM 1 1). Any finishing position which either (i) is + ;; determined by and angle bracket; or (ii) is inside a macro whose start + ;; isn't POINT-MACRO-START doesn't count as a finishing position. + `(let ((here (point)) + (pos (scan-lists ,from 1 1))) + (while (eq (char-before pos) ?>) + (setq pos (scan-lists pos 1 1))) + pos)) + +(defmacro c-sc-scan-lists-no-category+1-1 (from) + ;; Do a (scan-lists FROM 1 -1). Any finishing position which either (i) is + ;; determined by and angle bracket; or (ii) is inside a macro whose start + ;; isn't POINT-MACRO-START doesn't count as a finishing position. + `(let ((here (point)) + (pos (scan-lists ,from 1 -1))) + (while (eq (char-before pos) ?<) + (setq pos (scan-lists pos 1 1)) + (setq pos (scan-lists pos 1 -1))) + pos)) + +(defmacro c-sc-scan-lists-no-category-1+1 (from) + ;; Do a (scan-lists FROM -1 1). Any finishing position which either (i) is + ;; determined by and angle bracket; or (ii) is inside a macro whose start + ;; isn't POINT-MACRO-START doesn't count as a finishing position. + `(let ((here (point)) + (pos (scan-lists ,from -1 1))) + (while (eq (char-after pos) ?<) + (setq pos (scan-lists pos -1 1))) + pos)) + +(defmacro c-sc-scan-lists-no-category-1-1 (from) + ;; Do a (scan-lists FROM -1 -1). Any finishing position which either (i) is + ;; determined by and angle bracket; or (ii) is inside a macro whose start + ;; isn't POINT-MACRO-START doesn't count as a finishing position. + `(let ((here (point)) + (pos (scan-lists ,from -1 -1))) + (while (eq (char-after pos) ?>) + (setq pos (scan-lists pos -1 1)) + (setq pos (scan-lists pos -1 -1))) + pos)) + +(defmacro c-sc-scan-lists (from count depth) + (if c-use-category + `(scan-lists ,from ,count ,depth) + (cond + ((and (eq count 1) (eq depth 1)) + `(c-sc-scan-lists-no-category+1+1 ,from)) + ((and (eq count 1) (eq depth -1)) + `(c-sc-scan-lists-no-category+1-1 ,from)) + ((and (eq count -1) (eq depth 1)) + `(c-sc-scan-lists-no-category-1+1 ,from)) + ((and (eq count -1) (eq depth -1)) + `(c-sc-scan-lists-no-category-1-1 ,from)) + (t (error "Invalid parameter(s) to c-sc-scan-lists"))))) + + +(defun c-sc-parse-partial-sexp-no-category (from to targetdepth stopbefore + oldstate) + ;; Do a parse-partial-sexp using the supplied arguments, disregarding + ;; template/generic delimiters < > and disregarding macros other than the + ;; one at POINT-MACRO-START. + ;; + ;; NOTE that STOPBEFORE must be nil. TARGETDEPTH should be one less than + ;; the depth in OLDSTATE. This function is thus a SPECIAL PURPOSE variation + ;; on parse-partial-sexp, designed for calling from + ;; `c-remove-stale-state-cache'. + ;; + ;; Any finishing position which is determined by an angle bracket delimiter + ;; doesn't count as a finishing position. + ;; + ;; Note there is no special handling of CPP constructs here, since these are + ;; always syntactically balanced (thanks to `c-neutralize-CPP-line'). + (let ((state + (parse-partial-sexp from to targetdepth stopbefore oldstate))) + (while + (and (< (point) to) + ;; We must have hit targetdepth. + (or (eq (char-before) ?<) + (eq (char-before) ?>))) + (setcar state + (if (memq (char-before) '(?> ?\) ?\} ?\])) + (1+ (car state)) + (1- (car state)))) + (setq state + (parse-partial-sexp (point) to targetdepth stopbefore oldstate))) + state)) + +(defmacro c-sc-parse-partial-sexp (from to &optional targetdepth stopbefore + oldstate) + (if c-use-category + `(parse-partial-sexp ,from ,to ,targetdepth ,stopbefore ,oldstate) + `(c-sc-parse-partial-sexp-no-category ,from ,to ,targetdepth ,stopbefore + ,oldstate))) + + +(defmacro c-looking-at-non-alphnumspace () + "Are we looking at a character which isn't alphanumeric or space?" + (if (memq 'gen-comment-delim c-emacs-features) + `(looking-at +"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)") + `(or (looking-at +"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\)" + (let ((prop (c-get-char-property (point) 'syntax-table))) + (eq prop '(14))))))) ; '(14) is generic comment delimiter. + + +(defsubst c-intersect-lists (list alist) + ;; return the element of ALIST that matches the first element found + ;; in LIST. Uses assq. + (let (match) + (while (and list + (not (setq match (assq (car list) alist)))) + (setq list (cdr list))) + match)) + +(defsubst c-lookup-lists (list alist1 alist2) + ;; first, find the first entry from LIST that is present in ALIST1, + ;; then find the entry in ALIST2 for that entry. + (assq (car (c-intersect-lists list alist1)) alist2)) + +(defsubst c-langelem-sym (langelem) + "Return the syntactic symbol in LANGELEM. + +LANGELEM is either a cons cell on the \"old\" form given as the first +argument to lineup functions or a syntactic element on the \"new\" +form as used in `c-syntactic-element'." + (car langelem)) + +(defsubst c-langelem-pos (langelem) + "Return the anchor position in LANGELEM, or nil if there is none. + +LANGELEM is either a cons cell on the \"old\" form given as the first +argument to lineup functions or a syntactic element on the \"new\" +form as used in `c-syntactic-element'." + (if (consp (cdr langelem)) + (car-safe (cdr langelem)) + (cdr langelem))) + +(defun c-langelem-col (langelem &optional preserve-point) + "Return the column of the anchor position in LANGELEM. +Also move the point to that position unless PRESERVE-POINT is non-nil. + +LANGELEM is either a cons cell on the \"old\" form given as the first +argument to lineup functions or a syntactic element on the \"new\" +form as used in `c-syntactic-element'." + (let ((pos (c-langelem-pos langelem)) + (here (point))) + (if pos + (progn + (goto-char pos) + (prog1 (current-column) + (if preserve-point + (goto-char here)))) + 0))) + +(defsubst c-langelem-2nd-pos (langelem) + "Return the secondary position in LANGELEM, or nil if there is none. + +LANGELEM is typically a syntactic element on the \"new\" form as used +in `c-syntactic-element'. It may also be a cons cell as passed in the +first argument to lineup functions, but then the returned value always +will be nil." + (car-safe (cdr-safe (cdr-safe langelem)))) + +(defsubst c-keep-region-active () + ;; Do whatever is necessary to keep the region active in XEmacs. + ;; This is not needed for Emacs. + (and (boundp 'zmacs-region-stays) + (setq zmacs-region-stays t))) + +(put 'c-mode 'c-mode-prefix "c-") +(put 'c++-mode 'c-mode-prefix "c++-") +(put 'objc-mode 'c-mode-prefix "objc-") +(put 'java-mode 'c-mode-prefix "java-") +(put 'idl-mode 'c-mode-prefix "idl-") +(put 'pike-mode 'c-mode-prefix "pike-") +(put 'awk-mode 'c-mode-prefix "awk-") + +(defsubst c-mode-symbol (suffix) + "Prefix the current mode prefix (e.g. \"c-\") to SUFFIX and return +the corresponding symbol." + (or c-buffer-is-cc-mode + (error "Not inside a CC Mode based mode")) + (let ((mode-prefix (get c-buffer-is-cc-mode 'c-mode-prefix))) + (or mode-prefix + (error "%S has no mode prefix known to `c-mode-symbol'" + c-buffer-is-cc-mode)) + (intern (concat mode-prefix suffix)))) + +(defsubst c-mode-var (suffix) + "Prefix the current mode prefix (e.g. \"c-\") to SUFFIX and return +the value of the variable with that name." + (symbol-value (c-mode-symbol suffix))) + +(defsubst c-got-face-at (pos faces) + "Return non-nil if position POS in the current buffer has any of the +faces in the list FACES." + (let ((pos-faces (get-text-property pos 'face))) + (if (consp pos-faces) + (progn + (while (and pos-faces + (not (memq (car pos-faces) faces))) + (setq pos-faces (cdr pos-faces))) + pos-faces) + (memq pos-faces faces)))) + +(defsubst c-face-name-p (facename) + ;; Return t if FACENAME is the name of a face. This method is + ;; necessary since facep in XEmacs only returns t for the actual + ;; face objects (while it's only their names that are used just + ;; about anywhere else) without providing a predicate that tests + ;; face names. + (memq facename (face-list))) + +(defun c-concat-separated (list separator) + "Like `concat' on LIST, but separate each element with SEPARATOR. +Notably, null elements in LIST are ignored." + (mapconcat 'identity (delete nil (append list nil)) separator)) + +(defun c-make-keywords-re (adorn list &optional mode) + "Make a regexp that matches all the strings the list. +Duplicates and nil elements in the list are removed. The +resulting regexp may contain zero or more submatch expressions. + +If ADORN is t there will be at least one submatch and the first +surrounds the matched alternative, and the regexp will also not match +a prefix of any identifier. Adorned regexps cannot be appended. The +language variable `c-nonsymbol-key' is used to make the adornment. + +A value 'appendable for ADORN is like above, but all alternatives in +the list that end with a word constituent char will have \\> appended +instead, so that the regexp remains appendable. Note that this +variant doesn't always guarantee that an identifier prefix isn't +matched since the symbol constituent '_' is normally considered a +nonword token by \\>. + +The optional MODE specifies the language to get `c-nonsymbol-key' from +when it's needed. The default is the current language taken from +`c-buffer-is-cc-mode'." + + (setq list (delete nil (delete-duplicates list :test 'string-equal))) + (if list + (let (re) + + (if (eq adorn 'appendable) + ;; This is kludgy but it works: Search for a string that + ;; doesn't occur in any word in LIST. Append it to all + ;; the alternatives where we want to add \>. Run through + ;; `regexp-opt' and then replace it with \>. + (let ((unique "") pos) + (while (let (found) + (setq unique (concat unique "@") + pos list) + (while (and pos + (if (string-match unique (car pos)) + (progn (setq found t) + nil) + t)) + (setq pos (cdr pos))) + found)) + (setq pos list) + (while pos + (if (string-match "\\w\\'" (car pos)) + (setcar pos (concat (car pos) unique))) + (setq pos (cdr pos))) + (setq re (regexp-opt list)) + (setq pos 0) + (while (string-match unique re pos) + (setq pos (+ (match-beginning 0) 2) + re (replace-match "\\>" t t re)))) + + (setq re (regexp-opt list))) + + ;; Emacs 20 and XEmacs (all versions so far) has a buggy + ;; regexp-opt that doesn't always cope with strings containing + ;; newlines. This kludge doesn't handle shy parens correctly + ;; so we can't advice regexp-opt directly with it. + (let (fail-list) + (while list + (and (string-match "\n" (car list)) ; To speed it up a little. + (not (string-match (concat "\\`\\(" re "\\)\\'") + (car list))) + (setq fail-list (cons (car list) fail-list))) + (setq list (cdr list))) + (when fail-list + (setq re (concat re + "\\|" + (mapconcat + (if (eq adorn 'appendable) + (lambda (str) + (if (string-match "\\w\\'" str) + (concat (regexp-quote str) + "\\>") + (regexp-quote str))) + 'regexp-quote) + (sort fail-list + (lambda (a b) + (> (length a) (length b)))) + "\\|"))))) + + ;; Add our own grouping parenthesis around re instead of + ;; passing adorn to `regexp-opt', since in XEmacs it makes the + ;; top level grouping "shy". + (cond ((eq adorn 'appendable) + (concat "\\(" re "\\)")) + (adorn + (concat "\\(" re "\\)" + "\\(" + (c-get-lang-constant 'c-nonsymbol-key nil mode) + "\\|$\\)")) + (t + re))) + + ;; Produce a regexp that matches nothing. + (if adorn + "\\(\\<\\>\\)" + "\\<\\>"))) + +(put 'c-make-keywords-re 'lisp-indent-function 1) + +(defun c-make-bare-char-alt (chars &optional inverted) + "Make a character alternative string from the list of characters CHARS. +The returned string is of the type that can be used with +`skip-chars-forward' and `skip-chars-backward'. If INVERTED is +non-nil, a caret is prepended to invert the set." + ;; This function ought to be in the elisp core somewhere. + (let ((str (if inverted "^" "")) char char2) + (setq chars (sort (append chars nil) `<)) + (while chars + (setq char (pop chars)) + (if (memq char '(?\\ ?^ ?-)) + ;; Quoting necessary (this method only works in the skip + ;; functions). + (setq str (format "%s\\%c" str char)) + (setq str (format "%s%c" str char))) + ;; Check for range. + (setq char2 char) + (while (and chars (>= (1+ char2) (car chars))) + (setq char2 (pop chars))) + (unless (= char char2) + (if (< (1+ char) char2) + (setq str (format "%s-%c" str char2)) + (push char2 chars)))) + str)) + +;; Leftovers from (X)Emacs 19 compatibility. +(defalias 'c-regexp-opt 'regexp-opt) +(defalias 'c-regexp-opt-depth 'regexp-opt-depth) + + +;; Figure out what features this Emacs has + +(cc-bytecomp-defvar open-paren-in-column-0-is-defun-start) + +(defconst c-emacs-features + (let (list) + + (if (boundp 'infodock-version) + ;; I've no idea what this actually is, but it's legacy. /mast + (setq list (cons 'infodock list))) + + ;; XEmacs uses 8-bit modify-syntax-entry flags. + ;; Emacs uses a 1-bit flag. We will have to set up our + ;; syntax tables differently to handle this. + (let ((table (copy-syntax-table)) + entry) + (modify-syntax-entry ?a ". 12345678" table) + (cond + ;; Emacs + ((arrayp table) + (setq entry (aref table ?a)) + ;; In Emacs, table entries are cons cells + (if (consp entry) (setq entry (car entry)))) + ;; XEmacs + ((fboundp 'get-char-table) + (setq entry (get-char-table ?a table))) + ;; incompatible + (t (error "CC Mode is incompatible with this version of Emacs"))) + (setq list (cons (if (= (logand (lsh entry -16) 255) 255) + '8-bit + '1-bit) + list))) + + ;; Check whether beginning/end-of-defun call + ;; beginning/end-of-defun-function nicely, passing through the + ;; argument and respecting the return code. + (let* (mark-ring + (bod-param 'foo) (eod-param 'foo) + (beginning-of-defun-function + (lambda (&optional arg) + (or (eq bod-param 'foo) (setq bod-param 'bar)) + (and (eq bod-param 'foo) + (setq bod-param arg) + (eq arg 3)))) + (end-of-defun-function + (lambda (&optional arg) + (and (eq eod-param 'foo) + (setq eod-param arg) + (eq arg 3))))) + (if (save-excursion (and (beginning-of-defun 3) (eq bod-param 3) + (not (beginning-of-defun)) + (end-of-defun 3) (eq eod-param 3) + (not (end-of-defun)))) + (setq list (cons 'argumentative-bod-function list)))) + + ;; Record whether the `category' text property works. + (if c-use-category (setq list (cons 'category-properties list))) + + (let ((buf (generate-new-buffer " test")) + parse-sexp-lookup-properties + parse-sexp-ignore-comments + lookup-syntax-properties) + (save-excursion + (set-buffer buf) + (set-syntax-table (make-syntax-table)) + + ;; For some reason we have to set some of these after the + ;; buffer has been made current. (Specifically, + ;; `parse-sexp-ignore-comments' in Emacs 21.) + (setq parse-sexp-lookup-properties t + parse-sexp-ignore-comments t + lookup-syntax-properties t) + + ;; Find out if the `syntax-table' text property works. + (modify-syntax-entry ?< ".") + (modify-syntax-entry ?> ".") + (insert "<()>") + (c-mark-<-as-paren (point-min)) + (c-mark->-as-paren (+ 3 (point-min))) + (goto-char (point-min)) + (c-forward-sexp) + (if (= (point) (+ 4 (point-min))) + (setq list (cons 'syntax-properties list)) + (error (concat + "CC Mode is incompatible with this version of Emacs - " + "support for the `syntax-table' text property " + "is required."))) + + ;; Find out if "\\s!" (generic comment delimiters) work. + (c-safe + (modify-syntax-entry ?x "!") + (if (string-match "\\s!" "x") + (setq list (cons 'gen-comment-delim list)))) + + ;; Find out if "\\s|" (generic string delimiters) work. + (c-safe + (modify-syntax-entry ?x "|") + (if (string-match "\\s|" "x") + (setq list (cons 'gen-string-delim list)))) + + ;; See if POSIX char classes work. + (when (and (string-match "[[:alpha:]]" "a") + ;; All versions of Emacs 21 so far haven't fixed + ;; char classes in `skip-chars-forward' and + ;; `skip-chars-backward'. + (progn + (delete-region (point-min) (point-max)) + (insert "foo123") + (skip-chars-backward "[:alnum:]") + (bobp)) + (= (skip-chars-forward "[:alpha:]") 3)) + (setq list (cons 'posix-char-classes list))) + + ;; See if `open-paren-in-column-0-is-defun-start' exists and + ;; isn't buggy (Emacs >= 21.4). + (when (boundp 'open-paren-in-column-0-is-defun-start) + (let ((open-paren-in-column-0-is-defun-start nil) + (parse-sexp-ignore-comments t)) + (delete-region (point-min) (point-max)) + (set-syntax-table (make-syntax-table)) + (modify-syntax-entry ?\' "\"") + (cond + ;; XEmacs. Afaik this is currently an Emacs-only + ;; feature, but it's good to be prepared. + ((memq '8-bit list) + (modify-syntax-entry ?/ ". 1456") + (modify-syntax-entry ?* ". 23")) + ;; Emacs + ((memq '1-bit list) + (modify-syntax-entry ?/ ". 124b") + (modify-syntax-entry ?* ". 23"))) + (modify-syntax-entry ?\n "> b") + (insert "/* '\n () */") + (backward-sexp) + (if (bobp) + (setq list (cons 'col-0-paren list))))) + + (set-buffer-modified-p nil)) + (kill-buffer buf)) + + ;; Will the "LOCAL" parameter of `add-hook' work without the hook first + ;; being made local by `make-local-hook'? + (if (let ((buf1 (generate-new-buffer " test1")) + (buf2 (generate-new-buffer " test2")) + changed) + + (save-excursion ; Needed for XEmacs's byte compiler + (set-buffer buf1) + (add-hook 'after-change-functions + (lambda (beg end old-len) (setq changed t)) + nil + t) + (set-buffer buf2) + (insert ?c) + (set-buffer buf1) + (remove-hook 'after-change-functions + (lambda (beg end old-len) (setq changed t)) + t) + (kill-buffer buf1) + (kill-buffer buf2) + (not changed))) + (setq list (cons 'add-hook-local list))) + + + ;; See if `parse-partial-sexp' returns the eighth element. + (if (c-safe (>= (length (save-excursion + (parse-partial-sexp (point) (point)))) + 10)) + (setq list (cons 'pps-extended-state list)) + (error (concat + "CC Mode is incompatible with this version of Emacs - " + "`parse-partial-sexp' has to return at least 10 elements."))) + + ;;(message "c-emacs-features: %S" list) + list) + "A list of certain features in the (X)Emacs you are using. +There are many flavors of Emacs out there, each with different +features supporting those needed by CC Mode. The following values +might be present: + +'8-bit 8 bit syntax entry flags (XEmacs style). +'1-bit 1 bit syntax entry flags (Emacs style). +'argumentative-bod-function beginning-of-defun and end-of-defun pass + ARG through to beginning/end-of-defun-function. +'syntax-properties It works to override the syntax for specific characters + in the buffer with the 'syntax-table property. It's + always set - CC Mode no longer works in emacsen without + this feature. +'category-properties Syntax routines can add a level of indirection to text + properties using the 'category property. +'gen-comment-delim Generic comment delimiters work + (i.e. the syntax class `!'). +'gen-string-delim Generic string delimiters work + (i.e. the syntax class `|'). +'pps-extended-state `parse-partial-sexp' returns a list with at least 10 + elements, i.e. it contains the position of the start of + the last comment or string. It's always set - CC Mode + no longer works in emacsen without this feature. +'posix-char-classes The regexp engine understands POSIX character classes. +'col-0-paren It's possible to turn off the ad-hoc rule that a paren + in column zero is the start of a defun. +'infodock This is Infodock (based on XEmacs). + +'8-bit and '1-bit are mutually exclusive.") + + +;;; Some helper constants. + +;; If the regexp engine supports POSIX char classes then we can use +;; them to handle extended charsets correctly. +(if (memq 'posix-char-classes c-emacs-features) + (progn + (defconst c-alpha "[:alpha:]") + (defconst c-alnum "[:alnum:]") + (defconst c-digit "[:digit:]") + (defconst c-upper "[:upper:]") + (defconst c-lower "[:lower:]")) + (defconst c-alpha "a-zA-Z") + (defconst c-alnum "a-zA-Z0-9") + (defconst c-digit "0-9") + (defconst c-upper "A-Z") + (defconst c-lower "a-z")) + + +;;; System for handling language dependent constants. + +;; This is used to set various language dependent data in a flexible +;; way: Language constants can be built from the values of other +;; language constants, also those for other languages. They can also +;; process the values of other language constants uniformly across all +;; the languages. E.g. one language constant can list all the type +;; keywords in each language, and another can build a regexp for each +;; language from those lists without code duplication. +;; +;; Language constants are defined with `c-lang-defconst', and their +;; value forms (referred to as source definitions) are evaluated only +;; on demand when requested for a particular language with +;; `c-lang-const'. It's therefore possible to refer to the values of +;; constants defined later in the file, or in another file, just as +;; long as all the relevant `c-lang-defconst' have been loaded when +;; `c-lang-const' is actually evaluated from somewhere else. +;; +;; `c-lang-const' forms are also evaluated at compile time and +;; replaced with the values they produce. Thus there's no overhead +;; for this system when compiled code is used - only the values +;; actually used in the code are present, and the file(s) containing +;; the `c-lang-defconst' forms don't need to be loaded at all then. +;; There are however safeguards to make sure that they can be loaded +;; to get the source definitions for the values if there's a mismatch +;; in compiled versions, or if `c-lang-const' is used uncompiled. +;; +;; Note that the source definitions in a `c-lang-defconst' form are +;; compiled into the .elc file where it stands; there's no need to +;; load the source file to get it. +;; +;; See cc-langs.el for more details about how this system is deployed +;; in CC Mode, and how the associated language variable system +;; (`c-lang-defvar') works. That file also contains a lot of +;; examples. + +(defun c-add-language (mode base-mode) + "Declare a new language in the language dependent variable system. +This is intended to be used by modes that inherit CC Mode to add new +languages. It should be used at the top level before any calls to +`c-lang-defconst'. MODE is the mode name symbol for the new language, +and BASE-MODE is the mode name symbol for the language in CC Mode that +is to be the template for the new mode. + +The exact effect of BASE-MODE is to make all language constants that +haven't got a setting in the new language fall back to their values in +BASE-MODE. It does not have any effect outside the language constant +system." + (unless (string-match "\\`\\(.*-\\)mode\\'" (symbol-name mode)) + (error "The mode name symbol `%s' must end with \"-mode\"" mode)) + (put mode 'c-mode-prefix (match-string 1 (symbol-name mode))) + (unless (get base-mode 'c-mode-prefix) + (error "Unknown base mode `%s'" base-mode)) + (put mode 'c-fallback-mode base-mode)) + +(defvar c-lang-constants (make-vector 151 0)) +;; This obarray is a cache to keep track of the language constants +;; defined by `c-lang-defconst' and the evaluated values returned by +;; `c-lang-const'. It's mostly used at compile time but it's not +;; stored in compiled files. +;; +;; The obarray contains all the language constants as symbols. The +;; value cells hold the evaluated values as alists where each car is +;; the mode name symbol and the corresponding cdr is the evaluated +;; value in that mode. The property lists hold the source definitions +;; and other miscellaneous data. The obarray might also contain +;; various other symbols, but those don't have any variable bindings. + +(defvar c-lang-const-expansion nil) + +(defsubst c-get-current-file () + ;; Return the base name of the current file. + (let ((file (cond + (load-in-progress + ;; Being loaded. + load-file-name) + ((and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + ;; Being compiled. + byte-compile-dest-file) + (t + ;; Being evaluated interactively. + (buffer-file-name))))) + (and file + (file-name-sans-extension + (file-name-nondirectory file))))) + +(defmacro c-lang-defconst-eval-immediately (form) + "Can be used inside a VAL in `c-lang-defconst' to evaluate FORM +immediately, i.e. at the same time as the `c-lang-defconst' form +itself is evaluated." + ;; Evaluate at macro expansion time, i.e. in the + ;; `cl-macroexpand-all' inside `c-lang-defconst'. + (eval form)) + +(defmacro c-lang-defconst (name &rest args) + "Set the language specific values of the language constant NAME. +The second argument can optionally be a docstring. The rest of the +arguments are one or more repetitions of LANG VAL where LANG specifies +the language(s) that VAL applies to. LANG is the name of the +language, i.e. the mode name without the \"-mode\" suffix, or a list +of such language names, or `t' for all languages. VAL is a form to +evaluate to get the value. + +If LANG isn't `t' or one of the core languages in CC Mode, it must +have been declared with `c-add-language'. + +Neither NAME, LANG nor VAL are evaluated directly - they should not be +quoted. `c-lang-defconst-eval-immediately' can however be used inside +VAL to evaluate parts of it directly. + +When VAL is evaluated for some language, that language is temporarily +made current so that `c-lang-const' without an explicit language can +be used inside VAL to refer to the value of a language constant in the +same language. That is particularly useful if LANG is `t'. + +VAL is not evaluated right away but rather when the value is requested +with `c-lang-const'. Thus it's possible to use `c-lang-const' inside +VAL to refer to language constants that haven't been defined yet. +However, if the definition of a language constant is in another file +then that file must be loaded \(at compile time) before it's safe to +reference the constant. + +The assignments in ARGS are processed in sequence like `setq', so +\(c-lang-const NAME) may be used inside a VAL to refer to the last +assigned value to this language constant, or a value that it has +gotten in another earlier loaded file. + +To work well with repeated loads and interactive reevaluation, only +one `c-lang-defconst' for each NAME is permitted per file. If there +already is one it will be completely replaced; the value in the +earlier definition will not affect `c-lang-const' on the same +constant. A file is identified by its base name." + + (let* ((sym (intern (symbol-name name) c-lang-constants)) + ;; Make `c-lang-const' expand to a straightforward call to + ;; `c-get-lang-constant' in `cl-macroexpand-all' below. + ;; + ;; (The default behavior, i.e. to expand to a call inside + ;; `eval-when-compile' should be equivalent, since that macro + ;; should only expand to its content if it's used inside a + ;; form that's already evaluated at compile time. It's + ;; however necessary to use our cover macro + ;; `cc-eval-when-compile' due to bugs in `eval-when-compile', + ;; and it expands to a bulkier form that in this case only is + ;; unnecessary garbage that we don't want to store in the + ;; language constant source definitions.) + (c-lang-const-expansion 'call) + (c-langs-are-parametric t) + bindings + pre-files) + + (or (symbolp name) + (error "Not a symbol: %s" name)) + + (when (stringp (car-safe args)) + ;; The docstring is hardly used anywhere since there's no normal + ;; symbol to attach it to. It's primarily for getting the right + ;; format in the source. + (put sym 'variable-documentation (car args)) + (setq args (cdr args))) + + (or args + (error "No assignments in `c-lang-defconst' for %s" name)) + + ;; Rework ARGS to an association list to make it easier to handle. + ;; It's reversed at the same time to make it easier to implement + ;; the demand-driven (i.e. reversed) evaluation in `c-lang-const'. + (while args + (let ((assigned-mode + (cond ((eq (car args) t) t) + ((symbolp (car args)) + (list (intern (concat (symbol-name (car args)) + "-mode")))) + ((listp (car args)) + (mapcar (lambda (lang) + (or (symbolp lang) + (error "Not a list of symbols: %s" + (car args))) + (intern (concat (symbol-name lang) + "-mode"))) + (car args))) + (t (error "Not a symbol or a list of symbols: %s" + (car args))))) + val) + + (or (cdr args) + (error "No value for %s" (car args))) + (setq args (cdr args) + val (car args)) + + ;; Emacs has a weird bug where it seems to fail to read + ;; backquote lists from byte compiled files correctly (,@ + ;; forms, to be specific), so make sure the bindings in the + ;; expansion below don't contain any backquote stuff. + ;; (XEmacs handles it correctly and doesn't need this for that + ;; reason, but we also use this expansion handle + ;; `c-lang-defconst-eval-immediately' and to register + ;; dependencies on the `c-lang-const's in VAL.) + (setq val (cl-macroexpand-all val)) + + (setq bindings (cons (cons assigned-mode val) bindings) + args (cdr args)))) + + ;; Compile in the other files that have provided source + ;; definitions for this symbol, to make sure the order in the + ;; `source' property is correct even when files are loaded out of + ;; order. + (setq pre-files (nreverse + ;; Reverse to get the right load order. + (mapcar 'car (get sym 'source)))) + + `(eval-and-compile + (c-define-lang-constant ',name ',bindings + ,@(and pre-files `(',pre-files)))))) + +(put 'c-lang-defconst 'lisp-indent-function 1) +(eval-after-load "edebug" + '(def-edebug-spec c-lang-defconst + (&define name [&optional stringp] [&rest sexp def-form]))) + +(defun c-define-lang-constant (name bindings &optional pre-files) + ;; Used by `c-lang-defconst'. + + (let* ((sym (intern (symbol-name name) c-lang-constants)) + (source (get sym 'source)) + (file (intern + (or (c-get-current-file) + (error "`c-lang-defconst' must be used in a file")))) + (elem (assq file source))) + + ;;(when (cdr-safe elem) + ;; (message "Language constant %s redefined in %S" name file)) + + ;; Note that the order in the source alist is relevant. Like how + ;; `c-lang-defconst' reverses the bindings, this reverses the + ;; order between files so that the last to evaluate comes first. + (unless elem + (while pre-files + (unless (assq (car pre-files) source) + (setq source (cons (list (car pre-files)) source))) + (setq pre-files (cdr pre-files))) + (put sym 'source (cons (setq elem (list file)) source))) + + (setcdr elem bindings) + + ;; Bind the symbol as a variable, or clear any earlier evaluated + ;; value it has. + (set sym nil) + + ;; Clear the evaluated values that depend on this source. + (let ((agenda (get sym 'dependents)) + (visited (make-vector 101 0)) + ptr) + (while agenda + (setq sym (car agenda) + agenda (cdr agenda)) + (intern (symbol-name sym) visited) + (set sym nil) + (setq ptr (get sym 'dependents)) + (while ptr + (setq sym (car ptr) + ptr (cdr ptr)) + (unless (intern-soft (symbol-name sym) visited) + (setq agenda (cons sym agenda)))))) + + name)) + +(defmacro c-lang-const (name &optional lang) + "Get the mode specific value of the language constant NAME in language LANG. +LANG is the name of the language, i.e. the mode name without the +\"-mode\" suffix. If used inside `c-lang-defconst' or +`c-lang-defvar', LANG may be left out to refer to the current +language. NAME and LANG are not evaluated so they should not be +quoted." + + (or (symbolp name) + (error "Not a symbol: %s" name)) + (or (symbolp lang) + (error "Not a symbol: %s" lang)) + + (let ((sym (intern (symbol-name name) c-lang-constants)) + mode source-files args) + + (when lang + (setq mode (intern (concat (symbol-name lang) "-mode"))) + (unless (get mode 'c-mode-prefix) + (error + "Unknown language %S since it got no `c-mode-prefix' property" + (symbol-name lang)))) + + (if (eq c-lang-const-expansion 'immediate) + ;; No need to find out the source file(s) when we evaluate + ;; immediately since all the info is already there in the + ;; `source' property. + `',(c-get-lang-constant name nil mode) + + (let ((file (c-get-current-file))) + (if file (setq file (intern file))) + ;; Get the source file(s) that must be loaded to get the value + ;; of the constant. If the symbol isn't defined yet we assume + ;; that its definition will come later in this file, and thus + ;; are no file dependencies needed. + (setq source-files (nreverse + ;; Reverse to get the right load order. + (mapcan (lambda (elem) + (if (eq file (car elem)) + nil ; Exclude our own file. + (list (car elem)))) + (get sym 'source))))) + + ;; Make some effort to do a compact call to + ;; `c-get-lang-constant' since it will be compiled in. + (setq args (and mode `(',mode))) + (if (or source-files args) + (setq args (cons (and source-files `',source-files) + args))) + + (if (or (eq c-lang-const-expansion 'call) + (and (not c-lang-const-expansion) + (not mode)) + load-in-progress + (not (boundp 'byte-compile-dest-file)) + (not (stringp byte-compile-dest-file))) + ;; Either a straight call is requested in the context, or + ;; we're in an "uncontrolled" context and got no language, + ;; or we're not being byte compiled so the compile time + ;; stuff below is unnecessary. + `(c-get-lang-constant ',name ,@args) + + ;; Being compiled. If the loading and compiling version is + ;; the same we use a value that is evaluated at compile time, + ;; otherwise it's evaluated at runtime. + `(if (eq c-version-sym ',c-version-sym) + (cc-eval-when-compile + (c-get-lang-constant ',name ,@args)) + (c-get-lang-constant ',name ,@args)))))) + +(defvar c-lang-constants-under-evaluation nil) + +(defun c-get-lang-constant (name &optional source-files mode) + ;; Used by `c-lang-const'. + + (or mode + (setq mode c-buffer-is-cc-mode) + (error "No current language")) + + (let* ((sym (intern (symbol-name name) c-lang-constants)) + (source (get sym 'source)) + elem + (eval-in-sym (and c-lang-constants-under-evaluation + (caar c-lang-constants-under-evaluation)))) + + ;; Record the dependencies between this symbol and the one we're + ;; being evaluated in. + (when eval-in-sym + (or (memq eval-in-sym (get sym 'dependents)) + (put sym 'dependents (cons eval-in-sym (get sym 'dependents))))) + + ;; Make sure the source files have entries on the `source' + ;; property so that loading will take place when necessary. + (while source-files + (unless (assq (car source-files) source) + (put sym 'source + (setq source (cons (list (car source-files)) source))) + ;; Might pull in more definitions which affect the value. The + ;; clearing of dependent values etc is done when the + ;; definition is encountered during the load; this is just to + ;; jump past the check for a cached value below. + (set sym nil)) + (setq source-files (cdr source-files))) + + (if (and (boundp sym) + (setq elem (assq mode (symbol-value sym)))) + (cdr elem) + + ;; Check if an evaluation of this symbol is already underway. + ;; In that case we just continue with the "assignment" before + ;; the one currently being evaluated, thereby creating the + ;; illusion if a `setq'-like sequence of assignments. + (let* ((c-buffer-is-cc-mode mode) + (source-pos + (or (assq sym c-lang-constants-under-evaluation) + (cons sym (vector source nil)))) + ;; Append `c-lang-constants-under-evaluation' even if an + ;; earlier entry is found. It's only necessary to get + ;; the recording of dependencies above correct. + (c-lang-constants-under-evaluation + (cons source-pos c-lang-constants-under-evaluation)) + (fallback (get mode 'c-fallback-mode)) + value + ;; Make sure the recursion limits aren't very low + ;; since the `c-lang-const' dependencies can go deep. + (max-specpdl-size (max max-specpdl-size 3000)) + (max-lisp-eval-depth (max max-lisp-eval-depth 1000))) + + (if (if fallback + (let ((backup-source-pos (copy-sequence (cdr source-pos)))) + (and + ;; First try the original mode but don't accept an + ;; entry matching all languages since the fallback + ;; mode might have an explicit entry before that. + (eq (setq value (c-find-assignment-for-mode + (cdr source-pos) mode nil name)) + c-lang-constants) + ;; Try again with the fallback mode from the + ;; original position. Note that + ;; `c-buffer-is-cc-mode' still is the real mode if + ;; language parameterization takes place. + (eq (setq value (c-find-assignment-for-mode + (setcdr source-pos backup-source-pos) + fallback t name)) + c-lang-constants))) + ;; A simple lookup with no fallback mode. + (eq (setq value (c-find-assignment-for-mode + (cdr source-pos) mode t name)) + c-lang-constants)) + (error + "`%s' got no (prior) value in %s (might be a cyclic reference)" + name mode)) + + (condition-case err + (setq value (eval value)) + (error + ;; Print a message to aid in locating the error. We don't + ;; print the error itself since that will be done later by + ;; some caller higher up. + (message "Eval error in the `c-lang-defconst' for `%s' in %s:" + sym mode) + (makunbound sym) + (signal (car err) (cdr err)))) + + (set sym (cons (cons mode value) (symbol-value sym))) + value)))) + +(defun c-find-assignment-for-mode (source-pos mode match-any-lang name) + ;; Find the first assignment entry that applies to MODE at or after + ;; SOURCE-POS. If MATCH-ANY-LANG is non-nil, entries with `t' as + ;; the language list are considered to match, otherwise they don't. + ;; On return SOURCE-POS is updated to point to the next assignment + ;; after the returned one. If no assignment is found, + ;; `c-lang-constants' is returned as a magic value. + ;; + ;; SOURCE-POS is a vector that points out a specific assignment in + ;; the double alist that's used in the `source' property. The first + ;; element is the position in the top alist which is indexed with + ;; the source files, and the second element is the position in the + ;; nested bindings alist. + ;; + ;; NAME is only used for error messages. + + (catch 'found + (let ((file-entry (elt source-pos 0)) + (assignment-entry (elt source-pos 1)) + assignment) + + (while (if assignment-entry + t + ;; Handled the last assignment from one file, begin on the + ;; next. Due to the check in `c-lang-defconst', we know + ;; there's at least one. + (when file-entry + + (unless (aset source-pos 1 + (setq assignment-entry (cdar file-entry))) + ;; The file containing the source definitions has not + ;; been loaded. + (let ((file (symbol-name (caar file-entry))) + (c-lang-constants-under-evaluation nil)) + ;;(message (concat "Loading %s to get the source " + ;; "value for language constant %s") + ;; file name) + (load file)) + + (unless (setq assignment-entry (cdar file-entry)) + ;; The load didn't fill in the source for the + ;; constant as expected. The situation is + ;; probably that a derived mode was written for + ;; and compiled with another version of CC Mode, + ;; and the requested constant isn't in the + ;; currently loaded one. Put in a dummy + ;; assignment that matches no language. + (setcdr (car file-entry) + (setq assignment-entry (list (list nil)))))) + + (aset source-pos 0 (setq file-entry (cdr file-entry))) + t)) + + (setq assignment (car assignment-entry)) + (aset source-pos 1 + (setq assignment-entry (cdr assignment-entry))) + + (when (if (listp (car assignment)) + (memq mode (car assignment)) + match-any-lang) + (throw 'found (cdr assignment)))) + + c-lang-constants))) + +(defun c-lang-major-mode-is (mode) + ;; `c-major-mode-is' expands to a call to this function inside + ;; `c-lang-defconst'. Here we also match the mode(s) against any + ;; fallback modes for the one in `c-buffer-is-cc-mode', so that + ;; e.g. (c-major-mode-is 'c++-mode) is true in a derived language + ;; that has c++-mode as base mode. + (unless (listp mode) + (setq mode (list mode))) + (let (match (buf-mode c-buffer-is-cc-mode)) + (while (if (memq buf-mode mode) + (progn + (setq match t) + nil) + (setq buf-mode (get buf-mode 'c-fallback-mode)))) + match)) + + +(cc-provide 'cc-defs) + +;;; arch-tag: 3bb2629d-dd84-4ff0-ad39-584be0fe3cda +;;; cc-defs.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-engine.el b/site-lisp/cc-mode/5.32.3/cc-engine.el new file mode 100644 index 0000000..159a97c --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-engine.el @@ -0,0 +1,10874 @@ +;;; cc-engine.el --- core syntax guessing engine for CC mode + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2001- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 22-Apr-1997 (split from cc-mode.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; The functions which have docstring documentation can be considered +;; part of an API which other packages can use in CC Mode buffers. +;; Otoh, undocumented functions and functions with the documentation +;; in comments are considered purely internal and can change semantics +;; or even disappear in the future. +;; +;; (This policy applies to CC Mode as a whole, not just this file. It +;; probably also applies to many other Emacs packages, but here it's +;; clearly spelled out.) + +;; Hidden buffer changes +;; +;; Various functions in CC Mode use text properties for caching and +;; syntactic markup purposes, and those of them that might modify such +;; properties but still don't modify the buffer in a visible way are +;; said to do "hidden buffer changes". They should be used within +;; `c-save-buffer-state' or a similar function that saves and restores +;; buffer modifiedness, disables buffer change hooks, etc. +;; +;; Interactive functions are assumed to not do hidden buffer changes, +;; except in the specific parts of them that do real changes. +;; +;; Lineup functions are assumed to do hidden buffer changes. They +;; must not do real changes, though. +;; +;; All other functions that do hidden buffer changes have that noted +;; in their doc string or comment. +;; +;; The intention with this system is to avoid wrapping every leaf +;; function that do hidden buffer changes inside +;; `c-save-buffer-state'. It should be used as near the top of the +;; interactive functions as possible. +;; +;; Functions called during font locking are allowed to do hidden +;; buffer changes since the font-lock package run them in a context +;; similar to `c-save-buffer-state' (in fact, that function is heavily +;; inspired by `save-buffer-state' in the font-lock package). + +;; Use of text properties +;; +;; CC Mode uses several text properties internally to mark up various +;; positions, e.g. to improve speed and to eliminate glitches in +;; interactive refontification. +;; +;; Note: This doc is for internal use only. Other packages should not +;; assume that these text properties are used as described here. +;; +;; 'category +;; Used for "indirection". With its help, some other property can +;; be cheaply and easily switched on or off everywhere it occurs. +;; +;; 'syntax-table +;; Used to modify the syntax of some characters. It is used to +;; mark the "<" and ">" of angle bracket parens with paren syntax, and +;; to "hide" obtrusive characters in preprocessor lines. +;; +;; This property is used on single characters and is therefore +;; always treated as front and rear nonsticky (or start and end open +;; in XEmacs vocabulary). It's therefore installed on +;; `text-property-default-nonsticky' if that variable exists (Emacs +;; >= 21). +;; +;; 'c-is-sws and 'c-in-sws +;; Used by `c-forward-syntactic-ws' and `c-backward-syntactic-ws' to +;; speed them up. See the comment blurb before `c-put-is-sws' +;; below for further details. +;; +;; 'c-type +;; This property is used on single characters to mark positions with +;; special syntactic relevance of various sorts. Its primary use is +;; to avoid glitches when multiline constructs are refontified +;; interactively (on font lock decoration level 3). It's cleared in +;; a region before it's fontified and is then put on relevant chars +;; in that region as they are encountered during the fontification. +;; The value specifies the kind of position: +;; +;; 'c-decl-arg-start +;; Put on the last char of the token preceding each declaration +;; inside a declaration style arglist (typically in a function +;; prototype). +;; +;; 'c-decl-end +;; Put on the last char of the token preceding a declaration. +;; This is used in cases where declaration boundaries can't be +;; recognized simply by looking for a token like ";" or "}". +;; `c-type-decl-end-used' must be set if this is used (see also +;; `c-find-decl-spots'). +;; +;; 'c-<>-arg-sep +;; Put on the commas that separate arguments in angle bracket +;; arglists like C++ template arglists. +;; +;; 'c-decl-id-start and 'c-decl-type-start +;; Put on the last char of the token preceding each declarator +;; in the declarator list of a declaration. They are also used +;; between the identifiers cases like enum declarations. +;; 'c-decl-type-start is used when the declarators are types, +;; 'c-decl-id-start otherwise. +;; +;; 'c-awk-NL-prop +;; Used in AWK mode to mark the various kinds of newlines. See +;; cc-awk.el. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require-when-compile 'cc-langs) +(cc-require 'cc-vars) + +;; Silence the compiler. +(cc-bytecomp-defun buffer-syntactic-context) ; XEmacs +(cc-bytecomp-defun c-fontify-recorded-types-and-refs) +(cc-bytecomp-defvar c-maybe-stale-found-type) + + +;; Make declarations for all the `c-lang-defvar' variables in cc-langs. + +(defmacro c-declare-lang-variables () + `(progn + ,@(mapcan (lambda (init) + `(,(if (elt init 2) + `(defvar ,(car init) nil ,(elt init 2)) + `(defvar ,(car init) nil)) + (make-variable-buffer-local ',(car init)))) + (cdr c-lang-variable-inits)))) +(c-declare-lang-variables) + + +;;; Internal state variables. + +;; Internal state of hungry delete key feature +(defvar c-hungry-delete-key nil) +(make-variable-buffer-local 'c-hungry-delete-key) + +;; The electric flag (toggled by `c-toggle-electric-state'). +;; If t, electric actions (like automatic reindentation, and (if +;; c-auto-newline is also set) auto newlining) will happen when an electric +;; key like `{' is pressed (or an electric keyword like `else'). +(defvar c-electric-flag t) +(make-variable-buffer-local 'c-electric-flag) + +;; Internal state of auto newline feature. +(defvar c-auto-newline nil) +(make-variable-buffer-local 'c-auto-newline) + +;; Included in the mode line to indicate the active submodes. +;; (defvar c-submode-indicators nil) +;; (make-variable-buffer-local 'c-submode-indicators) + +(defun c-calculate-state (arg prevstate) + ;; Calculate the new state of PREVSTATE, t or nil, based on arg. If + ;; arg is nil or zero, toggle the state. If arg is negative, turn + ;; the state off, and if arg is positive, turn the state on + (if (or (not arg) + (zerop (setq arg (prefix-numeric-value arg)))) + (not prevstate) + (> arg 0))) + + +;; Basic handling of preprocessor directives. + +;; This is a dynamically bound cache used together with +;; `c-query-macro-start' and `c-query-and-set-macro-start'. It only +;; works as long as point doesn't cross a macro boundary. +(defvar c-macro-start 'unknown) + +(defsubst c-query-and-set-macro-start () + (if (symbolp c-macro-start) + (setq c-macro-start (save-excursion + (c-save-buffer-state () + (and (c-beginning-of-macro) + (point))))) + c-macro-start)) + +(defsubst c-query-macro-start () + (if (symbolp c-macro-start) + (save-excursion + (c-save-buffer-state () + (and (c-beginning-of-macro) + (point)))) + c-macro-start)) + +;; One element macro cache to cope with continual movement within very large +;; CPP macros. +(defvar c-macro-cache nil) +(make-variable-buffer-local 'c-macro-cache) +;; Nil or cons of the bounds of the most recent CPP form probed by +;; `c-beginning-of-macro', `c-end-of-macro' or `c-syntactic-end-of-macro'. +;; The cdr will be nil if we know only the start of the CPP form. +(defvar c-macro-cache-start-pos nil) +(make-variable-buffer-local 'c-macro-cache-start-pos) +;; The starting position from where we determined `c-macro-cache'. +(defvar c-macro-cache-syntactic nil) +(make-variable-buffer-local 'c-macro-cache-syntactic) +;; non-nil iff `c-macro-cache' has both elements set AND the cdr is at a +;; syntactic end of macro, not merely an apparent one. + +(defun c-invalidate-macro-cache (beg end) + ;; Called from a before-change function. If the change region is before or + ;; in the macro characterised by `c-macro-cache' etc., nullify it + ;; appropriately. BEG and END are the standard before-change-functions + ;; parameters. END isn't used. + (cond + ((null c-macro-cache)) + ((< beg (car c-macro-cache)) + (setq c-macro-cache nil + c-macro-cache-start-pos nil + c-macro-cache-syntactic nil)) + ((and (cdr c-macro-cache) + (< beg (cdr c-macro-cache))) + (setcdr c-macro-cache nil) + (setq c-macro-cache-start-pos beg + c-macro-cache-syntactic nil)))) + +(defun c-beginning-of-macro (&optional lim) + "Go to the beginning of a preprocessor directive. +Leave point at the beginning of the directive and return t if in one, +otherwise return nil and leave point unchanged. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (let ((here (point))) + (when c-opt-cpp-prefix + (if (and (car c-macro-cache) + (>= (point) (car c-macro-cache)) + (or (and (cdr c-macro-cache) + (<= (point) (cdr c-macro-cache))) + (<= (point) c-macro-cache-start-pos))) + (unless (< (car c-macro-cache) (or lim (point-min))) + (progn (goto-char (max (or lim (point-min)) (car c-macro-cache))) + (setq c-macro-cache-start-pos + (max c-macro-cache-start-pos here)) + t)) + (setq c-macro-cache nil + c-macro-cache-start-pos nil + c-macro-cache-syntactic nil) + + (save-restriction + (if lim (narrow-to-region lim (point-max))) + (beginning-of-line) + (while (eq (char-before (1- (point))) ?\\) + (forward-line -1)) + (back-to-indentation) + (if (and (<= (point) here) + (looking-at c-opt-cpp-start)) + (progn + (setq c-macro-cache (cons (point) nil) + c-macro-cache-start-pos here) + t) + (goto-char here) + nil)))))) + +(defun c-end-of-macro () + "Go to the end of a preprocessor directive. +More accurately, move the point to the end of the closest following +line that doesn't end with a line continuation backslash - no check is +done that the point is inside a cpp directive to begin with. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (if (and (cdr c-macro-cache) + (<= (point) (cdr c-macro-cache)) + (>= (point) (car c-macro-cache))) + (goto-char (cdr c-macro-cache)) + (unless (and (car c-macro-cache) + (<= (point) c-macro-cache-start-pos) + (>= (point) (car c-macro-cache))) + (setq c-macro-cache nil + c-macro-cache-start-pos nil + c-macro-cache-syntactic nil)) + (while (progn + (end-of-line) + (when (and (eq (char-before) ?\\) + (not (eobp))) + (forward-char) + t))) + (when (car c-macro-cache) + (setcdr c-macro-cache (point))))) + +(defun c-syntactic-end-of-macro () + ;; Go to the end of a CPP directive, or a "safe" pos just before. + ;; + ;; This is normally the end of the next non-escaped line. A "safe" + ;; position is one not within a string or comment. (The EOL on a line + ;; comment is NOT "safe"). + ;; + ;; This function must only be called from the beginning of a CPP construct. + ;; + ;; Note that this function might do hidden buffer changes. See the comment + ;; at the start of cc-engine.el for more info. + (let* ((here (point)) + (there (progn (c-end-of-macro) (point))) + s) + (unless c-macro-cache-syntactic + (setq s (parse-partial-sexp here there)) + (while (and (or (nth 3 s) ; in a string + (nth 4 s)) ; in a comment (maybe at end of line comment) + (> there here)) ; No infinite loops, please. + (setq there (1- (nth 8 s))) + (setq s (parse-partial-sexp here there))) + (setq c-macro-cache-syntactic (car c-macro-cache))) + (point))) + +(defun c-forward-over-cpp-define-id () + ;; Assuming point is at the "#" that introduces a preprocessor + ;; directive, it's moved forward to the end of the identifier which is + ;; "#define"d (or whatever c-opt-cpp-macro-define specifies). Non-nil + ;; is returned in this case, in all other cases nil is returned and + ;; point isn't moved. + ;; + ;; This function might do hidden buffer changes. + (when (and c-opt-cpp-macro-define-id + (looking-at c-opt-cpp-macro-define-id)) + (goto-char (match-end 0)))) + +(defun c-forward-to-cpp-define-body () + ;; Assuming point is at the "#" that introduces a preprocessor + ;; directive, it's moved forward to the start of the definition body + ;; if it's a "#define" (or whatever c-opt-cpp-macro-define + ;; specifies). Non-nil is returned in this case, in all other cases + ;; nil is returned and point isn't moved. + ;; + ;; This function might do hidden buffer changes. + (when (and c-opt-cpp-macro-define-start + (looking-at c-opt-cpp-macro-define-start) + (not (= (match-end 0) (c-point 'eol)))) + (goto-char (match-end 0)))) + + +;;; Basic utility functions. + +(defun c-syntactic-content (from to paren-level) + ;; Return the given region as a string where all syntactic + ;; whitespace is removed or, where necessary, replaced with a single + ;; space. If PAREN-LEVEL is given then all parens in the region are + ;; collapsed to "()", "[]" etc. + ;; + ;; This function might do hidden buffer changes. + + (save-excursion + (save-restriction + (narrow-to-region from to) + (goto-char from) + (let* ((parts (list nil)) (tail parts) pos in-paren) + + (while (re-search-forward c-syntactic-ws-start to t) + (goto-char (setq pos (match-beginning 0))) + (c-forward-syntactic-ws) + (if (= (point) pos) + (forward-char) + + (when paren-level + (save-excursion + (setq in-paren (= (car (parse-partial-sexp from pos 1)) 1) + pos (point)))) + + (if (and (> pos from) + (< (point) to) + (looking-at "\\w\\|\\s_") + (save-excursion + (goto-char (1- pos)) + (looking-at "\\w\\|\\s_"))) + (progn + (setcdr tail (list (buffer-substring-no-properties from pos) + " ")) + (setq tail (cddr tail))) + (setcdr tail (list (buffer-substring-no-properties from pos))) + (setq tail (cdr tail))) + + (when in-paren + (when (= (car (parse-partial-sexp pos to -1)) -1) + (setcdr tail (list (buffer-substring-no-properties + (1- (point)) (point)))) + (setq tail (cdr tail)))) + + (setq from (point)))) + + (setcdr tail (list (buffer-substring-no-properties from to))) + (apply 'concat (cdr parts)))))) + +(defun c-shift-line-indentation (shift-amt) + ;; Shift the indentation of the current line with the specified + ;; amount (positive inwards). The buffer is modified only if + ;; SHIFT-AMT isn't equal to zero. + (let ((pos (- (point-max) (point))) + (c-macro-start c-macro-start) + tmp-char-inserted) + (if (zerop shift-amt) + nil + ;; If we're on an empty line inside a macro, we take the point + ;; to be at the current indentation and shift it to the + ;; appropriate column. This way we don't treat the extra + ;; whitespace out to the line continuation as indentation. + (when (and (c-query-and-set-macro-start) + (looking-at "[ \t]*\\\\$") + (save-excursion + (skip-chars-backward " \t") + (bolp))) + (insert ?x) + (backward-char) + (setq tmp-char-inserted t)) + (unwind-protect + (let ((col (current-indentation))) + (delete-region (c-point 'bol) (c-point 'boi)) + (beginning-of-line) + (indent-to (+ col shift-amt))) + (when tmp-char-inserted + (delete-char 1)))) + ;; If initial point was within line's indentation and we're not on + ;; a line with a line continuation in a macro, position after the + ;; indentation. Else stay at same point in text. + (if (and (< (point) (c-point 'boi)) + (not tmp-char-inserted)) + (back-to-indentation) + (if (> (- (point-max) pos) (point)) + (goto-char (- (point-max) pos)))))) + +(defsubst c-keyword-sym (keyword) + ;; Return non-nil if the string KEYWORD is a known keyword. More + ;; precisely, the value is the symbol for the keyword in + ;; `c-keywords-obarray'. + (intern-soft keyword c-keywords-obarray)) + +(defsubst c-keyword-member (keyword-sym lang-constant) + ;; Return non-nil if the symbol KEYWORD-SYM, as returned by + ;; `c-keyword-sym', is a member of LANG-CONSTANT, which is the name + ;; of a language constant that ends with "-kwds". If KEYWORD-SYM is + ;; nil then the result is nil. + (get keyword-sym lang-constant)) + +;; String syntax chars, suitable for skip-syntax-(forward|backward). +(defconst c-string-syntax (if (memq 'gen-string-delim c-emacs-features) + "\"|" + "\"")) + +;; Regexp matching string limit syntax. +(defconst c-string-limit-regexp (if (memq 'gen-string-delim c-emacs-features) + "\\s\"\\|\\s|" + "\\s\"")) + +;; Regexp matching WS followed by string limit syntax. +(defconst c-ws*-string-limit-regexp + (concat "[ \t]*\\(" c-string-limit-regexp "\\)")) + +;; Holds formatted error strings for the few cases where parse errors +;; are reported. +(defvar c-parsing-error nil) +(make-variable-buffer-local 'c-parsing-error) + +(defun c-echo-parsing-error (&optional quiet) + (when (and c-report-syntactic-errors c-parsing-error (not quiet)) + (c-benign-error "%s" c-parsing-error)) + c-parsing-error) + +;; Faces given to comments and string literals. This is used in some +;; situations to speed up recognition; it isn't mandatory that font +;; locking is in use. This variable is extended with the face in +;; `c-doc-face-name' when fontification is activated in cc-fonts.el. +(defvar c-literal-faces + (append '(font-lock-comment-face font-lock-string-face) + (when (facep 'font-lock-comment-delimiter-face) + ;; New in Emacs 22. + '(font-lock-comment-delimiter-face)))) + +(defsubst c-put-c-type-property (pos value) + ;; Put a c-type property with the given value at POS. + (c-put-char-property pos 'c-type value)) + +(defun c-clear-c-type-property (from to value) + ;; Remove all occurences of the c-type property that has the given + ;; value in the region between FROM and TO. VALUE is assumed to not + ;; be nil. + ;; + ;; Note: This assumes that c-type is put on single chars only; it's + ;; very inefficient if matching properties cover large regions. + (save-excursion + (goto-char from) + (while (progn + (when (eq (get-text-property (point) 'c-type) value) + (c-clear-char-property (point) 'c-type)) + (goto-char (c-next-single-property-change (point) 'c-type nil to)) + (< (point) to))))) + + +;; Some debug tools to visualize various special positions. This +;; debug code isn't as portable as the rest of CC Mode. + +(cc-bytecomp-defun overlays-in) +(cc-bytecomp-defun overlay-get) +(cc-bytecomp-defun overlay-start) +(cc-bytecomp-defun overlay-end) +(cc-bytecomp-defun delete-overlay) +(cc-bytecomp-defun overlay-put) +(cc-bytecomp-defun make-overlay) + +(defun c-debug-add-face (beg end face) + (c-save-buffer-state ((overlays (overlays-in beg end)) overlay) + (while overlays + (setq overlay (car overlays) + overlays (cdr overlays)) + (when (eq (overlay-get overlay 'face) face) + (setq beg (min beg (overlay-start overlay)) + end (max end (overlay-end overlay))) + (delete-overlay overlay))) + (overlay-put (make-overlay beg end) 'face face))) + +(defun c-debug-remove-face (beg end face) + (c-save-buffer-state ((overlays (overlays-in beg end)) overlay + (ol-beg beg) (ol-end end)) + (while overlays + (setq overlay (car overlays) + overlays (cdr overlays)) + (when (eq (overlay-get overlay 'face) face) + (setq ol-beg (min ol-beg (overlay-start overlay)) + ol-end (max ol-end (overlay-end overlay))) + (delete-overlay overlay))) + (when (< ol-beg beg) + (overlay-put (make-overlay ol-beg beg) 'face face)) + (when (> ol-end end) + (overlay-put (make-overlay end ol-end) 'face face)))) + + +;; `c-beginning-of-statement-1' and accompanying stuff. + +;; KLUDGE ALERT: c-maybe-labelp is used to pass information between +;; c-crosses-statement-barrier-p and c-beginning-of-statement-1. A +;; better way should be implemented, but this will at least shut up +;; the byte compiler. +(defvar c-maybe-labelp) + +;; New awk-compatible version of c-beginning-of-statement-1, ACM 2002/6/22 + +;; Macros used internally in c-beginning-of-statement-1 for the +;; automaton actions. +(defmacro c-bos-push-state () + '(setq stack (cons (cons state saved-pos) + stack))) +(defmacro c-bos-pop-state (&optional do-if-done) + `(if (setq state (car (car stack)) + saved-pos (cdr (car stack)) + stack (cdr stack)) + t + ,do-if-done + (throw 'loop nil))) +(defmacro c-bos-pop-state-and-retry () + '(throw 'loop (setq state (car (car stack)) + saved-pos (cdr (car stack)) + ;; Throw nil if stack is empty, else throw non-nil. + stack (cdr stack)))) +(defmacro c-bos-save-pos () + '(setq saved-pos (vector pos tok ptok pptok))) +(defmacro c-bos-restore-pos () + '(unless (eq (elt saved-pos 0) start) + (setq pos (elt saved-pos 0) + tok (elt saved-pos 1) + ptok (elt saved-pos 2) + pptok (elt saved-pos 3)) + (goto-char pos) + (setq sym nil))) +(defmacro c-bos-save-error-info (missing got) + `(setq saved-pos (vector pos ,missing ,got))) +(defmacro c-bos-report-error () + '(unless noerror + (setq c-parsing-error + (format "No matching `%s' found for `%s' on line %d" + (elt saved-pos 1) + (elt saved-pos 2) + (1+ (count-lines (point-min) + (c-point 'bol (elt saved-pos 0)))))))) + +(defun c-beginning-of-statement-1 (&optional lim ignore-labels + noerror comma-delim) + "Move to the start of the current statement or declaration, or to +the previous one if already at the beginning of one. Only +statements/declarations on the same level are considered, i.e. don't +move into or out of sexps (not even normal expression parentheses). + +If point is already at the earliest statement within braces or parens, +this function doesn't move back into any whitespace preceding it; it +returns 'same in this case. + +Stop at statement continuation tokens like \"else\", \"catch\", +\"finally\" and the \"while\" in \"do ... while\" if the start point +is within the continuation. If starting at such a token, move to the +corresponding statement start. If at the beginning of a statement, +move to the closest containing statement if there is any. This might +also stop at a continuation clause. + +Labels are treated as part of the following statements if +IGNORE-LABELS is non-nil. (FIXME: Doesn't work if we stop at a known +statement start keyword.) Otherwise, each label is treated as a +separate statement. + +Macros are ignored \(i.e. skipped over) unless point is within one, in +which case the content of the macro is treated as normal code. Aside +from any normal statement starts found in it, stop at the first token +of the content in the macro, i.e. the expression of an \"#if\" or the +start of the definition in a \"#define\". Also stop at start of +macros before leaving them. + +Return: +'label if stopped at a label or \"case...:\" or \"default:\"; +'same if stopped at the beginning of the current statement; +'up if stepped to a containing statement; +'previous if stepped to a preceding statement; +'beginning if stepped from a statement continuation clause to + its start clause; or +'macro if stepped to a macro start. +Note that 'same and not 'label is returned if stopped at the same +label without crossing the colon character. + +LIM may be given to limit the search. If the search hits the limit, +point will be left at the closest following token, or at the start +position if that is less ('same is returned in this case). + +NOERROR turns off error logging to `c-parsing-error'. + +Normally only ';' and virtual semicolons are considered to delimit +statements, but if COMMA-DELIM is non-nil then ',' is treated +as a delimiter too. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + ;; The bulk of this function is a pushdown automaton that looks at statement + ;; boundaries and the tokens (such as "while") in c-opt-block-stmt-key. Its + ;; purpose is to keep track of nested statements, ensuring that such + ;; statements are skipped over in their entirety (somewhat akin to what C-M-p + ;; does with nested braces/brackets/parentheses). + ;; + ;; Note: The position of a boundary is the following token. + ;; + ;; Beginning with the current token (the one following point), move back one + ;; sexp at a time (where a sexp is, more or less, either a token or the + ;; entire contents of a brace/bracket/paren pair). Each time a statement + ;; boundary is crossed or a "while"-like token is found, update the state of + ;; the PDA. Stop at the beginning of a statement when the stack (holding + ;; nested statement info) is empty and the position has been moved. + ;; + ;; The following variables constitute the PDA: + ;; + ;; sym: This is either the "while"-like token (e.g. 'for) we've just + ;; scanned back over, 'boundary if we've just gone back over a + ;; statement boundary, or nil otherwise. + ;; state: takes one of the values (nil else else-boundary while + ;; while-boundary catch catch-boundary). + ;; nil means "no "while"-like token yet scanned". + ;; 'else, for example, means "just gone back over an else". + ;; 'else-boundary means "just gone back over a statement boundary + ;; immediately after having gone back over an else". + ;; saved-pos: A vector of either saved positions (tok ptok pptok, etc.) or + ;; of error reporting information. + ;; stack: The stack onto which the PDA pushes its state. Each entry + ;; consists of a saved value of state and saved-pos. An entry is + ;; pushed when we move back over a "continuation" token (e.g. else) + ;; and popped when we encounter the corresponding opening token + ;; (e.g. if). + ;; + ;; + ;; The following diagram briefly outlines the PDA. + ;; + ;; Common state: + ;; "else": Push state, goto state `else'. + ;; "while": Push state, goto state `while'. + ;; "catch" or "finally": Push state, goto state `catch'. + ;; boundary: Pop state. + ;; other: Do nothing special. + ;; + ;; State `else': + ;; boundary: Goto state `else-boundary'. + ;; other: Error, pop state, retry token. + ;; + ;; State `else-boundary': + ;; "if": Pop state. + ;; boundary: Error, pop state. + ;; other: See common state. + ;; + ;; State `while': + ;; boundary: Save position, goto state `while-boundary'. + ;; other: Pop state, retry token. + ;; + ;; State `while-boundary': + ;; "do": Pop state. + ;; boundary: Restore position if it's not at start, pop state. [*see below] + ;; other: See common state. + ;; + ;; State `catch': + ;; boundary: Goto state `catch-boundary'. + ;; other: Error, pop state, retry token. + ;; + ;; State `catch-boundary': + ;; "try": Pop state. + ;; "catch": Goto state `catch'. + ;; boundary: Error, pop state. + ;; other: See common state. + ;; + ;; [*] In the `while-boundary' state, we had pushed a 'while state, and were + ;; searching for a "do" which would have opened a do-while. If we didn't + ;; find it, we discard the analysis done since the "while", go back to this + ;; token in the buffer and restart the scanning there, this time WITHOUT + ;; pushing the 'while state onto the stack. + ;; + ;; In addition to the above there is some special handling of labels + ;; and macros. + + (let ((case-fold-search nil) + (start (point)) + macro-start + (delims (if comma-delim '(?\; ?,) '(?\;))) + (c-stmt-delim-chars (if comma-delim + c-stmt-delim-chars-with-comma + c-stmt-delim-chars)) + c-in-literal-cache c-maybe-labelp after-case:-pos saved + ;; Current position. + pos + ;; Position of last stmt boundary character (e.g. ;). + boundary-pos + ;; The position of the last sexp or bound that follows the + ;; first found colon, i.e. the start of the nonlabel part of + ;; the statement. It's `start' if a colon is found just after + ;; the start. + after-labels-pos + ;; Like `after-labels-pos', but the first such position inside + ;; a label, i.e. the start of the last label before the start + ;; of the nonlabel part of the statement. + last-label-pos + ;; The last position where a label is possible provided the + ;; statement started there. It's nil as long as no invalid + ;; label content has been found (according to + ;; `c-nonlabel-token-key'). It's `start' if no valid label + ;; content was found in the label. Note that we might still + ;; regard it a label if it starts with `c-label-kwds'. + label-good-pos + ;; Putative positions of the components of a bitfield declaration, + ;; e.g. "int foo : NUM_FOO_BITS ;" + bitfield-type-pos bitfield-id-pos bitfield-size-pos + ;; Symbol just scanned back over (e.g. 'while or 'boundary). + ;; See above. + sym + ;; Current state in the automaton. See above. + state + ;; Current saved positions. See above. + saved-pos + ;; Stack of conses (state . saved-pos). + stack + ;; Regexp which matches "for", "if", etc. + (cond-key (or c-opt-block-stmt-key + "\\<\\>")) ; Matches nothing. + ;; Return value. + (ret 'same) + ;; Positions of the last three sexps or bounds we've stopped at. + tok ptok pptok) + + (save-restriction + (if lim (narrow-to-region lim (point-max))) + + (if (save-excursion + (and (c-beginning-of-macro) + (/= (point) start))) + (setq macro-start (point))) + + ;; Try to skip back over unary operator characters, to register + ;; that we've moved. + (while (progn + (setq pos (point)) + (c-backward-syntactic-ws) + ;; Protect post-++/-- operators just before a virtual semicolon. + (and (not (c-at-vsemi-p)) + (/= (skip-chars-backward "-+!*&~@`#") 0)))) + + ;; Skip back over any semicolon here. If it was a bare semicolon, we're + ;; done. Later on we ignore the boundaries for statements that don't + ;; contain any sexp. The only thing that is affected is that the error + ;; checking is a little less strict, and we really don't bother. + (if (and (memq (char-before) delims) + (progn (forward-char -1) + (setq saved (point)) + (c-backward-syntactic-ws) + (or (memq (char-before) delims) + (memq (char-before) '(?: nil)) + (eq (char-syntax (char-before)) ?\() + (c-at-vsemi-p)))) + (setq ret 'previous + pos saved) + + ;; Begin at start and not pos to detect macros if we stand + ;; directly after the #. + (goto-char start) + (if (looking-at "\\<\\|\\W") + ;; Record this as the first token if not starting inside it. + (setq tok start)) + + ;; The following while loop goes back one sexp (balanced parens, + ;; etc. with contents, or symbol or suchlike) each iteration. This + ;; movement is accomplished with a call to c-backward-sexp approx 170 + ;; lines below. + ;; + ;; The loop is exited only by throwing nil to the (catch 'loop ...): + ;; 1. On reaching the start of a macro; + ;; 2. On having passed a stmt boundary with the PDA stack empty; + ;; 3. On reaching the start of an Objective C method def; + ;; 4. From macro `c-bos-pop-state'; when the stack is empty; + ;; 5. From macro `c-bos-pop-state-and-retry' when the stack is empty. + (while + (catch 'loop ;; Throw nil to break, non-nil to continue. + (cond + ;; Are we in a macro, just after the opening #? + ((save-excursion + (and macro-start ; Always NIL for AWK. + (progn (skip-chars-backward " \t") + (eq (char-before) ?#)) + (progn (setq saved (1- (point))) + (beginning-of-line) + (not (eq (char-before (1- (point))) ?\\))) + (looking-at c-opt-cpp-start) + (progn (skip-chars-forward " \t") + (eq (point) saved)))) + (goto-char saved) + (if (and (c-forward-to-cpp-define-body) + (progn (c-forward-syntactic-ws start) + (< (point) start))) + ;; Stop at the first token in the content of the macro. + (setq pos (point) + ignore-labels t) ; Avoid the label check on exit. + (setq pos saved + ret 'macro + ignore-labels t)) + (throw 'loop nil)) ; 1. Start of macro. + + ;; Do a round through the automaton if we've just passed a + ;; statement boundary or passed a "while"-like token. + ((or sym + (and (looking-at cond-key) + (setq sym (intern (match-string 1))))) + + (when (and (< pos start) (null stack)) + (throw 'loop nil)) ; 2. Statement boundary. + + ;; The PDA state handling. + ;; + ;; Refer to the description of the PDA in the opening + ;; comments. In the following OR form, the first leaf + ;; attempts to handles one of the specific actions detailed + ;; (e.g., finding token "if" whilst in state `else-boundary'). + ;; We drop through to the second leaf (which handles common + ;; state) if no specific handler is found in the first cond. + ;; If a parsing error is detected (e.g. an "else" with no + ;; preceding "if"), we throw to the enclosing catch. + ;; + ;; Note that the (eq state 'else) means + ;; "we've just passed an else", NOT "we're looking for an + ;; else". + (or (cond + ((eq state 'else) + (if (eq sym 'boundary) + (setq state 'else-boundary) + (c-bos-report-error) + (c-bos-pop-state-and-retry))) + + ((eq state 'else-boundary) + (cond ((eq sym 'if) + (c-bos-pop-state (setq ret 'beginning))) + ((eq sym 'boundary) + (c-bos-report-error) + (c-bos-pop-state)))) + + ((eq state 'while) + (if (and (eq sym 'boundary) + ;; Since this can cause backtracking we do a + ;; little more careful analysis to avoid it: + ;; If there's a label in front of the while + ;; it can't be part of a do-while. + (not after-labels-pos)) + (progn (c-bos-save-pos) + (setq state 'while-boundary)) + (c-bos-pop-state-and-retry))) ; Can't be a do-while + + ((eq state 'while-boundary) + (cond ((eq sym 'do) + (c-bos-pop-state (setq ret 'beginning))) + ((eq sym 'boundary) ; isn't a do-while + (c-bos-restore-pos) ; the position of the while + (c-bos-pop-state)))) ; no longer searching for do. + + ((eq state 'catch) + (if (eq sym 'boundary) + (setq state 'catch-boundary) + (c-bos-report-error) + (c-bos-pop-state-and-retry))) + + ((eq state 'catch-boundary) + (cond + ((eq sym 'try) + (c-bos-pop-state (setq ret 'beginning))) + ((eq sym 'catch) + (setq state 'catch)) + ((eq sym 'boundary) + (c-bos-report-error) + (c-bos-pop-state))))) + + ;; This is state common. We get here when the previous + ;; cond statement found no particular state handler. + (cond ((eq sym 'boundary) + ;; If we have a boundary at the start + ;; position we push a frame to go to the + ;; previous statement. + (if (>= pos start) + (c-bos-push-state) + (c-bos-pop-state))) + ((eq sym 'else) + (c-bos-push-state) + (c-bos-save-error-info 'if 'else) + (setq state 'else)) + ((eq sym 'while) + ;; Is this a real while, or a do-while? + ;; The next `when' triggers unless we are SURE that + ;; the `while' is not the tailend of a `do-while'. + (when (or (not pptok) + (memq (char-after pptok) delims) + ;; The following kludge is to prevent + ;; infinite recursion when called from + ;; c-awk-after-if-for-while-condition-p, + ;; or the like. + (and (eq (point) start) + (c-vsemi-status-unknown-p)) + (c-at-vsemi-p pptok)) + ;; Since this can cause backtracking we do a + ;; little more careful analysis to avoid it: If + ;; the while isn't followed by a (possibly + ;; virtual) semicolon it can't be a do-while. + (c-bos-push-state) + (setq state 'while))) + ((memq sym '(catch finally)) + (c-bos-push-state) + (c-bos-save-error-info 'try sym) + (setq state 'catch)))) + + (when c-maybe-labelp + ;; We're either past a statement boundary or at the + ;; start of a statement, so throw away any label data + ;; for the previous one. + (setq after-labels-pos nil + last-label-pos nil + c-maybe-labelp nil)))) + + ;; Step to the previous sexp, but not if we crossed a + ;; boundary, since that doesn't consume an sexp. + (if (eq sym 'boundary) + (setq ret 'previous) + + ;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE + ;; BACKWARDS THROUGH THE SOURCE. + + (c-backward-syntactic-ws) + (let ((before-sws-pos (point)) + ;; The end position of the area to search for statement + ;; barriers in this round. + (maybe-after-boundary-pos pos)) + + ;; Go back over exactly one logical sexp, taking proper + ;; account of macros and escaped EOLs. + (while + (progn + (unless (c-safe (c-backward-sexp) t) + ;; Give up if we hit an unbalanced block. Since the + ;; stack won't be empty the code below will report a + ;; suitable error. + (throw 'loop nil)) + (cond + ;; Have we moved into a macro? + ((and (not macro-start) + (c-beginning-of-macro)) + ;; Have we crossed a statement boundary? If not, + ;; keep going back until we find one or a "real" sexp. + (and + (save-excursion + (c-end-of-macro) + (not (c-crosses-statement-barrier-p + (point) maybe-after-boundary-pos))) + (setq maybe-after-boundary-pos (point)))) + ;; Have we just gone back over an escaped NL? This + ;; doesn't count as a sexp. + ((looking-at "\\\\$"))))) + + ;; Have we crossed a statement boundary? + (setq boundary-pos + (cond + ;; Are we at a macro beginning? + ((and (not macro-start) + c-opt-cpp-prefix + (looking-at c-opt-cpp-prefix)) + (save-excursion + (c-end-of-macro) + (c-crosses-statement-barrier-p + (point) maybe-after-boundary-pos))) + ;; Just gone back over a brace block? + ((and + (eq (char-after) ?{) + (not (c-looking-at-inexpr-block lim nil t))) + (save-excursion + (c-forward-sexp) (point))) + ;; Just gone back over some paren block? + ((looking-at "\\s\(") + (save-excursion + (goto-char (1+ (c-down-list-backward + before-sws-pos))) + (c-crosses-statement-barrier-p + (point) maybe-after-boundary-pos))) + ;; Just gone back over an ordinary symbol of some sort? + (t (c-crosses-statement-barrier-p + (point) maybe-after-boundary-pos)))) + + (when boundary-pos + (setq pptok ptok + ptok tok + tok boundary-pos + sym 'boundary) + ;; Like a C "continue". Analyze the next sexp. + (throw 'loop t)))) + + ;; ObjC method def? + (when (and c-opt-method-key + (setq saved (c-in-method-def-p))) + (setq pos saved + ignore-labels t) ; Avoid the label check on exit. + (throw 'loop nil)) ; 3. ObjC method def. + + ;; Might we have a bitfield declaration, " : "? + (if c-has-bitfields + (cond + ;; The : and fields? + ((and (numberp c-maybe-labelp) + (not bitfield-size-pos) + (save-excursion + (goto-char (or tok start)) + (not (looking-at c-keywords-regexp))) + (not (looking-at c-keywords-regexp)) + (not (c-punctuation-in (point) c-maybe-labelp))) + (setq bitfield-size-pos (or tok start) + bitfield-id-pos (point))) + ;; The field? + ((and bitfield-id-pos + (not bitfield-type-pos)) + (if (and (looking-at c-symbol-key) ; Can only be an integer type. :-) + (not (looking-at c-not-primitive-type-keywords-regexp)) + (not (c-punctuation-in (point) tok))) + (setq bitfield-type-pos (point)) + (setq bitfield-size-pos nil + bitfield-id-pos nil))))) + + ;; Handle labels. + (unless (eq ignore-labels t) + (when (numberp c-maybe-labelp) + ;; `c-crosses-statement-barrier-p' has found a colon, so we + ;; might be in a label now. Have we got a real label + ;; (including a case label) or something like C++'s "public:"? + ;; A case label might use an expression rather than a token. + (setq after-case:-pos (or tok start)) + (if (or (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'" + ;; Catch C++'s inheritance construct "class foo : bar". + (save-excursion + (and + (c-safe (c-backward-sexp) t) + (looking-at c-nonlabel-token-2-key)))) + (setq c-maybe-labelp nil) + (if after-labels-pos ; Have we already encountered a label? + (if (not last-label-pos) + (setq last-label-pos (or tok start))) + (setq after-labels-pos (or tok start))) + (setq c-maybe-labelp t + label-good-pos nil))) ; bogus "label" + + (when (and (not label-good-pos) ; i.e. no invalid "label"'s yet + ; been found. + (looking-at c-nonlabel-token-key)) ; e.g. "while :" + ;; We're in a potential label and it's the first + ;; time we've found something that isn't allowed in + ;; one. + (setq label-good-pos (or tok start)))) + + ;; We've moved back by a sexp, so update the token positions. + (setq sym nil + pptok ptok + ptok tok + tok (point) + pos tok) ; always non-nil + ) ; end of (catch loop ....) + ) ; end of sexp-at-a-time (while ....) + + ;; If the stack isn't empty there might be errors to report. + (while stack + (if (and (vectorp saved-pos) (eq (length saved-pos) 3)) + (c-bos-report-error)) + (setq saved-pos (cdr (car stack)) + stack (cdr stack))) + + (when (and (eq ret 'same) + (not (memq sym '(boundary ignore nil)))) + ;; Need to investigate closer whether we've crossed + ;; between a substatement and its containing statement. + (if (setq saved (if (looking-at c-block-stmt-1-key) + ptok + pptok)) + (cond ((> start saved) (setq pos saved)) + ((= start saved) (setq ret 'up))))) + + (when (and (not ignore-labels) + (eq c-maybe-labelp t) + (not (eq ret 'beginning)) + after-labels-pos + (not bitfield-type-pos) ; Bitfields take precedence over labels. + (or (not label-good-pos) + (<= label-good-pos pos) + (progn + (goto-char (if (and last-label-pos + (< last-label-pos start)) + last-label-pos + pos)) + (looking-at c-label-kwds-regexp)))) + ;; We're in a label. Maybe we should step to the statement + ;; after it. + (if (< after-labels-pos start) + (setq pos after-labels-pos) + (setq ret 'label) + (if (and last-label-pos (< last-label-pos start)) + ;; Might have jumped over several labels. Go to the last one. + (setq pos last-label-pos))))) + + ;; Have we got "case :"? + (goto-char pos) + (when (and after-case:-pos + (not (eq ret 'beginning)) + (looking-at c-case-kwds-regexp)) + (if (< after-case:-pos start) + (setq pos after-case:-pos)) + (if (eq ret 'same) + (setq ret 'label))) + + ;; Skip over the unary operators that can start the statement. + (while (progn + (c-backward-syntactic-ws) + ;; protect AWK post-inc/decrement operators, etc. + (and (not (c-at-vsemi-p (point))) + (/= (skip-chars-backward "-+!*&~@`#") 0))) + (setq pos (point))) + (goto-char pos) + ret))) + +(defun c-punctuation-in (from to) + "Return non-nil if there is a non-comment non-macro punctuation character +between FROM and TO. FROM must not be in a string or comment. The returned +value is the position of the first such character." + (save-excursion + (goto-char from) + (let ((pos (point))) + (while (progn (skip-chars-forward c-symbol-chars to) + (c-forward-syntactic-ws to) + (> (point) pos)) + (setq pos (point)))) + (and (< (point) to) (point)))) + +(defun c-crosses-statement-barrier-p (from to) + "Return non-nil if buffer positions FROM to TO cross one or more +statement or declaration boundaries. The returned value is actually +the position of the earliest boundary char. FROM must not be within +a string or comment. + +The variable `c-maybe-labelp' is set to the position of the first `:' that +might start a label (i.e. not part of `::' and not preceded by `?'). If a +single `?' is found, then `c-maybe-labelp' is cleared. + +For AWK, a statement which is terminated by an EOL (not a \; or a }) is +regarded as having a \"virtual semicolon\" immediately after the last token on +the line. If this virtual semicolon is _at_ from, the function recognizes it. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (let* ((skip-chars + ;; If the current language has CPP macros, insert # into skip-chars. + (if c-opt-cpp-symbol + (concat (substring c-stmt-delim-chars 0 1) ; "^" + c-opt-cpp-symbol ; usually "#" + (substring c-stmt-delim-chars 1)) ; e.g. ";{}?:" + c-stmt-delim-chars)) + (non-skip-list + (append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:) + lit-range vsemi-pos) + (save-restriction + (widen) + (save-excursion + (catch 'done + (goto-char from) + (while (progn (skip-chars-forward + skip-chars + (min to (c-point 'bonl))) + (< (point) to)) + (cond + ;; Virtual semicolon? + ((and (bolp) + (save-excursion + (progn + (if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment? + (goto-char (car lit-range))) + (c-backward-syntactic-ws) ; ? put a limit here, maybe? + (setq vsemi-pos (point)) + (c-at-vsemi-p)))) + (throw 'done vsemi-pos)) + ;; In a string/comment? + ((setq lit-range (c-literal-limits from)) + (goto-char (cdr lit-range))) + ((eq (char-after) ?:) + (forward-char) + (if (and (eq (char-after) ?:) + (< (point) to)) + ;; Ignore scope operators. + (forward-char) + (setq c-maybe-labelp (1- (point))))) + ((eq (char-after) ??) + ;; A question mark. Can't be a label, so stop + ;; looking for more : and ?. + (setq c-maybe-labelp nil + skip-chars (substring c-stmt-delim-chars 0 -2))) + ;; At a CPP construct? + ((and c-opt-cpp-symbol (looking-at c-opt-cpp-symbol) + (save-excursion + (forward-line 0) + (looking-at c-opt-cpp-prefix))) + (c-end-of-macro)) + ((memq (char-after) non-skip-list) + (throw 'done (point))))) + ;; In trailing space after an as yet undetected virtual semicolon? + (c-backward-syntactic-ws from) + (if (and (< (point) to) + (c-at-vsemi-p)) + (point) + nil)))))) + +(defun c-at-statement-start-p () + "Return non-nil if the point is at the first token in a statement +or somewhere in the syntactic whitespace before it. + +A \"statement\" here is not restricted to those inside code blocks. +Any kind of declaration-like construct that occur outside function +bodies is also considered a \"statement\". + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (save-excursion + (let ((end (point)) + c-maybe-labelp) + (c-syntactic-skip-backward (substring c-stmt-delim-chars 1) nil t) + (or (bobp) + (eq (char-before) ?}) + (and (eq (char-before) ?{) + (not (and c-special-brace-lists + (progn (backward-char) + (c-looking-at-special-brace-list))))) + (c-crosses-statement-barrier-p (point) end))))) + +(defun c-at-expression-start-p () + "Return non-nil if the point is at the first token in an expression or +statement, or somewhere in the syntactic whitespace before it. + +An \"expression\" here is a bit different from the normal language +grammar sense: It's any sequence of expression tokens except commas, +unless they are enclosed inside parentheses of some kind. Also, an +expression never continues past an enclosing parenthesis, but it might +contain parenthesis pairs of any sort except braces. + +Since expressions never cross statement boundaries, this function also +recognizes statement beginnings, just like `c-at-statement-start-p'. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (save-excursion + (let ((end (point)) + (c-stmt-delim-chars c-stmt-delim-chars-with-comma) + c-maybe-labelp) + (c-syntactic-skip-backward (substring c-stmt-delim-chars 1) nil t) + (or (bobp) + (memq (char-before) '(?{ ?})) + (save-excursion (backward-char) + (looking-at "\\s(")) + (c-crosses-statement-barrier-p (point) end))))) + + +;; A set of functions that covers various idiosyncrasies in +;; implementations of `forward-comment'. + +;; Note: Some emacsen considers incorrectly that any line comment +;; ending with a backslash continues to the next line. I can't think +;; of any way to work around that in a reliable way without changing +;; the buffer, though. Suggestions welcome. ;) (No, temporarily +;; changing the syntax for backslash doesn't work since we must treat +;; escapes in string literals correctly.) + +(defun c-forward-single-comment () + "Move forward past whitespace and the closest following comment, if any. +Return t if a comment was found, nil otherwise. In either case, the +point is moved past the following whitespace. Line continuations, +i.e. a backslashes followed by line breaks, are treated as whitespace. +The line breaks that end line comments are considered to be the +comment enders, so the point will be put on the beginning of the next +line if it moved past a line comment. + +This function does not do any hidden buffer changes." + + (let ((start (point))) + (when (looking-at "\\([ \t\n\r\f\v]\\|\\\\[\n\r]\\)+") + (goto-char (match-end 0))) + + (when (forward-comment 1) + (if (eobp) + ;; Some emacsen (e.g. XEmacs 21) return t when moving + ;; forwards at eob. + nil + + ;; Emacs includes the ending newline in a b-style (c++) + ;; comment, but XEmacs doesn't. We depend on the Emacs + ;; behavior (which also is symmetric). + (if (and (eolp) (elt (parse-partial-sexp start (point)) 7)) + (condition-case nil (forward-char 1))) + + t)))) + +(defsubst c-forward-comments () + "Move forward past all following whitespace and comments. +Line continuations, i.e. a backslashes followed by line breaks, are +treated as whitespace. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (while (or + ;; If forward-comment in at least XEmacs 21 is given a large + ;; positive value, it'll loop all the way through if it hits + ;; eob. + (and (forward-comment 5) + ;; Some emacsen (e.g. XEmacs 21) return t when moving + ;; forwards at eob. + (not (eobp))) + + (when (looking-at "\\\\[\n\r]") + (forward-char 2) + t)))) + +(defun c-backward-single-comment () + "Move backward past whitespace and the closest preceding comment, if any. +Return t if a comment was found, nil otherwise. In either case, the +point is moved past the preceding whitespace. Line continuations, +i.e. a backslashes followed by line breaks, are treated as whitespace. +The line breaks that end line comments are considered to be the +comment enders, so the point cannot be at the end of the same line to +move over a line comment. + +This function does not do any hidden buffer changes." + + (let ((start (point))) + ;; When we got newline terminated comments, forward-comment in all + ;; supported emacsen so far will stop at eol of each line not + ;; ending with a comment when moving backwards. This corrects for + ;; that, and at the same time handles line continuations. + (while (progn + (skip-chars-backward " \t\n\r\f\v") + (and (looking-at "[\n\r]") + (eq (char-before) ?\\))) + (backward-char)) + + (if (bobp) + ;; Some emacsen (e.g. Emacs 19.34) return t when moving + ;; backwards at bob. + nil + + ;; Leave point after the closest following newline if we've + ;; backed up over any above, since forward-comment won't move + ;; backward over a line comment if point is at the end of the + ;; same line. + (re-search-forward "\\=\\s *[\n\r]" start t) + + (if (if (let (open-paren-in-column-0-is-defun-start) (forward-comment -1)) + (if (eolp) + ;; If forward-comment above succeeded and we're at eol + ;; then the newline we moved over above didn't end a + ;; line comment, so we give it another go. + (let (open-paren-in-column-0-is-defun-start) + (forward-comment -1)) + t)) + + ;; Emacs <= 20 and XEmacs move back over the closer of a + ;; block comment that lacks an opener. + (if (looking-at "\\*/") + (progn (forward-char 2) nil) + t))))) + +(defsubst c-backward-comments () + "Move backward past all preceding whitespace and comments. +Line continuations, i.e. a backslashes followed by line breaks, are +treated as whitespace. The line breaks that end line comments are +considered to be the comment enders, so the point cannot be at the end +of the same line to move over a line comment. Unlike +c-backward-syntactic-ws, this function doesn't move back over +preprocessor directives. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (let ((start (point))) + (while (and + ;; `forward-comment' in some emacsen (e.g. XEmacs 21.4) + ;; return t when moving backwards at bob. + (not (bobp)) + + (if (let (open-paren-in-column-0-is-defun-start) + (forward-comment -1)) + (if (looking-at "\\*/") + ;; Emacs <= 20 and XEmacs move back over the + ;; closer of a block comment that lacks an opener. + (progn (forward-char 2) nil) + t) + + ;; XEmacs treats line continuations as whitespace but + ;; only in the backward direction, which seems a bit + ;; odd. Anyway, this is necessary for Emacs. + (when (and (looking-at "[\n\r]") + (eq (char-before) ?\\) + (< (point) start)) + (backward-char) + t)))))) + + +;; Tools for skipping over syntactic whitespace. + +;; The following functions use text properties to cache searches over +;; large regions of syntactic whitespace. It works as follows: +;; +;; o If a syntactic whitespace region contains anything but simple +;; whitespace (i.e. space, tab and line breaks), the text property +;; `c-in-sws' is put over it. At places where we have stopped +;; within that region there's also a `c-is-sws' text property. +;; That since there typically are nested whitespace inside that +;; must be handled separately, e.g. whitespace inside a comment or +;; cpp directive. Thus, from one point with `c-is-sws' it's safe +;; to jump to another point with that property within the same +;; `c-in-sws' region. It can be likened to a ladder where +;; `c-in-sws' marks the bars and `c-is-sws' the rungs. +;; +;; o The `c-is-sws' property is put on the simple whitespace chars at +;; a "rung position" and also maybe on the first following char. +;; As many characters as can be conveniently found in this range +;; are marked, but no assumption can be made that the whole range +;; is marked (it could be clobbered by later changes, for +;; instance). +;; +;; Note that some part of the beginning of a sequence of simple +;; whitespace might be part of the end of a preceding line comment +;; or cpp directive and must not be considered part of the "rung". +;; Such whitespace is some amount of horizontal whitespace followed +;; by a newline. In the case of cpp directives it could also be +;; two newlines with horizontal whitespace between them. +;; +;; The reason to include the first following char is to cope with +;; "rung positions" that doesn't have any ordinary whitespace. If +;; `c-is-sws' is put on a token character it does not have +;; `c-in-sws' set simultaneously. That's the only case when that +;; can occur, and the reason for not extending the `c-in-sws' +;; region to cover it is that the `c-in-sws' region could then be +;; accidentally merged with a following one if the token is only +;; one character long. +;; +;; o On buffer changes the `c-in-sws' and `c-is-sws' properties are +;; removed in the changed region. If the change was inside +;; syntactic whitespace that means that the "ladder" is broken, but +;; a later call to `c-forward-sws' or `c-backward-sws' will use the +;; parts on either side and use an ordinary search only to "repair" +;; the gap. +;; +;; Special care needs to be taken if a region is removed: If there +;; are `c-in-sws' on both sides of it which do not connect inside +;; the region then they can't be joined. If e.g. a marked macro is +;; broken, syntactic whitespace inside the new text might be +;; marked. If those marks would become connected with the old +;; `c-in-sws' range around the macro then we could get a ladder +;; with one end outside the macro and the other at some whitespace +;; within it. +;; +;; The main motivation for this system is to increase the speed in +;; skipping over the large whitespace regions that can occur at the +;; top level in e.g. header files that contain a lot of comments and +;; cpp directives. For small comments inside code it's probably +;; slower than using `forward-comment' straightforwardly, but speed is +;; not a significant factor there anyway. + +; (defface c-debug-is-sws-face +; '((t (:background "GreenYellow"))) +; "Debug face to mark the `c-is-sws' property.") +; (defface c-debug-in-sws-face +; '((t (:underline t))) +; "Debug face to mark the `c-in-sws' property.") + +; (defun c-debug-put-sws-faces () +; ;; Put the sws debug faces on all the `c-is-sws' and `c-in-sws' +; ;; properties in the buffer. +; (interactive) +; (save-excursion +; (c-save-buffer-state (in-face) +; (goto-char (point-min)) +; (setq in-face (if (get-text-property (point) 'c-is-sws) +; (point))) +; (while (progn +; (goto-char (next-single-property-change +; (point) 'c-is-sws nil (point-max))) +; (if in-face +; (progn +; (c-debug-add-face in-face (point) 'c-debug-is-sws-face) +; (setq in-face nil)) +; (setq in-face (point))) +; (not (eobp)))) +; (goto-char (point-min)) +; (setq in-face (if (get-text-property (point) 'c-in-sws) +; (point))) +; (while (progn +; (goto-char (next-single-property-change +; (point) 'c-in-sws nil (point-max))) +; (if in-face +; (progn +; (c-debug-add-face in-face (point) 'c-debug-in-sws-face) +; (setq in-face nil)) +; (setq in-face (point))) +; (not (eobp))))))) + +(defmacro c-debug-sws-msg (&rest args) + ;;`(message ,@args) + ) + +(defmacro c-put-is-sws (beg end) + ;; This macro does a hidden buffer change. + `(let ((beg ,beg) (end ,end)) + (put-text-property beg end 'c-is-sws t) + ,@(when (facep 'c-debug-is-sws-face) + `((c-debug-add-face beg end 'c-debug-is-sws-face))))) + +(defmacro c-put-in-sws (beg end) + ;; This macro does a hidden buffer change. + `(let ((beg ,beg) (end ,end)) + (put-text-property beg end 'c-in-sws t) + ,@(when (facep 'c-debug-is-sws-face) + `((c-debug-add-face beg end 'c-debug-in-sws-face))))) + +(defmacro c-remove-is-sws (beg end) + ;; This macro does a hidden buffer change. + `(let ((beg ,beg) (end ,end)) + (remove-text-properties beg end '(c-is-sws nil)) + ,@(when (facep 'c-debug-is-sws-face) + `((c-debug-remove-face beg end 'c-debug-is-sws-face))))) + +(defmacro c-remove-in-sws (beg end) + ;; This macro does a hidden buffer change. + `(let ((beg ,beg) (end ,end)) + (remove-text-properties beg end '(c-in-sws nil)) + ,@(when (facep 'c-debug-is-sws-face) + `((c-debug-remove-face beg end 'c-debug-in-sws-face))))) + +(defmacro c-remove-is-and-in-sws (beg end) + ;; This macro does a hidden buffer change. + `(let ((beg ,beg) (end ,end)) + (remove-text-properties beg end '(c-is-sws nil c-in-sws nil)) + ,@(when (facep 'c-debug-is-sws-face) + `((c-debug-remove-face beg end 'c-debug-is-sws-face) + (c-debug-remove-face beg end 'c-debug-in-sws-face))))) + +(defsubst c-invalidate-sws-region-after (beg end) + ;; Called from `after-change-functions'. Note that if + ;; `c-forward-sws' or `c-backward-sws' are used outside + ;; `c-save-buffer-state' or similar then this will remove the cache + ;; properties right after they're added. + ;; + ;; This function does hidden buffer changes. + + (save-excursion + ;; Adjust the end to remove the properties in any following simple + ;; ws up to and including the next line break, if there is any + ;; after the changed region. This is necessary e.g. when a rung + ;; marked empty line is converted to a line comment by inserting + ;; "//" before the line break. In that case the line break would + ;; keep the rung mark which could make a later `c-backward-sws' + ;; move into the line comment instead of over it. + (goto-char end) + (skip-chars-forward " \t\f\v") + (when (and (eolp) (not (eobp))) + (setq end (1+ (point))))) + + (when (and (= beg end) + (get-text-property beg 'c-in-sws) + (> beg (point-min)) + (get-text-property (1- beg) 'c-in-sws)) + ;; Ensure that an `c-in-sws' range gets broken. Note that it isn't + ;; safe to keep a range that was continuous before the change. E.g: + ;; + ;; #define foo + ;; \ + ;; bar + ;; + ;; There can be a "ladder" between "#" and "b". Now, if the newline + ;; after "foo" is removed then "bar" will become part of the cpp + ;; directive instead of a syntactically relevant token. In that + ;; case there's no longer syntactic ws from "#" to "b". + (setq beg (1- beg))) + + (c-debug-sws-msg "c-invalidate-sws-region-after [%s..%s]" beg end) + (c-remove-is-and-in-sws beg end)) + +(defun c-forward-sws () + ;; Used by `c-forward-syntactic-ws' to implement the unbounded search. + ;; + ;; This function might do hidden buffer changes. + + (let (;; `rung-pos' is set to a position as early as possible in the + ;; unmarked part of the simple ws region. + (rung-pos (point)) next-rung-pos rung-end-pos last-put-in-sws-pos + rung-is-marked next-rung-is-marked simple-ws-end + ;; `safe-start' is set when it's safe to cache the start position. + ;; It's not set if we've initially skipped over comments and line + ;; continuations since we might have gone out through the end of a + ;; macro then. This provision makes `c-forward-sws' not populate the + ;; cache in the majority of cases, but otoh is `c-backward-sws' by far + ;; more common. + safe-start) + + ;; Skip simple ws and do a quick check on the following character to see + ;; if it's anything that can't start syntactic ws, so we can bail out + ;; early in the majority of cases when there just are a few ws chars. + (skip-chars-forward " \t\n\r\f\v") + (when (looking-at c-syntactic-ws-start) + + (setq rung-end-pos (min (1+ (point)) (point-max))) + (if (setq rung-is-marked (text-property-any rung-pos rung-end-pos + 'c-is-sws t)) + ;; Find the last rung position to avoid setting properties in all + ;; the cases when the marked rung is complete. + ;; (`next-single-property-change' is certain to move at least one + ;; step forward.) + (setq rung-pos (1- (c-next-single-property-change + rung-is-marked 'c-is-sws nil rung-end-pos))) + ;; Got no marked rung here. Since the simple ws might have started + ;; inside a line comment or cpp directive we must set `rung-pos' as + ;; high as possible. + (setq rung-pos (point))) + + (while + (progn + (while + (when (and rung-is-marked + (get-text-property (point) 'c-in-sws)) + + ;; The following search is the main reason that `c-in-sws' + ;; and `c-is-sws' aren't combined to one property. + (goto-char (c-next-single-property-change + (point) 'c-in-sws nil (point-max))) + (unless (get-text-property (point) 'c-is-sws) + ;; If the `c-in-sws' region extended past the last + ;; `c-is-sws' char we have to go back a bit. + (or (get-text-property (1- (point)) 'c-is-sws) + (goto-char (previous-single-property-change + (point) 'c-is-sws))) + (backward-char)) + + (c-debug-sws-msg + "c-forward-sws cached move %s -> %s (max %s)" + rung-pos (point) (point-max)) + + (setq rung-pos (point)) + (and (> (skip-chars-forward " \t\n\r\f\v") 0) + (not (eobp)))) + + ;; We'll loop here if there is simple ws after the last rung. + ;; That means that there's been some change in it and it's + ;; possible that we've stepped into another ladder, so extend + ;; the previous one to join with it if there is one, and try to + ;; use the cache again. + (c-debug-sws-msg + "c-forward-sws extending rung with [%s..%s] (max %s)" + (1+ rung-pos) (1+ (point)) (point-max)) + (unless (get-text-property (point) 'c-is-sws) + ;; Remove any `c-in-sws' property from the last char of + ;; the rung before we mark it with `c-is-sws', so that we + ;; won't connect with the remains of a broken "ladder". + (c-remove-in-sws (point) (1+ (point)))) + (c-put-is-sws (1+ rung-pos) + (1+ (point))) + (c-put-in-sws rung-pos + (setq rung-pos (point) + last-put-in-sws-pos rung-pos))) + + (setq simple-ws-end (point)) + (c-forward-comments) + + (cond + ((/= (point) simple-ws-end) + ;; Skipped over comments. Don't cache at eob in case the buffer + ;; is narrowed. + (not (eobp))) + + ((save-excursion + (and c-opt-cpp-prefix + (looking-at c-opt-cpp-start) + (progn (skip-chars-backward " \t") + (bolp)) + (or (bobp) + (progn (backward-char) + (not (eq (char-before) ?\\)))))) + ;; Skip a preprocessor directive. + (end-of-line) + (while (and (eq (char-before) ?\\) + (= (forward-line 1) 0)) + (end-of-line)) + (forward-line 1) + (setq safe-start t) + ;; Don't cache at eob in case the buffer is narrowed. + (not (eobp))))) + + ;; We've searched over a piece of non-white syntactic ws. See if this + ;; can be cached. + (setq next-rung-pos (point)) + (skip-chars-forward " \t\n\r\f\v") + (setq rung-end-pos (min (1+ (point)) (point-max))) + + (if (or + ;; Cache if we haven't skipped comments only, and if we started + ;; either from a marked rung or from a completely uncached + ;; position. + (and safe-start + (or rung-is-marked + (not (get-text-property simple-ws-end 'c-in-sws)))) + + ;; See if there's a marked rung in the encountered simple ws. If + ;; so then we can cache, unless `safe-start' is nil. Even then + ;; we need to do this to check if the cache can be used for the + ;; next step. + (and (setq next-rung-is-marked + (text-property-any next-rung-pos rung-end-pos + 'c-is-sws t)) + safe-start)) + + (progn + (c-debug-sws-msg + "c-forward-sws caching [%s..%s] - [%s..%s] (max %s)" + rung-pos (1+ simple-ws-end) next-rung-pos rung-end-pos + (point-max)) + + ;; Remove the properties for any nested ws that might be cached. + ;; Only necessary for `c-is-sws' since `c-in-sws' will be set + ;; anyway. + (c-remove-is-sws (1+ simple-ws-end) next-rung-pos) + (unless (and rung-is-marked (= rung-pos simple-ws-end)) + (c-put-is-sws rung-pos + (1+ simple-ws-end)) + (setq rung-is-marked t)) + (c-put-in-sws rung-pos + (setq rung-pos (point) + last-put-in-sws-pos rung-pos)) + (unless (get-text-property (1- rung-end-pos) 'c-is-sws) + ;; Remove any `c-in-sws' property from the last char of + ;; the rung before we mark it with `c-is-sws', so that we + ;; won't connect with the remains of a broken "ladder". + (c-remove-in-sws (1- rung-end-pos) rung-end-pos)) + (c-put-is-sws next-rung-pos + rung-end-pos)) + + (c-debug-sws-msg + "c-forward-sws not caching [%s..%s] - [%s..%s] (max %s)" + rung-pos (1+ simple-ws-end) next-rung-pos rung-end-pos + (point-max)) + + ;; Set `rung-pos' for the next rung. It's the same thing here as + ;; initially, except that the rung position is set as early as + ;; possible since we can't be in the ending ws of a line comment or + ;; cpp directive now. + (if (setq rung-is-marked next-rung-is-marked) + (setq rung-pos (1- (c-next-single-property-change + rung-is-marked 'c-is-sws nil rung-end-pos))) + (setq rung-pos next-rung-pos)) + (setq safe-start t))) + + ;; Make sure that the newly marked `c-in-sws' region doesn't connect to + ;; another one after the point (which might occur when editing inside a + ;; comment or macro). + (when (eq last-put-in-sws-pos (point)) + (cond ((< last-put-in-sws-pos (point-max)) + (c-debug-sws-msg + "c-forward-sws clearing at %s for cache separation" + last-put-in-sws-pos) + (c-remove-in-sws last-put-in-sws-pos + (1+ last-put-in-sws-pos))) + (t + ;; If at eob we have to clear the last character before the end + ;; instead since the buffer might be narrowed and there might + ;; be a `c-in-sws' after (point-max). In this case it's + ;; necessary to clear both properties. + (c-debug-sws-msg + "c-forward-sws clearing thoroughly at %s for cache separation" + (1- last-put-in-sws-pos)) + (c-remove-is-and-in-sws (1- last-put-in-sws-pos) + last-put-in-sws-pos)))) + ))) + +(defun c-backward-sws () + ;; Used by `c-backward-syntactic-ws' to implement the unbounded search. + ;; + ;; This function might do hidden buffer changes. + + (let (;; `rung-pos' is set to a position as late as possible in the unmarked + ;; part of the simple ws region. + (rung-pos (point)) next-rung-pos last-put-in-sws-pos + rung-is-marked simple-ws-beg cmt-skip-pos) + + ;; Skip simple horizontal ws and do a quick check on the preceding + ;; character to see if it's anying that can't end syntactic ws, so we can + ;; bail out early in the majority of cases when there just are a few ws + ;; chars. Newlines are complicated in the backward direction, so we can't + ;; skip over them. + (skip-chars-backward " \t\f") + (when (and (not (bobp)) + (save-excursion + (backward-char) + (looking-at c-syntactic-ws-end))) + + ;; Try to find a rung position in the simple ws preceding point, so that + ;; we can get a cache hit even if the last bit of the simple ws has + ;; changed recently. + (setq simple-ws-beg (point)) + (skip-chars-backward " \t\n\r\f\v") + (if (setq rung-is-marked (text-property-any + (point) (min (1+ rung-pos) (point-max)) + 'c-is-sws t)) + ;; `rung-pos' will be the earliest marked position, which means that + ;; there might be later unmarked parts in the simple ws region. + ;; It's not worth the effort to fix that; the last part of the + ;; simple ws is also typically edited often, so it could be wasted. + (goto-char (setq rung-pos rung-is-marked)) + (goto-char simple-ws-beg)) + + (while + (progn + (while + (when (and rung-is-marked + (not (bobp)) + (get-text-property (1- (point)) 'c-in-sws)) + + ;; The following search is the main reason that `c-in-sws' + ;; and `c-is-sws' aren't combined to one property. + (goto-char (previous-single-property-change + (point) 'c-in-sws nil (point-min))) + (unless (get-text-property (point) 'c-is-sws) + ;; If the `c-in-sws' region extended past the first + ;; `c-is-sws' char we have to go forward a bit. + (goto-char (c-next-single-property-change + (point) 'c-is-sws))) + + (c-debug-sws-msg + "c-backward-sws cached move %s <- %s (min %s)" + (point) rung-pos (point-min)) + + (setq rung-pos (point)) + (if (and (< (min (skip-chars-backward " \t\f\v") + (progn + (setq simple-ws-beg (point)) + (skip-chars-backward " \t\n\r\f\v"))) + 0) + (setq rung-is-marked + (text-property-any (point) rung-pos + 'c-is-sws t))) + t + (goto-char simple-ws-beg) + nil)) + + ;; We'll loop here if there is simple ws before the first rung. + ;; That means that there's been some change in it and it's + ;; possible that we've stepped into another ladder, so extend + ;; the previous one to join with it if there is one, and try to + ;; use the cache again. + (c-debug-sws-msg + "c-backward-sws extending rung with [%s..%s] (min %s)" + rung-is-marked rung-pos (point-min)) + (unless (get-text-property (1- rung-pos) 'c-is-sws) + ;; Remove any `c-in-sws' property from the last char of + ;; the rung before we mark it with `c-is-sws', so that we + ;; won't connect with the remains of a broken "ladder". + (c-remove-in-sws (1- rung-pos) rung-pos)) + (c-put-is-sws rung-is-marked + rung-pos) + (c-put-in-sws rung-is-marked + (1- rung-pos)) + (setq rung-pos rung-is-marked + last-put-in-sws-pos rung-pos)) + + (c-backward-comments) + (setq cmt-skip-pos (point)) + + (cond + ((and c-opt-cpp-prefix + (/= cmt-skip-pos simple-ws-beg) + (c-beginning-of-macro)) + ;; Inside a cpp directive. See if it should be skipped over. + (let ((cpp-beg (point))) + + ;; Move back over all line continuations in the region skipped + ;; over by `c-backward-comments'. If we go past it then we + ;; started inside the cpp directive. + (goto-char simple-ws-beg) + (beginning-of-line) + (while (and (> (point) cmt-skip-pos) + (progn (backward-char) + (eq (char-before) ?\\))) + (beginning-of-line)) + + (if (< (point) cmt-skip-pos) + ;; Don't move past the cpp directive if we began inside + ;; it. Note that the position at the end of the last line + ;; of the macro is also considered to be within it. + (progn (goto-char cmt-skip-pos) + nil) + + ;; It's worthwhile to spend a little bit of effort on finding + ;; the end of the macro, to get a good `simple-ws-beg' + ;; position for the cache. Note that `c-backward-comments' + ;; could have stepped over some comments before going into + ;; the macro, and then `simple-ws-beg' must be kept on the + ;; same side of those comments. + (goto-char simple-ws-beg) + (skip-chars-backward " \t\n\r\f\v") + (if (eq (char-before) ?\\) + (forward-char)) + (forward-line 1) + (if (< (point) simple-ws-beg) + ;; Might happen if comments after the macro were skipped + ;; over. + (setq simple-ws-beg (point))) + + (goto-char cpp-beg) + t))) + + ((/= (save-excursion + (skip-chars-forward " \t\n\r\f\v" simple-ws-beg) + (setq next-rung-pos (point))) + simple-ws-beg) + ;; Skipped over comments. Must put point at the end of + ;; the simple ws at point since we might be after a line + ;; comment or cpp directive that's been partially + ;; narrowed out, and we can't risk marking the simple ws + ;; at the end of it. + (goto-char next-rung-pos) + t))) + + ;; We've searched over a piece of non-white syntactic ws. See if this + ;; can be cached. + (setq next-rung-pos (point)) + (skip-chars-backward " \t\f\v") + + (if (or + ;; Cache if we started either from a marked rung or from a + ;; completely uncached position. + rung-is-marked + (not (get-text-property (1- simple-ws-beg) 'c-in-sws)) + + ;; Cache if there's a marked rung in the encountered simple ws. + (save-excursion + (skip-chars-backward " \t\n\r\f\v") + (text-property-any (point) (min (1+ next-rung-pos) (point-max)) + 'c-is-sws t))) + + (progn + (c-debug-sws-msg + "c-backward-sws caching [%s..%s] - [%s..%s] (min %s)" + (point) (1+ next-rung-pos) + simple-ws-beg (min (1+ rung-pos) (point-max)) + (point-min)) + + ;; Remove the properties for any nested ws that might be cached. + ;; Only necessary for `c-is-sws' since `c-in-sws' will be set + ;; anyway. + (c-remove-is-sws (1+ next-rung-pos) simple-ws-beg) + (unless (and rung-is-marked (= simple-ws-beg rung-pos)) + (let ((rung-end-pos (min (1+ rung-pos) (point-max)))) + (unless (get-text-property (1- rung-end-pos) 'c-is-sws) + ;; Remove any `c-in-sws' property from the last char of + ;; the rung before we mark it with `c-is-sws', so that we + ;; won't connect with the remains of a broken "ladder". + (c-remove-in-sws (1- rung-end-pos) rung-end-pos)) + (c-put-is-sws simple-ws-beg + rung-end-pos) + (setq rung-is-marked t))) + (c-put-in-sws (setq simple-ws-beg (point) + last-put-in-sws-pos simple-ws-beg) + rung-pos) + (c-put-is-sws (setq rung-pos simple-ws-beg) + (1+ next-rung-pos))) + + (c-debug-sws-msg + "c-backward-sws not caching [%s..%s] - [%s..%s] (min %s)" + (point) (1+ next-rung-pos) + simple-ws-beg (min (1+ rung-pos) (point-max)) + (point-min)) + (setq rung-pos next-rung-pos + simple-ws-beg (point)) + )) + + ;; Make sure that the newly marked `c-in-sws' region doesn't connect to + ;; another one before the point (which might occur when editing inside a + ;; comment or macro). + (when (eq last-put-in-sws-pos (point)) + (cond ((< (point-min) last-put-in-sws-pos) + (c-debug-sws-msg + "c-backward-sws clearing at %s for cache separation" + (1- last-put-in-sws-pos)) + (c-remove-in-sws (1- last-put-in-sws-pos) + last-put-in-sws-pos)) + ((> (point-min) 1) + ;; If at bob and the buffer is narrowed, we have to clear the + ;; character we're standing on instead since there might be a + ;; `c-in-sws' before (point-min). In this case it's necessary + ;; to clear both properties. + (c-debug-sws-msg + "c-backward-sws clearing thoroughly at %s for cache separation" + last-put-in-sws-pos) + (c-remove-is-and-in-sws last-put-in-sws-pos + (1+ last-put-in-sws-pos))))) + ))) + + +;; Other whitespace tools +(defun c-partial-ws-p (beg end) + ;; Is the region (beg end) WS, and is there WS (or BOB/EOB) next to the + ;; region? This is a "heuristic" function. ..... + ;; + ;; The motivation for the second bit is to check whether removing this + ;; region would coalesce two symbols. + ;; + ;; FIXME!!! This function doesn't check virtual semicolons in any way. Be + ;; careful about using this function for, e.g. AWK. (2007/3/7) + (save-excursion + (let ((end+1 (min (1+ end) (point-max)))) + (or (progn (goto-char (max (point-min) (1- beg))) + (c-skip-ws-forward end) + (eq (point) end)) + (progn (goto-char beg) + (c-skip-ws-forward end+1) + (eq (point) end+1)))))) + +;; A system for finding noteworthy parens before the point. + +(defconst c-state-cache-too-far 5000) +;; A maximum comfortable scanning distance, e.g. between +;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state). When +;; this distance is exceeded, we take "emergency meausures", e.g. by clearing +;; the cache and starting again from point-min or a beginning of defun. This +;; value can be tuned for efficiency or set to a lower value for testing. + +(defvar c-state-cache nil) +(make-variable-buffer-local 'c-state-cache) +;; The state cache used by `c-parse-state' to cut down the amount of +;; searching. It's the result from some earlier `c-parse-state' call. See +;; `c-parse-state''s doc string for details of its structure. +;; +;; The use of the cached info is more effective if the next +;; `c-parse-state' call is on a line close by the one the cached state +;; was made at; the cache can actually slow down a little if the +;; cached state was made very far back in the buffer. The cache is +;; most effective if `c-parse-state' is used on each line while moving +;; forward. + +(defvar c-state-cache-good-pos 1) +(make-variable-buffer-local 'c-state-cache-good-pos) +;; This is a position where `c-state-cache' is known to be correct, or +;; nil (see below). It's a position inside one of the recorded unclosed +;; parens or the top level, but not further nested inside any literal or +;; subparen that is closed before the last recorded position. +;; +;; The exact position is chosen to try to be close to yet earlier than +;; the position where `c-state-cache' will be called next. Right now +;; the heuristic is to set it to the position after the last found +;; closing paren (of any type) before the line on which +;; `c-parse-state' was called. That is chosen primarily to work well +;; with refontification of the current line. +;; +;; 2009-07-28: When `c-state-point-min' and the last position where +;; `c-parse-state' or for which `c-invalidate-state-cache' was called, are +;; both in the same literal, there is no such "good position", and +;; c-state-cache-good-pos is then nil. This is the ONLY circumstance in which +;; it can be nil. In this case, `c-state-point-min-literal' will be non-nil. +;; +;; 2009-06-12: In a brace desert, c-state-cache-good-pos may also be in +;; the middle of the desert, as long as it is not within a brace pair +;; recorded in `c-state-cache' or a paren/bracket pair. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; We maintain a simple cache of positions which aren't in a literal, so as to +;; speed up testing for non-literality. +(defconst c-state-nonlit-pos-interval 3000) +;; The approximate interval between entries in `c-state-nonlit-pos-cache'. + +(defvar c-state-nonlit-pos-cache nil) +(make-variable-buffer-local 'c-state-nonlit-pos-cache) +;; A list of buffer positions which are known not to be in a literal or a cpp +;; construct. This is ordered with higher positions at the front of the list. +;; Only those which are less than `c-state-nonlit-pos-cache-limit' are valid. + +(defvar c-state-nonlit-pos-cache-limit 1) +(make-variable-buffer-local 'c-state-nonlit-pos-cache-limit) +;; An upper limit on valid entries in `c-state-nonlit-pos-cache'. This is +;; reduced by buffer changes, and increased by invocations of +;; `c-state-literal-at'. + +(defvar c-state-semi-nonlit-pos-cache nil) +(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache) +;; A list of buffer positions which are known not to be in a literal. This is +;; ordered with higher positions at the front of the list. Only those which +;; are less than `c-state-semi-nonlit-pos-cache-limit' are valid. + +(defvar c-state-semi-nonlit-pos-cache-limit 1) +(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache-limit) +;; An upper limit on valid entries in `c-state-semi-nonlit-pos-cache'. This is +;; reduced by buffer changes, and increased by invocations of +;; `c-state-literal-at'. FIMXE!!! + +(defsubst c-state-pp-to-literal (from to) + ;; Do a parse-partial-sexp from FROM to TO, returning either + ;; (STATE TYPE (BEG . END)) if TO is in a literal; or + ;; (STATE) otherwise, + ;; where STATE is the parsing state at TO, TYPE is the type of the literal + ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal. + ;; + ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote), + ;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of + ;; STATE are valid. + (save-excursion + (let ((s (parse-partial-sexp from to)) + ty) + (when (or (nth 3 s) (nth 4 s)) ; in a string or comment + (setq ty (cond + ((nth 3 s) 'string) + ((eq (nth 7 s) t) 'c++) + (t 'c))) + (parse-partial-sexp (point) (point-max) + nil ; TARGETDEPTH + nil ; STOPBEFORE + s ; OLDSTATE + 'syntax-table)) ; stop at end of literal + (if ty + `(,s ,ty (,(nth 8 s) . ,(point))) + `(,s))))) + +(defun c-state-safe-place (here) + ;; Return a buffer position before HERE which is "safe", i.e. outside any + ;; string, comment, or macro. + ;; + ;; NOTE: This function manipulates `c-state-nonlit-pos-cache'. This cache + ;; MAY NOT contain any positions within macros, since macros are frequently + ;; turned into comments by use of the `c-cpp-delimiter' category properties. + ;; We cannot rely on this mechanism whilst determining a cache pos since + ;; this function is also called from outwith `c-parse-state'. + (save-restriction + (widen) + (save-excursion + (let ((c c-state-nonlit-pos-cache) + pos npos high-pos lit macro-beg macro-end) + ;; Trim the cache to take account of buffer changes. + (while (and c (> (car c) c-state-nonlit-pos-cache-limit)) + (setq c (cdr c))) + (setq c-state-nonlit-pos-cache c) + + (while (and c (> (car c) here)) + (setq high-pos (car c)) + (setq c (cdr c))) + (setq pos (or (car c) (point-min))) + + (unless high-pos + (while + ;; Add an element to `c-state-nonlit-pos-cache' each iteration. + (and + (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here) + + ;; Test for being in a literal. If so, go to after it. + (progn + (setq lit (car (cddr (c-state-pp-to-literal pos npos)))) + (or (null lit) + (prog1 (<= (cdr lit) here) + (setq npos (cdr lit))))) + + ;; Test for being in a macro. If so, go to after it. + (progn + (goto-char npos) + (setq macro-beg + (and (c-beginning-of-macro) (/= (point) npos) (point))) + (when macro-beg + (c-syntactic-end-of-macro) + (or (eobp) (forward-char)) + (setq macro-end (point))) + (or (null macro-beg) + (prog1 (<= macro-end here) + (setq npos macro-end))))) + + (setq pos npos) + (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache))) + ;; Add one extra element above HERE so as to to avoid the previous + ;; expensive calculation when the next call is close to the current + ;; one. This is especially useful when inside a large macro. + (setq c-state-nonlit-pos-cache (cons npos c-state-nonlit-pos-cache))) + + (if (> pos c-state-nonlit-pos-cache-limit) + (setq c-state-nonlit-pos-cache-limit pos)) + pos)))) + +(defun c-state-semi-safe-place (here) + ;; Return a buffer position before HERE which is "safe", i.e. outside any + ;; string or comment. It may be in a macro. + (save-restriction + (widen) + (save-excursion + (let ((c c-state-semi-nonlit-pos-cache) + pos npos high-pos lit macro-beg macro-end) + ;; Trim the cache to take account of buffer changes. + (while (and c (> (car c) c-state-semi-nonlit-pos-cache-limit)) + (setq c (cdr c))) + (setq c-state-semi-nonlit-pos-cache c) + + (while (and c (> (car c) here)) + (setq high-pos (car c)) + (setq c (cdr c))) + (setq pos (or (car c) (point-min))) + + (unless high-pos + (while + ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration. + (and + (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here) + + ;; Test for being in a literal. If so, go to after it. + (progn + (setq lit (car (cddr (c-state-pp-to-literal pos npos)))) + (or (null lit) + (prog1 (<= (cdr lit) here) + (setq npos (cdr lit)))))) + + (setq pos npos) + (setq c-state-semi-nonlit-pos-cache + (cons pos c-state-semi-nonlit-pos-cache)))) + + (if (> pos c-state-semi-nonlit-pos-cache-limit) + (setq c-state-semi-nonlit-pos-cache-limit pos)) + pos)))) + +(defun c-state-literal-at (here) + ;; If position HERE is inside a literal, return (START . END), the + ;; boundaries of the literal (which may be outside the accessible bit of the + ;; buffer). Otherwise, return nil. + ;; + ;; This function is almost the same as `c-literal-limits'. Previously, it + ;; differed in that it was a lower level function, and that it rigourously + ;; followed the syntax from BOB. `c-literal-limits' is now (2011-12) + ;; virtually identical to this function. + (save-restriction + (widen) + (save-excursion + (let ((pos (c-state-safe-place here))) + (car (cddr (c-state-pp-to-literal pos here))))))) + +(defsubst c-state-lit-beg (pos) + ;; Return the start of the literal containing POS, or POS itself. + (or (car (c-state-literal-at pos)) + pos)) + +(defsubst c-state-cache-non-literal-place (pos state) + ;; Return a position outside of a string/comment/macro at or before POS. + ;; STATE is the parse-partial-sexp state at POS. + (let ((res (if (or (nth 3 state) ; in a string? + (nth 4 state)) ; in a comment? + (nth 8 state) + pos))) + (save-excursion + (goto-char res) + (if (c-beginning-of-macro) + (point) + res)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Stuff to do with point-min, and coping with any literal there. +(defvar c-state-point-min 1) +(make-variable-buffer-local 'c-state-point-min) +;; This is (point-min) when `c-state-cache' was last calculated. A change of +;; narrowing is likely to affect the parens that are visible before the point. + +(defvar c-state-point-min-lit-type nil) +(make-variable-buffer-local 'c-state-point-min-lit-type) +(defvar c-state-point-min-lit-start nil) +(make-variable-buffer-local 'c-state-point-min-lit-start) +;; These two variables define the literal, if any, containing point-min. +;; Their values are, respectively, 'string, c, or c++, and the start of the +;; literal. If there's no literal there, they're both nil. + +(defvar c-state-min-scan-pos 1) +(make-variable-buffer-local 'c-state-min-scan-pos) +;; This is the earliest buffer-pos from which scanning can be done. It is +;; either the end of the literal containing point-min, or point-min itself. +;; It becomes nil if the buffer is changed earlier than this point. +(defun c-state-get-min-scan-pos () + ;; Return the lowest valid scanning pos. This will be the end of the + ;; literal enclosing point-min, or point-min itself. + (or c-state-min-scan-pos + (save-restriction + (save-excursion + (widen) + (goto-char c-state-point-min-lit-start) + (if (eq c-state-point-min-lit-type 'string) + (forward-sexp) + (forward-comment 1)) + (setq c-state-min-scan-pos (point)))))) + +(defun c-state-mark-point-min-literal () + ;; Determine the properties of any literal containing POINT-MIN, setting the + ;; variables `c-state-point-min-lit-type', `c-state-point-min-lit-start', + ;; and `c-state-min-scan-pos' accordingly. The return value is meaningless. + (let ((p-min (point-min)) + lit) + (save-restriction + (widen) + (setq lit (c-state-literal-at p-min)) + (if lit + (setq c-state-point-min-lit-type + (save-excursion + (goto-char (car lit)) + (cond + ((looking-at c-block-comment-start-regexp) 'c) + ((looking-at c-line-comment-starter) 'c++) + (t 'string))) + c-state-point-min-lit-start (car lit) + c-state-min-scan-pos (cdr lit)) + (setq c-state-point-min-lit-type nil + c-state-point-min-lit-start nil + c-state-min-scan-pos p-min))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; A variable which signals a brace dessert - helpful for reducing the number +;; of fruitless backward scans. +(defvar c-state-brace-pair-desert nil) +(make-variable-buffer-local 'c-state-brace-pair-desert) +;; Used only in `c-append-lower-brace-pair-to-state-cache'. It is set when +;; that defun has searched backwards for a brace pair and not found one. Its +;; value is either nil or a cons (PA . FROM), where PA is the position of the +;; enclosing opening paren/brace/bracket which bounds the backwards search (or +;; nil when at top level) and FROM is where the backward search started. It +;; is reset to nil in `c-invalidate-state-cache'. + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Lowish level functions/macros which work directly on `c-state-cache', or a +;; list of like structure. +(defmacro c-state-cache-top-lparen (&optional cache) + ;; Return the address of the top left brace/bracket/paren recorded in CACHE + ;; (default `c-state-cache') (or nil). + (let ((cash (or cache 'c-state-cache))) + `(if (consp (car ,cash)) + (caar ,cash) + (car ,cash)))) + +(defmacro c-state-cache-top-paren (&optional cache) + ;; Return the address of the latest brace/bracket/paren (whether left or + ;; right) recorded in CACHE (default `c-state-cache') or nil. + (let ((cash (or cache 'c-state-cache))) + `(if (consp (car ,cash)) + (cdar ,cash) + (car ,cash)))) + +(defmacro c-state-cache-after-top-paren (&optional cache) + ;; Return the position just after the latest brace/bracket/paren (whether + ;; left or right) recorded in CACHE (default `c-state-cache') or nil. + (let ((cash (or cache 'c-state-cache))) + `(if (consp (car ,cash)) + (cdar ,cash) + (and (car ,cash) + (1+ (car ,cash)))))) + +(defun c-get-cache-scan-pos (here) + ;; From the state-cache, determine the buffer position from which we might + ;; scan forward to HERE to update this cache. This position will be just + ;; after a paren/brace/bracket recorded in the cache, if possible, otherwise + ;; return the earliest position in the accessible region which isn't within + ;; a literal. If the visible portion of the buffer is entirely within a + ;; literal, return NIL. + (let ((c c-state-cache) elt) + ;(while (>= (or (c-state-cache-top-lparen c) 1) here) + (while (and c + (>= (c-state-cache-top-lparen c) here)) + (setq c (cdr c))) + + (setq elt (car c)) + (cond + ((consp elt) + (if (> (cdr elt) here) + (1+ (car elt)) + (cdr elt))) + (elt (1+ elt)) + ((<= (c-state-get-min-scan-pos) here) + (c-state-get-min-scan-pos)) + (t nil)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Variables which keep track of preprocessor constructs. +(defvar c-state-old-cpp-beg nil) +(make-variable-buffer-local 'c-state-old-cpp-beg) +(defvar c-state-old-cpp-end nil) +(make-variable-buffer-local 'c-state-old-cpp-end) +;; These are the limits of the macro containing point at the previous call of +;; `c-parse-state', or nil. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Defuns which analyse the buffer, yet don't change `c-state-cache'. +(defun c-get-fallback-scan-pos (here) + ;; Return a start position for building `c-state-cache' from + ;; scratch. This will be at the top level, 2 defuns back. + (save-excursion + ;; Go back 2 bods, but ignore any bogus positions returned by + ;; beginning-of-defun (i.e. open paren in column zero). + (goto-char here) + (let ((cnt 2)) + (while (not (or (bobp) (zerop cnt))) + (c-beginning-of-defun-1) ; Pure elisp BOD. + (if (eq (char-after) ?\{) + (setq cnt (1- cnt))))) + (point))) + +(defun c-state-balance-parens-backwards (here- here+ top) + ;; Return the position of the opening paren/brace/bracket before HERE- which + ;; matches the outermost close p/b/b between HERE+ and TOP. Except when + ;; there's a macro, HERE- and HERE+ are the same. Like this: + ;; + ;; ............................................ + ;; | | + ;; ( [ ( .........#macro.. ) ( ) ] ) + ;; ^ ^ ^ ^ + ;; | | | | + ;; return HERE- HERE+ TOP + ;; + ;; If there aren't enough opening paren/brace/brackets, return the position + ;; of the outermost one found, or HERE- if there are none. If there are no + ;; closeing p/b/bs between HERE+ and TOP, return HERE-. HERE-/+ and TOP + ;; must not be inside literals. Only the accessible portion of the buffer + ;; will be scanned. + + ;; PART 1: scan from `here+' up to `top', accumulating ")"s which enclose + ;; `here'. Go round the next loop each time we pass over such a ")". These + ;; probably match "("s before `here-'. + (let (pos pa ren+1 lonely-rens) + (save-excursion + (save-restriction + (narrow-to-region (point-min) top) ; This can move point, sometimes. + (setq pos here+) + (c-safe + (while + (setq ren+1 (c-sc-scan-lists pos 1 1)) ; might signal + (setq lonely-rens (cons ren+1 lonely-rens) + pos ren+1))))) + + ;; PART 2: Scan back before `here-' searching for the "("s + ;; matching/mismatching the ")"s found above. We only need to direct the + ;; caller to scan when we've encountered unmatched right parens. + (setq pos here-) + (when lonely-rens + (c-safe + (while + (and lonely-rens ; actual values aren't used. + (setq pa (c-sc-scan-lists pos -1 1))) + (setq pos pa) + (setq lonely-rens (cdr lonely-rens))))) + pos)) + +(defun c-parse-state-get-strategy (here good-pos) + ;; Determine the scanning strategy for adjusting `c-parse-state', attempting + ;; to minimise the amount of scanning. HERE is the pertinent position in + ;; the buffer, GOOD-POS is a position where `c-state-cache' (possibly with + ;; its head trimmed) is known to be good, or nil if there is no such + ;; position. + ;; + ;; The return value is a list, one of the following: + ;; + ;; o - ('forward CACHE-POS START-POINT) - scan forward from START-POINT, + ;; which is not less than CACHE-POS. + ;; o - ('backward CACHE-POS nil) - scan backwards (from HERE). + ;; o - ('BOD nil START-POINT) - scan forwards from START-POINT, which is at the + ;; top level. + ;; o - ('IN-LIT nil nil) - point is inside the literal containing point-min. + ;; , where CACHE-POS is the highest position recorded in `c-state-cache' at + ;; or below HERE. + (let ((cache-pos (c-get-cache-scan-pos here)) ; highest position below HERE in cache (or 1) + BOD-pos ; position of 2nd BOD before HERE. + strategy ; 'forward, 'backward, 'BOD, or 'IN-LIT. + start-point + how-far) ; putative scanning distance. + (setq good-pos (or good-pos (c-state-get-min-scan-pos))) + (cond + ((< here (c-state-get-min-scan-pos)) + (setq strategy 'IN-LIT + start-point nil + cache-pos nil + how-far 0)) + ((<= good-pos here) + (setq strategy 'forward + start-point (max good-pos cache-pos) + how-far (- here start-point))) + ((< (- good-pos here) (- here cache-pos)) ; FIXME!!! ; apply some sort of weighting. + (setq strategy 'backward + how-far (- good-pos here))) + (t + (setq strategy 'forward + how-far (- here cache-pos) + start-point cache-pos))) + + ;; Might we be better off starting from the top level, two defuns back, + ;; instead? + (when (> how-far c-state-cache-too-far) + (setq BOD-pos (c-get-fallback-scan-pos here)) ; somewhat EXPENSIVE!!! + (if (< (- here BOD-pos) how-far) + (setq strategy 'BOD + start-point BOD-pos))) + + (list + strategy + (and (memq strategy '(forward backward)) cache-pos) + (and (memq strategy '(forward BOD)) start-point)))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Routines which change `c-state-cache' and associated values. +(defun c-renarrow-state-cache () + ;; The region (more precisely, point-min) has changed since we + ;; calculated `c-state-cache'. Amend `c-state-cache' accordingly. + (if (< (point-min) c-state-point-min) + ;; If point-min has MOVED BACKWARDS then we drop the state completely. + ;; It would be possible to do a better job here and recalculate the top + ;; only. + (progn + (c-state-mark-point-min-literal) + (setq c-state-cache nil + c-state-cache-good-pos c-state-min-scan-pos + c-state-brace-pair-desert nil)) + + ;; point-min has MOVED FORWARD. + + ;; Is the new point-min inside a (different) literal? + (unless (and c-state-point-min-lit-start ; at prev. point-min + (< (point-min) (c-state-get-min-scan-pos))) + (c-state-mark-point-min-literal)) + + ;; Cut off a bit of the tail from `c-state-cache'. + (let ((ptr (cons nil c-state-cache)) + pa) + (while (and (setq pa (c-state-cache-top-lparen (cdr ptr))) + (>= pa (point-min))) + (setq ptr (cdr ptr))) + + (when (consp ptr) + (if (eq (cdr ptr) c-state-cache) + (setq c-state-cache nil + c-state-cache-good-pos c-state-min-scan-pos) + (setcdr ptr nil) + (setq c-state-cache-good-pos (1+ (c-state-cache-top-lparen)))) + ))) + + (setq c-state-point-min (point-min))) + +(defun c-append-lower-brace-pair-to-state-cache (from &optional upper-lim) + ;; If there is a brace pair preceding FROM in the buffer, at the same level + ;; of nesting (not necessarily immediately preceding), push a cons onto + ;; `c-state-cache' to represent it. FROM must not be inside a literal. If + ;; UPPER-LIM is non-nil, we append the highest brace pair whose "}" is below + ;; UPPER-LIM. + ;; + ;; Return non-nil when this has been done. + ;; + ;; The situation it copes with is this transformation: + ;; + ;; OLD: { (.) {...........} + ;; ^ ^ + ;; FROM HERE + ;; + ;; NEW: { {....} (.) {......... + ;; ^ ^ ^ + ;; LOWER BRACE PAIR HERE or HERE + ;; + ;; This routine should be fast. Since it can get called a LOT, we maintain + ;; `c-state-brace-pair-desert', a small cache of "failures", such that we + ;; reduce the time wasted in repeated fruitless searches in brace deserts. + (save-excursion + (save-restriction + (let ((bra from) ce ; Positions of "{" and "}". + new-cons + (cache-pos (c-state-cache-top-lparen)) ; might be nil. + (macro-start-or-from + (progn (goto-char from) + (c-beginning-of-macro) + (point)))) + (or upper-lim (setq upper-lim from)) + + ;; If we're essentially repeating a fruitless search, just give up. + (unless (and c-state-brace-pair-desert + (eq cache-pos (car c-state-brace-pair-desert)) + (<= from (cdr c-state-brace-pair-desert))) + ;; DESERT-LIM. Only search what we absolutely need to, + (let ((desert-lim + (and c-state-brace-pair-desert + (eq cache-pos (car c-state-brace-pair-desert)) + (cdr c-state-brace-pair-desert))) + ;; CACHE-LIM. This limit will be necessary when an opening + ;; paren at `cache-pos' has just had its matching close paren + ;; inserted. `cache-pos' continues to be a search bound, even + ;; though the algorithm below would skip over the new paren + ;; pair. + (cache-lim (and cache-pos (< cache-pos from) cache-pos))) + (narrow-to-region + (cond + ((and desert-lim cache-lim) + (max desert-lim cache-lim)) + (desert-lim) + (cache-lim) + ((point-min))) + (point-max))) + + ;; In the next pair of nested loops, the inner one moves back past a + ;; pair of (mis-)matching parens or brackets; the outer one moves + ;; back over a sequence of unmatched close brace/paren/bracket each + ;; time round. + (while + (progn + (c-safe + (while + (and (setq ce (c-sc-scan-lists bra -1 -1)) ; back past )/]/}; might signal + (setq bra (c-sc-scan-lists ce -1 1)) ; back past (/[/{; might signal + (or (> ce upper-lim) + (not (eq (char-after bra) ?\{)) + (and (goto-char bra) + (c-beginning-of-macro) + (< (point) macro-start-or-from)))))) + (and ce (< ce bra))) + (setq bra ce)) ; If we just backed over an unbalanced closing + ; brace, ignore it. + + (if (and ce (< bra ce) (eq (char-after bra) ?\{)) + ;; We've found the desired brace-pair. + (progn + (setq new-cons (cons bra (1+ ce))) + (cond + ((consp (car c-state-cache)) + (setcar c-state-cache new-cons)) + ((and (numberp (car c-state-cache)) ; probably never happens + (< ce (car c-state-cache))) + (setcdr c-state-cache + (cons new-cons (cdr c-state-cache)))) + (t (setq c-state-cache (cons new-cons c-state-cache))))) + + ;; We haven't found a brace pair. Record this in the cache. + (setq c-state-brace-pair-desert (cons cache-pos from)))))))) + +(defsubst c-state-push-any-brace-pair (bra+1 macro-start-or-here) + ;; If BRA+1 is nil, do nothing. Otherwise, BRA+1 is the buffer position + ;; following a {, and that brace has a (mis-)matching } (or ]), and we + ;; "push" "a" brace pair onto `c-state-cache'. + ;; + ;; Here "push" means overwrite the top element if it's itself a brace-pair, + ;; otherwise push it normally. + ;; + ;; The brace pair we push is normally the one surrounding BRA+1, but if the + ;; latter is inside a macro, not being a macro containing + ;; MACRO-START-OR-HERE, we scan backwards through the buffer for a non-macro + ;; base pair. This latter case is assumed to be rare. + ;; + ;; Note: POINT is not preserved in this routine. + (if bra+1 + (if (or (> bra+1 macro-start-or-here) + (progn (goto-char bra+1) + (not (c-beginning-of-macro)))) + (setq c-state-cache + (cons (cons (1- bra+1) + (c-sc-scan-lists bra+1 1 1)) + (if (consp (car c-state-cache)) + (cdr c-state-cache) + c-state-cache))) + ;; N.B. This defsubst codes one method for the simple, normal case, + ;; and a more sophisticated, slower way for the general case. Don't + ;; eliminate this defsubst - it's a speed optimisation. + (c-append-lower-brace-pair-to-state-cache (1- bra+1))))) + +(defun c-append-to-state-cache (from) + ;; Scan the buffer from FROM to (point-max), adding elements into + ;; `c-state-cache' for braces etc. Return a candidate for + ;; `c-state-cache-good-pos'. + ;; + ;; FROM must be after the latest brace/paren/bracket in `c-state-cache', if + ;; any. Typically, it is immediately after it. It must not be inside a + ;; literal. + (let ((here-bol (c-point 'bol (point-max))) + (macro-start-or-here + (save-excursion (goto-char (point-max)) + (if (c-beginning-of-macro) + (point) + (point-max)))) + pa+1 ; pos just after an opening PAren (or brace). + (ren+1 from) ; usually a pos just after an closing paREN etc. + ; Is actually the pos. to scan for a (/{/[ from, + ; which sometimes is after a silly )/}/]. + paren+1 ; Pos after some opening or closing paren. + paren+1s ; A list of `paren+1's; used to determine a + ; good-pos. + bra+1 ; just after L bra-ce. + bra+1s ; list of OLD values of bra+1. + mstart) ; start of a macro. + + (save-excursion + ;; Each time round the following loop, we enter a succesively deeper + ;; level of brace/paren nesting. (Except sometimes we "continue at + ;; the existing level".) `pa+1' is a pos inside an opening + ;; brace/paren/bracket, usually just after it. + (while + (progn + ;; Each time round the next loop moves forward over an opening then + ;; a closing brace/bracket/paren. This loop is white hot, so it + ;; plays ugly tricks to go fast. DON'T PUT ANYTHING INTO THIS + ;; LOOP WHICH ISN'T ABSOLUTELY NECESSARY!!! It terminates when a + ;; call of `scan-lists' signals an error, which happens when there + ;; are no more b/b/p's to scan. + (c-safe + (while t + (setq pa+1 (c-sc-scan-lists ren+1 1 -1) ; Into (/{/[; might signal + paren+1s (cons pa+1 paren+1s)) + (setq ren+1 (c-sc-scan-lists pa+1 1 1)) ; Out of )/}/]; might signal + (if (and (eq (char-before pa+1) ?{)) ; Check for a macro later. + (setq bra+1 pa+1)) + (setcar paren+1s ren+1))) + + (if (and pa+1 (> pa+1 ren+1)) + ;; We've just entered a deeper nesting level. + (progn + ;; Insert the brace pair (if present) and the single open + ;; paren/brace/bracket into `c-state-cache' It cannot be + ;; inside a macro, except one around point, because of what + ;; `c-neutralize-syntax-in-CPP' has done. + (c-state-push-any-brace-pair bra+1 macro-start-or-here) + ;; Insert the opening brace/bracket/paren position. + (setq c-state-cache (cons (1- pa+1) c-state-cache)) + ;; Clear admin stuff for the next more nested part of the scan. + (setq ren+1 pa+1 pa+1 nil bra+1 nil bra+1s nil) + t) ; Carry on the loop + + ;; All open p/b/b's at this nesting level, if any, have probably + ;; been closed by matching/mismatching ones. We're probably + ;; finished - we just need to check for having found an + ;; unmatched )/}/], which we ignore. Such a )/}/] can't be in a + ;; macro, due the action of `c-neutralize-syntax-in-CPP'. + (c-safe (setq ren+1 (c-sc-scan-lists ren+1 1 1)))))) ; acts as loop control. + + ;; Record the final, innermost, brace-pair if there is one. + (c-state-push-any-brace-pair bra+1 macro-start-or-here) + + ;; Determine a good pos + (while (and (setq paren+1 (car paren+1s)) + (> (if (> paren+1 macro-start-or-here) + paren+1 + (goto-char paren+1) + (setq mstart (and (c-beginning-of-macro) + (point))) + (or mstart paren+1)) + here-bol)) + (setq paren+1s (cdr paren+1s))) + (cond + ((and paren+1 mstart) + (min paren+1 mstart)) + (paren+1) + (t from))))) + +(defun c-remove-stale-state-cache (good-pos pps-point) + ;; Remove stale entries from the `c-cache-state', i.e. those which will + ;; not be in it when it is amended for position (point-max). + ;; Additionally, the "outermost" open-brace entry before (point-max) + ;; will be converted to a cons if the matching close-brace is scanned. + ;; + ;; GOOD-POS is a "maximal" "safe position" - there must be no open + ;; parens/braces/brackets between GOOD-POS and (point-max). + ;; + ;; As a second thing, calculate the result of parse-partial-sexp at + ;; PPS-POINT, w.r.t. GOOD-POS. The motivation here is that + ;; `c-state-cache-good-pos' may become PPS-POINT, but the caller may need to + ;; adjust it to get outside a string/comment. (Sorry about this! The code + ;; needs to be FAST). + ;; + ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where + ;; o - GOOD-POS is a position where the new value `c-state-cache' is known + ;; to be good (we aim for this to be as high as possible); + ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair + ;; preceding POS which needs to be recorded in `c-state-cache'. It is a + ;; position to scan backwards from. + ;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT. + (save-restriction + (narrow-to-region 1 (point-max)) + (save-excursion + (let* ((in-macro-start ; start of macro containing (point-max) or nil. + (save-excursion + (goto-char (point-max)) + (and (c-beginning-of-macro) + (point)))) + (good-pos-actual-macro-start ; Start of macro containing good-pos + ; or nil + (and (< good-pos (point-max)) + (save-excursion + (goto-char good-pos) + (and (c-beginning-of-macro) + (point))))) + (good-pos-actual-macro-end ; End of this macro, (maybe + ; (point-max)), or nil. + (and good-pos-actual-macro-start + (save-excursion + (goto-char good-pos-actual-macro-start) + (c-end-of-macro) + (point)))) + pps-state ; Will be 9 or 10 elements long. + pos + upper-lim ; ,beyond which `c-state-cache' entries are removed + scan-back-pos + pair-beg pps-point-state target-depth) + + ;; Remove entries beyond (point-max). Also remove any entries inside + ;; a macro, unless (point-max) is in the same macro. + (setq upper-lim + (if (or (null c-state-old-cpp-beg) + (and (> (point-max) c-state-old-cpp-beg) + (< (point-max) c-state-old-cpp-end))) + (point-max) + (min (point-max) c-state-old-cpp-beg))) + (while (and c-state-cache (>= (c-state-cache-top-lparen) upper-lim)) + (setq c-state-cache (cdr c-state-cache))) + ;; If `upper-lim' is inside the last recorded brace pair, remove its + ;; RBrace and indicate we'll need to search backwards for a previous + ;; brace pair. + (when (and c-state-cache + (consp (car c-state-cache)) + (> (cdar c-state-cache) upper-lim)) + (setcar c-state-cache (caar c-state-cache)) + (setq scan-back-pos (car c-state-cache))) + + ;; The next loop jumps forward out of a nested level of parens each + ;; time round; the corresponding elements in `c-state-cache' are + ;; removed. `pos' is just after the brace-pair or the open paren at + ;; (car c-state-cache). There can be no open parens/braces/brackets + ;; between `good-pos'/`good-pos-actual-macro-start' and (point-max), + ;; due to the interface spec to this function. + (setq pos (if (and good-pos-actual-macro-end + (not (eq good-pos-actual-macro-start + in-macro-start))) + (1+ good-pos-actual-macro-end) ; get outside the macro as + ; marked by a `category' text property. + good-pos)) + (goto-char pos) + (while (and c-state-cache + (< (point) (point-max))) + (cond + ((null pps-state) ; first time through + (setq target-depth -1)) + ((eq (car pps-state) target-depth) ; found closing ),},] + (setq target-depth (1- (car pps-state)))) + ;; Do nothing when we've merely reached pps-point. + ) + + ;; Scan! + (setq pps-state + (c-sc-parse-partial-sexp + (point) (if (< (point) pps-point) pps-point (point-max)) + target-depth + nil pps-state)) + + (if (= (point) pps-point) + (setq pps-point-state pps-state)) + + (when (eq (car pps-state) target-depth) + (setq pos (point)) ; POS is now just after an R-paren/brace. + (cond + ((and (consp (car c-state-cache)) + (eq (point) (cdar c-state-cache))) + ;; We've just moved out of the paren pair containing the brace-pair + ;; at (car c-state-cache). `pair-beg' is where the open paren is, + ;; and is potentially where the open brace of a cons in + ;; c-state-cache will be. + (setq pair-beg (car-safe (cdr c-state-cache)) + c-state-cache (cdr-safe (cdr c-state-cache)))) ; remove {}pair + containing Lparen. + ((numberp (car c-state-cache)) + (setq pair-beg (car c-state-cache) + c-state-cache (cdr c-state-cache))) ; remove this + ; containing Lparen + ((numberp (cadr c-state-cache)) + (setq pair-beg (cadr c-state-cache) + c-state-cache (cddr c-state-cache))) ; Remove a paren pair + ; together with enclosed brace pair. + ;; (t nil) ; Ignore an unmated Rparen. + ))) + + (if (< (point) pps-point) + (setq pps-state (c-sc-parse-partial-sexp + (point) pps-point + nil nil ; TARGETDEPTH, STOPBEFORE + pps-state))) + + ;; If the last paren pair we moved out of was actually a brace pair, + ;; insert it into `c-state-cache'. + (when (and pair-beg (eq (char-after pair-beg) ?{)) + (if (consp (car-safe c-state-cache)) + (setq c-state-cache (cdr c-state-cache))) + (setq c-state-cache (cons (cons pair-beg pos) + c-state-cache))) + + (list pos scan-back-pos pps-state))))) + +(defun c-remove-stale-state-cache-backwards (here cache-pos) + ;; Strip stale elements of `c-state-cache' by moving backwards through the + ;; buffer, and inform the caller of the scenario detected. + ;; + ;; HERE is the position we're setting `c-state-cache' for. + ;; CACHE-POS is just after the latest recorded position in `c-state-cache' + ;; before HERE, or a position at or near point-min which isn't in a + ;; literal. + ;; + ;; This function must only be called only when (> `c-state-cache-good-pos' + ;; HERE). Usually the gap between CACHE-POS and HERE is large. It is thus + ;; optimised to eliminate (or minimise) scanning between these two + ;; positions. + ;; + ;; Return a three element list (GOOD-POS SCAN-BACK-POS FWD-FLAG), where: + ;; o - GOOD-POS is a "good position", where `c-state-cache' is valid, or + ;; could become so after missing elements are inserted into + ;; `c-state-cache'. This is JUST AFTER an opening or closing + ;; brace/paren/bracket which is already in `c-state-cache' or just before + ;; one otherwise. exceptionally (when there's no such b/p/b handy) the BOL + ;; before `here''s line, or the start of the literal containing it. + ;; o - SCAN-BACK-POS, if non-nil, indicates there may be a brace pair + ;; preceding POS which isn't recorded in `c-state-cache'. It is a position + ;; to scan backwards from. + ;; o - FWD-FLAG, if non-nil, indicates there may be parens/braces between + ;; POS and HERE which aren't recorded in `c-state-cache'. + ;; + ;; The comments in this defun use "paren" to mean parenthesis or square + ;; bracket (as contrasted with a brace), and "(" and ")" likewise. + ;; + ;; . {..} (..) (..) ( .. { } ) (...) ( .... . ..) + ;; | | | | | | + ;; CP E here D C good + (let ((pos c-state-cache-good-pos) + pa ren ; positions of "(" and ")" + dropped-cons ; whether the last element dropped from `c-state-cache' + ; was a cons (representing a brace-pair) + good-pos ; see above. + lit ; (START . END) of a literal containing some point. + here-lit-start here-lit-end ; bounds of literal containing `here' + ; or `here' itself. + here- here+ ; start/end of macro around HERE, or HERE + (here-bol (c-point 'bol here)) + (too-far-back (max (- here c-state-cache-too-far) 1))) + + ;; Remove completely irrelevant entries from `c-state-cache'. + (while (and c-state-cache + (>= (setq pa (c-state-cache-top-lparen)) here)) + (setq dropped-cons (consp (car c-state-cache))) + (setq c-state-cache (cdr c-state-cache)) + (setq pos pa)) + ;; At this stage, (> pos here); + ;; (< (c-state-cache-top-lparen) here) (or is nil). + + (cond + ((and (consp (car c-state-cache)) + (> (cdar c-state-cache) here)) + ;; CASE 1: The top of the cache is a brace pair which now encloses + ;; `here'. As good-pos, return the address. of the "{". Since we've no + ;; knowledge of what's inside these braces, we have no alternative but + ;; to direct the caller to scan the buffer from the opening brace. + (setq pos (caar c-state-cache)) + (setcar c-state-cache pos) + (list (1+ pos) pos t)) ; return value. We've just converted a brace pair + ; entry into a { entry, so the caller needs to + ; search for a brace pair before the {. + + ;; `here' might be inside a literal. Check for this. + ((progn + (setq lit (c-state-literal-at here) + here-lit-start (or (car lit) here) + here-lit-end (or (cdr lit) here)) + ;; Has `here' just "newly entered" a macro? + (save-excursion + (goto-char here-lit-start) + (if (and (c-beginning-of-macro) + (or (null c-state-old-cpp-beg) + (not (= (point) c-state-old-cpp-beg)))) + (progn + (setq here- (point)) + (c-end-of-macro) + (setq here+ (point))) + (setq here- here-lit-start + here+ here-lit-end))) + + ;; `here' might be nested inside any depth of parens (or brackets but + ;; not braces). Scan backwards to find the outermost such opening + ;; paren, if there is one. This will be the scan position to return. + (save-restriction + (narrow-to-region cache-pos (point-max)) + (setq pos (c-state-balance-parens-backwards here- here+ pos))) + nil)) ; for the cond + + ((< pos here-lit-start) + ;; CASE 2: Address of outermost ( or [ which now encloses `here', but + ;; didn't enclose the (previous) `c-state-cache-good-pos'. If there is + ;; a brace pair preceding this, it will already be in `c-state-cache', + ;; unless there was a brace pair after it, i.e. there'll only be one to + ;; scan for if we've just deleted one. + (list pos (and dropped-cons pos) t)) ; Return value. + + ;; `here' isn't enclosed in a (previously unrecorded) bracket/paren. + ;; Further forward scanning isn't needed, but we still need to find a + ;; GOOD-POS. Step out of all enclosing "("s on HERE's line. + ((progn + (save-restriction + (narrow-to-region here-bol (point-max)) + (setq pos here-lit-start) + (c-safe (while (setq pa (c-sc-scan-lists pos -1 1)) + (setq pos pa)))) ; might signal + nil)) ; for the cond + + ((save-restriction + (narrow-to-region too-far-back (point-max)) + (setq ren (c-safe (c-sc-scan-lists pos -1 -1)))) + + ;; CASE 3: After a }/)/] before `here''s BOL. + (list (1+ ren) (and dropped-cons pos) nil)) ; Return value + + (t + ;; CASE 4; Best of a bad job: BOL before `here-bol', or beginning of + ;; literal containing it. + (setq good-pos (c-state-lit-beg (c-point 'bopl here-bol))) + (list good-pos (and dropped-cons good-pos) nil))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Externally visible routines. + +(defun c-state-cache-init () + (setq c-state-cache nil + c-state-cache-good-pos 1 + c-state-nonlit-pos-cache nil + c-state-nonlit-pos-cache-limit 1 + c-state-brace-pair-desert nil + c-state-point-min 1 + c-state-point-min-lit-type nil + c-state-point-min-lit-start nil + c-state-min-scan-pos 1 + c-state-old-cpp-beg nil + c-state-old-cpp-end nil) + (c-state-mark-point-min-literal)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Debugging routines to dump `c-state-cache' in a "replayable" form. +;; (defmacro c-sc-de (elt) ; "c-state-cache-dump-element" +;; `(format ,(concat "(setq " (symbol-name elt) " %s) ") ,elt)) +;; (defmacro c-sc-qde (elt) ; "c-state-cache-quote-dump-element" +;; `(format ,(concat "(setq " (symbol-name elt) " '%s) ") ,elt)) +;; (defun c-state-dump () +;; ;; For debugging. +;; ;(message +;; (concat +;; (c-sc-qde c-state-cache) +;; (c-sc-de c-state-cache-good-pos) +;; (c-sc-qde c-state-nonlit-pos-cache) +;; (c-sc-de c-state-nonlit-pos-cache-limit) +;; (c-sc-qde c-state-brace-pair-desert) +;; (c-sc-de c-state-point-min) +;; (c-sc-de c-state-point-min-lit-type) +;; (c-sc-de c-state-point-min-lit-start) +;; (c-sc-de c-state-min-scan-pos) +;; (c-sc-de c-state-old-cpp-beg) +;; (c-sc-de c-state-old-cpp-end))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun c-invalidate-state-cache-1 (here) + ;; Invalidate all info on `c-state-cache' that applies to the buffer at HERE + ;; or higher and set `c-state-cache-good-pos' accordingly. The cache is + ;; left in a consistent state. + ;; + ;; This is much like `c-whack-state-after', but it never changes a paren + ;; pair element into an open paren element. Doing that would mean that the + ;; new open paren wouldn't have the required preceding paren pair element. + ;; + ;; This function is called from c-after-change. + + ;; The caches of non-literals: + (if (< here c-state-nonlit-pos-cache-limit) + (setq c-state-nonlit-pos-cache-limit here)) + (if (< here c-state-semi-nonlit-pos-cache-limit) + (setq c-state-semi-nonlit-pos-cache-limit here)) + + ;; `c-state-cache': + ;; Case 1: if `here' is in a literal containing point-min, everything + ;; becomes (or is already) nil. + (if (or (null c-state-cache-good-pos) + (< here (c-state-get-min-scan-pos))) + (setq c-state-cache nil + c-state-cache-good-pos nil + c-state-min-scan-pos nil) + +;;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value below +;;; `here'. To maintain its consistency, we may need to insert a new brace +;;; pair. + (let ((here-bol (c-point 'bol here)) + too-high-pa ; recorded {/(/[ next above here, or nil. + dropped-cons ; was the last removed element a brace pair? + pa) + ;; The easy bit - knock over-the-top bits off `c-state-cache'. + (while (and c-state-cache + (>= (setq pa (c-state-cache-top-paren)) here)) + (setq dropped-cons (consp (car c-state-cache)) + too-high-pa (c-state-cache-top-lparen) + c-state-cache (cdr c-state-cache))) + + ;; Do we need to add in an earlier brace pair, having lopped one off? + (if (and dropped-cons + (< too-high-pa (+ here c-state-cache-too-far))) + (c-append-lower-brace-pair-to-state-cache too-high-pa here-bol)) + (setq c-state-cache-good-pos (or (c-state-cache-after-top-paren) + (c-state-get-min-scan-pos))))) + + ;; The brace-pair desert marker: + (when (car c-state-brace-pair-desert) + (if (< here (car c-state-brace-pair-desert)) + (setq c-state-brace-pair-desert nil) + (if (< here (cdr c-state-brace-pair-desert)) + (setcdr c-state-brace-pair-desert here))))) + +(defun c-parse-state-1 () + ;; Find and record all noteworthy parens between some good point earlier in + ;; the file and point. That good point is at least the beginning of the + ;; top-level construct we are in, or the beginning of the preceding + ;; top-level construct if we aren't in one. + ;; + ;; The returned value is a list of the noteworthy parens with the last one + ;; first. If an element in the list is an integer, it's the position of an + ;; open paren (of any type) which has not been closed before the point. If + ;; an element is a cons, it gives the position of a closed BRACE paren + ;; pair[*]; the car is the start brace position and the cdr is the position + ;; following the closing brace. Only the last closed brace paren pair + ;; before each open paren and before the point is recorded, and thus the + ;; state never contains two cons elements in succession. When a close brace + ;; has no matching open brace (e.g., the matching brace is outside the + ;; visible region), it is not represented in the returned value. + ;; + ;; [*] N.B. The close "brace" might be a mismatching close bracket or paren. + ;; This defun explicitly treats mismatching parens/braces/brackets as + ;; matching. It is the open brace which makes it a "brace" pair. + ;; + ;; If POINT is within a macro, open parens and brace pairs within + ;; THIS macro MIGHT be recorded. This depends on whether their + ;; syntactic properties have been suppressed by + ;; `c-neutralize-syntax-in-CPP'. This might need fixing (2008-12-11). + ;; + ;; Currently no characters which are given paren syntax with the + ;; syntax-table property are recorded, i.e. angle bracket arglist + ;; parens are never present here. Note that this might change. + ;; + ;; BUG: This function doesn't cope entirely well with unbalanced + ;; parens in macros. (2008-12-11: this has probably been resolved + ;; by the function `c-neutralize-syntax-in-CPP'.) E.g. in the + ;; following case the brace before the macro isn't balanced with the + ;; one after it: + ;; + ;; { + ;; #define X { + ;; } + ;; + ;; Note to maintainers: this function DOES get called with point + ;; within comments and strings, so don't assume it doesn't! + ;; + ;; This function might do hidden buffer changes. + (let* ((here (point)) + (here-bopl (c-point 'bopl)) + strategy ; 'forward, 'backward etc.. + ;; Candidate positions to start scanning from: + cache-pos ; highest position below HERE already existing in + ; cache (or 1). + good-pos + start-point + bopl-state + res + scan-backward-pos scan-forward-p) ; used for 'backward. + ;; If POINT-MIN has changed, adjust the cache + (unless (= (point-min) c-state-point-min) + (c-renarrow-state-cache)) + + ;; Strategy? + (setq res (c-parse-state-get-strategy here c-state-cache-good-pos) + strategy (car res) + cache-pos (cadr res) + start-point (nth 2 res)) + + (when (eq strategy 'BOD) + (setq c-state-cache nil + c-state-cache-good-pos start-point)) + + ;; SCAN! + (save-restriction + (cond + ((memq strategy '(forward BOD)) + (narrow-to-region (point-min) here) + (setq res (c-remove-stale-state-cache start-point here-bopl)) + (setq cache-pos (car res) + scan-backward-pos (cadr res) + bopl-state (car (cddr res))) ; will be nil if (< here-bopl + ; start-point) + (if scan-backward-pos + (c-append-lower-brace-pair-to-state-cache scan-backward-pos)) + (setq good-pos + (c-append-to-state-cache cache-pos)) + (setq c-state-cache-good-pos + (if (and bopl-state + (< good-pos (- here c-state-cache-too-far))) + (c-state-cache-non-literal-place here-bopl bopl-state) + good-pos))) + + ((eq strategy 'backward) + (setq res (c-remove-stale-state-cache-backwards here cache-pos) + good-pos (car res) + scan-backward-pos (cadr res) + scan-forward-p (car (cddr res))) + (if scan-backward-pos + (c-append-lower-brace-pair-to-state-cache + scan-backward-pos)) + (setq c-state-cache-good-pos + (if scan-forward-p + (progn (narrow-to-region (point-min) here) + (c-append-to-state-cache good-pos)) + good-pos))) + + (t ; (eq strategy 'IN-LIT) + (setq c-state-cache nil + c-state-cache-good-pos nil))))) + + c-state-cache) + +(defun c-invalidate-state-cache (here) + ;; This is a wrapper over `c-invalidate-state-cache-1'. + ;; + ;; It suppresses the syntactic effect of the < and > (template) brackets and + ;; of all parens in preprocessor constructs, except for any such construct + ;; containing point. We can then call `c-invalidate-state-cache-1' without + ;; worrying further about macros and template delimiters. + (if (memq 'category-properties c-emacs-features) + ;; Emacs + (c-with-<->-as-parens-suppressed + (if (and c-state-old-cpp-beg + (< c-state-old-cpp-beg here)) + (c-with-all-but-one-cpps-commented-out + c-state-old-cpp-beg + (min c-state-old-cpp-end here) + (c-invalidate-state-cache-1 here)) + (c-with-cpps-commented-out + (c-invalidate-state-cache-1 here)))) + ;; XEmacs + (c-invalidate-state-cache-1 here))) + +(defun c-parse-state () + ;; This is a wrapper over `c-parse-state-1'. See that function for a + ;; description of the functionality and return value. + ;; + ;; It suppresses the syntactic effect of the < and > (template) brackets and + ;; of all parens in preprocessor constructs, except for any such construct + ;; containing point. We can then call `c-parse-state-1' without worrying + ;; further about macros and template delimiters. + (let (here-cpp-beg here-cpp-end) + (save-excursion + (if (c-beginning-of-macro) + (progn + (setq here-cpp-beg (point)) + (unless + (> (setq here-cpp-end (c-syntactic-end-of-macro)) + here-cpp-beg) + (setq here-cpp-beg nil here-cpp-end nil))))) + ;; FIXME!!! Put in a `condition-case' here to protect the integrity of the + ;; subsystem. + (prog1 + (if (memq 'category-properties c-emacs-features) + ;; Emacs + (c-with-<->-as-parens-suppressed + (if (and here-cpp-beg (> here-cpp-end here-cpp-beg)) + (c-with-all-but-one-cpps-commented-out + here-cpp-beg here-cpp-end + (c-parse-state-1)) + (c-with-cpps-commented-out + (c-parse-state-1)))) + ;; XEmacs + (c-parse-state-1)) + (setq c-state-old-cpp-beg (and here-cpp-beg (copy-marker here-cpp-beg t)) + c-state-old-cpp-end (and here-cpp-end (copy-marker here-cpp-end t))) + ))) + +;; Debug tool to catch cache inconsistencies. This is called from +;; 000tests.el. +(defvar c-debug-parse-state nil) +(unless (fboundp 'c-real-parse-state) + (fset 'c-real-parse-state (symbol-function 'c-parse-state))) +(cc-bytecomp-defun c-real-parse-state) + +(defvar c-parse-state-state nil) +(make-variable-buffer-local 'c-parse-state-state) +(defun c-record-parse-state-state () + (setq c-parse-state-state + (mapcar + (lambda (arg) + (cons arg (symbol-value arg))) + '(c-state-cache + c-state-cache-good-pos + c-state-nonlit-pos-cache + c-state-nonlit-pos-cache-limit + c-state-brace-pair-desert + c-state-point-min + c-state-point-min-lit-type + c-state-point-min-lit-start + c-state-min-scan-pos + c-state-old-cpp-beg + c-state-old-cpp-end)))) +(defun c-replay-parse-state-state () + (message + (concat "(setq " + (mapconcat + (lambda (arg) + (format "%s %s%s" (car arg) (if (atom (cdr arg)) "" "'") (cdr arg))) + c-parse-state-state " ") + ")"))) + +(defun c-debug-parse-state () + (let ((here (point)) (res1 (c-real-parse-state)) res2) + (let ((c-state-cache nil) + (c-state-cache-good-pos 1) + (c-state-nonlit-pos-cache nil) + (c-state-nonlit-pos-cache-limit 1) + (c-state-brace-pair-desert nil) + (c-state-point-min 1) + (c-state-point-min-lit-type nil) + (c-state-point-min-lit-start nil) + (c-state-min-scan-pos 1) + (c-state-old-cpp-beg nil) + (c-state-old-cpp-end nil)) + (setq res2 (c-real-parse-state))) + (unless (equal res1 res2) + ;; The cache can actually go further back due to the ad-hoc way + ;; the first paren is found, so try to whack off a bit of its + ;; start before complaining. + ;; (save-excursion + ;; (goto-char (or (c-least-enclosing-brace res2) (point))) + ;; (c-beginning-of-defun-1) + ;; (while (not (or (bobp) (eq (char-after) ?{))) + ;; (c-beginning-of-defun-1)) + ;; (unless (equal (c-whack-state-before (point) res1) res2) + ;; (message (concat "c-parse-state inconsistency at %s: " + ;; "using cache: %s, from scratch: %s") + ;; here res1 res2))) + (message (concat "c-parse-state inconsistency at %s: " + "using cache: %s, from scratch: %s") + here res1 res2) + (message "Old state:") + (c-replay-parse-state-state)) + (c-record-parse-state-state) + res1)) + +(defun c-toggle-parse-state-debug (&optional arg) + (interactive "P") + (setq c-debug-parse-state (c-calculate-state arg c-debug-parse-state)) + (fset 'c-parse-state (symbol-function (if c-debug-parse-state + 'c-debug-parse-state + 'c-real-parse-state))) + (c-keep-region-active)) +(when c-debug-parse-state + (c-toggle-parse-state-debug 1)) + + +(defun c-whack-state-before (bufpos paren-state) + ;; Whack off any state information from PAREN-STATE which lies + ;; before BUFPOS. Not destructive on PAREN-STATE. + (let* ((newstate (list nil)) + (ptr newstate) + car) + (while paren-state + (setq car (car paren-state) + paren-state (cdr paren-state)) + (if (< (if (consp car) (car car) car) bufpos) + (setq paren-state nil) + (setcdr ptr (list car)) + (setq ptr (cdr ptr)))) + (cdr newstate))) + +(defun c-whack-state-after (bufpos paren-state) + ;; Whack off any state information from PAREN-STATE which lies at or + ;; after BUFPOS. Not destructive on PAREN-STATE. + (catch 'done + (while paren-state + (let ((car (car paren-state))) + (if (consp car) + ;; just check the car, because in a balanced brace + ;; expression, it must be impossible for the corresponding + ;; close brace to be before point, but the open brace to + ;; be after. + (if (<= bufpos (car car)) + nil ; whack it off + (if (< bufpos (cdr car)) + ;; its possible that the open brace is before + ;; bufpos, but the close brace is after. In that + ;; case, convert this to a non-cons element. The + ;; rest of the state is before bufpos, so we're + ;; done. + (throw 'done (cons (car car) (cdr paren-state))) + ;; we know that both the open and close braces are + ;; before bufpos, so we also know that everything else + ;; on state is before bufpos. + (throw 'done paren-state))) + (if (<= bufpos car) + nil ; whack it off + ;; it's before bufpos, so everything else should too. + (throw 'done paren-state))) + (setq paren-state (cdr paren-state))) + nil))) + +(defun c-most-enclosing-brace (paren-state &optional bufpos) + ;; Return the bufpos of the innermost enclosing open paren before + ;; bufpos, or nil if none was found. + (let (enclosingp) + (or bufpos (setq bufpos 134217727)) + (while paren-state + (setq enclosingp (car paren-state) + paren-state (cdr paren-state)) + (if (or (consp enclosingp) + (>= enclosingp bufpos)) + (setq enclosingp nil) + (setq paren-state nil))) + enclosingp)) + +(defun c-least-enclosing-brace (paren-state) + ;; Return the bufpos of the outermost enclosing open paren, or nil + ;; if none was found. + (let (pos elem) + (while paren-state + (setq elem (car paren-state) + paren-state (cdr paren-state)) + (if (integerp elem) + (setq pos elem))) + pos)) + +(defun c-safe-position (bufpos paren-state) + ;; Return the closest "safe" position recorded on PAREN-STATE that + ;; is higher up than BUFPOS. Return nil if PAREN-STATE doesn't + ;; contain any. Return nil if BUFPOS is nil, which is useful to + ;; find the closest limit before a given limit that might be nil. + ;; + ;; A "safe" position is a position at or after a recorded open + ;; paren, or after a recorded close paren. The returned position is + ;; thus either the first position after a close brace, or the first + ;; position after an enclosing paren, or at the enclosing paren in + ;; case BUFPOS is immediately after it. + (when bufpos + (let (elem) + (catch 'done + (while paren-state + (setq elem (car paren-state)) + (if (consp elem) + (cond ((< (cdr elem) bufpos) + (throw 'done (cdr elem))) + ((< (car elem) bufpos) + ;; See below. + (throw 'done (min (1+ (car elem)) bufpos)))) + (if (< elem bufpos) + ;; elem is the position at and not after the opening paren, so + ;; we can go forward one more step unless it's equal to + ;; bufpos. This is useful in some cases avoid an extra paren + ;; level between the safe position and bufpos. + (throw 'done (min (1+ elem) bufpos)))) + (setq paren-state (cdr paren-state))))))) + +(defun c-beginning-of-syntax () + ;; This is used for `font-lock-beginning-of-syntax-function'. It + ;; goes to the closest previous point that is known to be outside + ;; any string literal or comment. `c-state-cache' is used if it has + ;; a position in the vicinity. + (let* ((paren-state c-state-cache) + elem + + (pos (catch 'done + ;; Note: Similar code in `c-safe-position'. The + ;; difference is that we accept a safe position at + ;; the point and don't bother to go forward past open + ;; parens. + (while paren-state + (setq elem (car paren-state)) + (if (consp elem) + (cond ((<= (cdr elem) (point)) + (throw 'done (cdr elem))) + ((<= (car elem) (point)) + (throw 'done (car elem)))) + (if (<= elem (point)) + (throw 'done elem))) + (setq paren-state (cdr paren-state))) + (point-min)))) + + (if (> pos (- (point) 4000)) + (goto-char pos) + ;; The position is far back. Try `c-beginning-of-defun-1' + ;; (although we can't be entirely sure it will go to a position + ;; outside a comment or string in current emacsen). FIXME: + ;; Consult `syntax-ppss' here. + (c-beginning-of-defun-1) + (if (< (point) pos) + (goto-char pos))))) + + +;; Tools for scanning identifiers and other tokens. + +(defun c-on-identifier () + "Return non-nil if the point is on or directly after an identifier. +Keywords are recognized and not considered identifiers. If an +identifier is detected, the returned value is its starting position. +If an identifier ends at the point and another begins at it \(can only +happen in Pike) then the point for the preceding one is returned. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + ;; FIXME: Shouldn't this function handle "operator" in C++? + + (save-excursion + (skip-syntax-backward "w_") + + (or + + ;; Check for a normal (non-keyword) identifier. + (and (looking-at c-symbol-start) + (not (looking-at c-keywords-regexp)) + (point)) + + (when (c-major-mode-is 'pike-mode) + ;; Handle the ` syntax in Pike. + (let ((pos (point))) + (skip-chars-backward "-!%&*+/<=>^|~[]()") + (and (if (< (skip-chars-backward "`") 0) + t + (goto-char pos) + (eq (char-after) ?\`)) + (looking-at c-symbol-key) + (>= (match-end 0) pos) + (point)))) + + ;; Handle the "operator +" syntax in C++. + (when (and c-overloadable-operators-regexp + (= (c-backward-token-2 0) 0)) + + (cond ((and (looking-at c-overloadable-operators-regexp) + (or (not c-opt-op-identifier-prefix) + (and (= (c-backward-token-2 1) 0) + (looking-at c-opt-op-identifier-prefix)))) + (point)) + + ((save-excursion + (and c-opt-op-identifier-prefix + (looking-at c-opt-op-identifier-prefix) + (= (c-forward-token-2 1) 0) + (looking-at c-overloadable-operators-regexp))) + (point)))) + + ))) + +(defsubst c-simple-skip-symbol-backward () + ;; If the point is at the end of a symbol then skip backward to the + ;; beginning of it. Don't move otherwise. Return non-nil if point + ;; moved. + ;; + ;; This function might do hidden buffer changes. + (or (< (skip-syntax-backward "w_") 0) + (and (c-major-mode-is 'pike-mode) + ;; Handle the ` syntax in Pike. + (let ((pos (point))) + (if (and (< (skip-chars-backward "-!%&*+/<=>^|~[]()") 0) + (< (skip-chars-backward "`") 0) + (looking-at c-symbol-key) + (>= (match-end 0) pos)) + t + (goto-char pos) + nil))))) + +(defun c-beginning-of-current-token (&optional back-limit) + ;; Move to the beginning of the current token. Do not move if not + ;; in the middle of one. BACK-LIMIT may be used to bound the + ;; backward search; if given it's assumed to be at the boundary + ;; between two tokens. Return non-nil if the point is moved, nil + ;; otherwise. + ;; + ;; This function might do hidden buffer changes. + (let ((start (point))) + (if (looking-at "\\w\\|\\s_") + (skip-syntax-backward "w_" back-limit) + (when (< (skip-syntax-backward ".()" back-limit) 0) + (while (let ((pos (or (and (looking-at c-nonsymbol-token-regexp) + (match-end 0)) + ;; `c-nonsymbol-token-regexp' should always match + ;; since we've skipped backward over punctuator + ;; or paren syntax, but consume one char in case + ;; it doesn't so that we don't leave point before + ;; some earlier incorrect token. + (1+ (point))))) + (if (<= pos start) + (goto-char pos)))))) + (< (point) start))) + +(defun c-end-of-current-token (&optional back-limit) + ;; Move to the end of the current token. Do not move if not in the + ;; middle of one. BACK-LIMIT may be used to bound the backward + ;; search; if given it's assumed to be at the boundary between two + ;; tokens. Return non-nil if the point is moved, nil otherwise. + ;; + ;; This function might do hidden buffer changes. + (let ((start (point))) + (cond ((< (skip-syntax-backward "w_" (1- start)) 0) + (skip-syntax-forward "w_")) + ((< (skip-syntax-backward ".()" back-limit) 0) + (while (progn + (if (looking-at c-nonsymbol-token-regexp) + (goto-char (match-end 0)) + ;; `c-nonsymbol-token-regexp' should always match since + ;; we've skipped backward over punctuator or paren + ;; syntax, but move forward in case it doesn't so that + ;; we don't leave point earlier than we started with. + (forward-char)) + (< (point) start))))) + (> (point) start))) + +(defconst c-jump-syntax-balanced + (if (memq 'gen-string-delim c-emacs-features) + "\\w\\|\\s_\\|\\s\(\\|\\s\)\\|\\s\"\\|\\s|" + "\\w\\|\\s_\\|\\s\(\\|\\s\)\\|\\s\"")) + +(defconst c-jump-syntax-unbalanced + (if (memq 'gen-string-delim c-emacs-features) + "\\w\\|\\s_\\|\\s\"\\|\\s|" + "\\w\\|\\s_\\|\\s\"")) + +(defun c-forward-token-2 (&optional count balanced limit) + "Move forward by tokens. +A token is defined as all symbols and identifiers which aren't +syntactic whitespace \(note that multicharacter tokens like \"==\" are +treated properly). Point is always either left at the beginning of a +token or not moved at all. COUNT specifies the number of tokens to +move; a negative COUNT moves in the opposite direction. A COUNT of 0 +moves to the next token beginning only if not already at one. If +BALANCED is true, move over balanced parens, otherwise move into them. +Also, if BALANCED is true, never move out of an enclosing paren. + +LIMIT sets the limit for the movement and defaults to the point limit. +The case when LIMIT is set in the middle of a token, comment or macro +is handled correctly, i.e. the point won't be left there. + +Return the number of tokens left to move \(positive or negative). If +BALANCED is true, a move over a balanced paren counts as one. Note +that if COUNT is 0 and no appropriate token beginning is found, 1 will +be returned. Thus, a return value of 0 guarantees that point is at +the requested position and a return value less \(without signs) than +COUNT guarantees that point is at the beginning of some token. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (or count (setq count 1)) + (if (< count 0) + (- (c-backward-token-2 (- count) balanced limit)) + + (let ((jump-syntax (if balanced + c-jump-syntax-balanced + c-jump-syntax-unbalanced)) + (last (point)) + (prev (point))) + + (if (zerop count) + ;; If count is zero we should jump if in the middle of a token. + (c-end-of-current-token)) + + (save-restriction + (if limit (narrow-to-region (point-min) limit)) + (if (/= (point) + (progn (c-forward-syntactic-ws) (point))) + ;; Skip whitespace. Count this as a move if we did in + ;; fact move. + (setq count (max (1- count) 0))) + + (if (eobp) + ;; Moved out of bounds. Make sure the returned count isn't zero. + (progn + (if (zerop count) (setq count 1)) + (goto-char last)) + + ;; Use `condition-case' to avoid having the limit tests + ;; inside the loop. + (condition-case nil + (while (and + (> count 0) + (progn + (setq last (point)) + (cond ((looking-at jump-syntax) + (goto-char (scan-sexps (point) 1)) + t) + ((looking-at c-nonsymbol-token-regexp) + (goto-char (match-end 0)) + t) + ;; `c-nonsymbol-token-regexp' above should always + ;; match if there are correct tokens. Try to + ;; widen to see if the limit was set in the + ;; middle of one, else fall back to treating + ;; the offending thing as a one character token. + ((and limit + (save-restriction + (widen) + (looking-at c-nonsymbol-token-regexp))) + nil) + (t + (forward-char) + t)))) + (c-forward-syntactic-ws) + (setq prev last + count (1- count))) + (error (goto-char last))) + + (when (eobp) + (goto-char prev) + (setq count (1+ count))))) + + count))) + +(defun c-backward-token-2 (&optional count balanced limit) + "Move backward by tokens. +See `c-forward-token-2' for details." + + (or count (setq count 1)) + (if (< count 0) + (- (c-forward-token-2 (- count) balanced limit)) + + (or limit (setq limit (point-min))) + (let ((jump-syntax (if balanced + c-jump-syntax-balanced + c-jump-syntax-unbalanced)) + (last (point))) + + (if (zerop count) + ;; The count is zero so try to skip to the beginning of the + ;; current token. + (if (> (point) + (progn (c-beginning-of-current-token) (point))) + (if (< (point) limit) + ;; The limit is inside the same token, so return 1. + (setq count 1)) + + ;; We're not in the middle of a token. If there's + ;; whitespace after the point then we must move backward, + ;; so set count to 1 in that case. + (and (looking-at c-syntactic-ws-start) + ;; If we're looking at a '#' that might start a cpp + ;; directive then we have to do a more elaborate check. + (or (/= (char-after) ?#) + (not c-opt-cpp-prefix) + (save-excursion + (and (= (point) + (progn (beginning-of-line) + (looking-at "[ \t]*") + (match-end 0))) + (or (bobp) + (progn (backward-char) + (not (eq (char-before) ?\\))))))) + (setq count 1)))) + + ;; Use `condition-case' to avoid having to check for buffer + ;; limits in `backward-char', `scan-sexps' and `goto-char' below. + (condition-case nil + (while (and + (> count 0) + (progn + (c-backward-syntactic-ws) + (backward-char) + (if (looking-at jump-syntax) + (goto-char (scan-sexps (1+ (point)) -1)) + ;; This can be very inefficient if there's a long + ;; sequence of operator tokens without any separation. + ;; That doesn't happen in practice, anyway. + (c-beginning-of-current-token)) + (>= (point) limit))) + (setq last (point) + count (1- count))) + (error (goto-char last))) + + (if (< (point) limit) + (goto-char last)) + + count))) + +(defun c-forward-token-1 (&optional count balanced limit) + "Like `c-forward-token-2' but doesn't treat multicharacter operator +tokens like \"==\" as single tokens, i.e. all sequences of symbol +characters are jumped over character by character. This function is +for compatibility only; it's only a wrapper over `c-forward-token-2'." + (let ((c-nonsymbol-token-regexp "\\s.\\|\\s\(\\|\\s\)")) + (c-forward-token-2 count balanced limit))) + +(defun c-backward-token-1 (&optional count balanced limit) + "Like `c-backward-token-2' but doesn't treat multicharacter operator +tokens like \"==\" as single tokens, i.e. all sequences of symbol +characters are jumped over character by character. This function is +for compatibility only; it's only a wrapper over `c-backward-token-2'." + (let ((c-nonsymbol-token-regexp "\\s.\\|\\s\(\\|\\s\)")) + (c-backward-token-2 count balanced limit))) + + +;; Tools for doing searches restricted to syntactically relevant text. + +(defun c-syntactic-re-search-forward (regexp &optional bound noerror + paren-level not-inside-token + lookbehind-submatch) + "Like `re-search-forward', but only report matches that are found +in syntactically significant text. I.e. matches in comments, macros +or string literals are ignored. The start point is assumed to be +outside any comment, macro or string literal, or else the content of +that region is taken as syntactically significant text. + +If PAREN-LEVEL is non-nil, an additional restriction is added to +ignore matches in nested paren sexps. The search will also not go +outside the current list sexp, which has the effect that if the point +should be moved to BOUND when no match is found \(i.e. NOERROR is +neither nil nor t), then it will be at the closing paren if the end of +the current list sexp is encountered first. + +If NOT-INSIDE-TOKEN is non-nil, matches in the middle of tokens are +ignored. Things like multicharacter operators and special symbols +\(e.g. \"`()\" in Pike) are handled but currently not floating point +constants. + +If LOOKBEHIND-SUBMATCH is non-nil, it's taken as a number of a +subexpression in REGEXP. The end of that submatch is used as the +position to check for syntactic significance. If LOOKBEHIND-SUBMATCH +isn't used or if that subexpression didn't match then the start +position of the whole match is used instead. The \"look behind\" +subexpression is never tested before the starting position, so it +might be a good idea to include \\=\\= as a match alternative in it. + +Optimization note: Matches might be missed if the \"look behind\" +subexpression can match the end of nonwhite syntactic whitespace, +i.e. the end of comments or cpp directives. This since the function +skips over such things before resuming the search. It's on the other +hand not safe to assume that the \"look behind\" subexpression never +matches syntactic whitespace. + +Bug: Unbalanced parens inside cpp directives are currently not handled +correctly \(i.e. they don't get ignored as they should) when +PAREN-LEVEL is set. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (or bound (setq bound (point-max))) + (if paren-level (setq paren-level -1)) + + ;;(message "c-syntactic-re-search-forward %s %s %S" (point) bound regexp) + + (let ((start (point)) + tmp + ;; Start position for the last search. + search-pos + ;; The `parse-partial-sexp' state between the start position + ;; and the point. + state + ;; The current position after the last state update. The next + ;; `parse-partial-sexp' continues from here. + (state-pos (point)) + ;; The position at which to check the state and the state + ;; there. This is separate from `state-pos' since we might + ;; need to back up before doing the next search round. + check-pos check-state + ;; Last position known to end a token. + (last-token-end-pos (point-min)) + ;; Set when a valid match is found. + found) + + (condition-case err + (while + (and + (progn + (setq search-pos (point)) + (re-search-forward regexp bound noerror)) + + (progn + (setq state (parse-partial-sexp + state-pos (match-beginning 0) paren-level nil state) + state-pos (point)) + (if (setq check-pos (and lookbehind-submatch + (or (not paren-level) + (>= (car state) 0)) + (match-end lookbehind-submatch))) + (setq check-state (parse-partial-sexp + state-pos check-pos paren-level nil state)) + (setq check-pos state-pos + check-state state)) + + ;; NOTE: If we got a look behind subexpression and get + ;; an insignificant match in something that isn't + ;; syntactic whitespace (i.e. strings or in nested + ;; parentheses), then we can never skip more than a + ;; single character from the match start position + ;; (i.e. `state-pos' here) before continuing the + ;; search. That since the look behind subexpression + ;; might match the end of the insignificant region in + ;; the next search. + + (cond + ((elt check-state 7) + ;; Match inside a line comment. Skip to eol. Use + ;; `re-search-forward' instead of `skip-chars-forward' to get + ;; the right bound behavior. + (re-search-forward "[\n\r]" bound noerror)) + + ((elt check-state 4) + ;; Match inside a block comment. Skip to the '*/'. + (search-forward "*/" bound noerror)) + + ((and (not (elt check-state 5)) + (eq (char-before check-pos) ?/) + (not (c-get-char-property (1- check-pos) 'syntax-table)) + (memq (char-after check-pos) '(?/ ?*))) + ;; Match in the middle of the opener of a block or line + ;; comment. + (if (= (char-after check-pos) ?/) + (re-search-forward "[\n\r]" bound noerror) + (search-forward "*/" bound noerror))) + + ;; The last `parse-partial-sexp' above might have + ;; stopped short of the real check position if the end + ;; of the current sexp was encountered in paren-level + ;; mode. The checks above are always false in that + ;; case, and since they can do better skipping in + ;; lookbehind-submatch mode, we do them before + ;; checking the paren level. + + ((and paren-level + (/= (setq tmp (car check-state)) 0)) + ;; Check the paren level first since we're short of the + ;; syntactic checking position if the end of the + ;; current sexp was encountered by `parse-partial-sexp'. + (if (> tmp 0) + + ;; Inside a nested paren sexp. + (if lookbehind-submatch + ;; See the NOTE above. + (progn (goto-char state-pos) t) + ;; Skip out of the paren quickly. + (setq state (parse-partial-sexp state-pos bound 0 nil state) + state-pos (point))) + + ;; Have exited the current paren sexp. + (if noerror + (progn + ;; The last `parse-partial-sexp' call above + ;; has left us just after the closing paren + ;; in this case, so we can modify the bound + ;; to leave the point at the right position + ;; upon return. + (setq bound (1- (point))) + nil) + (signal 'search-failed (list regexp))))) + + ((setq tmp (elt check-state 3)) + ;; Match inside a string. + (if (or lookbehind-submatch + (not (integerp tmp))) + ;; See the NOTE above. + (progn (goto-char state-pos) t) + ;; Skip to the end of the string before continuing. + (let ((ender (make-string 1 tmp)) (continue t)) + (while (if (search-forward ender bound noerror) + (progn + (setq state (parse-partial-sexp + state-pos (point) nil nil state) + state-pos (point)) + (elt state 3)) + (setq continue nil))) + continue))) + + ((save-excursion + (save-match-data + (c-beginning-of-macro start))) + ;; Match inside a macro. Skip to the end of it. + (c-end-of-macro) + (cond ((<= (point) bound) t) + (noerror nil) + (t (signal 'search-failed (list regexp))))) + + ((and not-inside-token + (or (< check-pos last-token-end-pos) + (< check-pos + (save-excursion + (goto-char check-pos) + (save-match-data + (c-end-of-current-token last-token-end-pos)) + (setq last-token-end-pos (point)))))) + ;; Inside a token. + (if lookbehind-submatch + ;; See the NOTE above. + (goto-char state-pos) + (goto-char (min last-token-end-pos bound)))) + + (t + ;; A real match. + (setq found t) + nil))) + + ;; Should loop to search again, but take care to avoid + ;; looping on the same spot. + (or (/= search-pos (point)) + (if (= (point) bound) + (if noerror + nil + (signal 'search-failed (list regexp))) + (forward-char) + t)))) + + (error + (goto-char start) + (signal (car err) (cdr err)))) + + ;;(message "c-syntactic-re-search-forward done %s" (or (match-end 0) (point))) + + (if found + (progn + (goto-char (match-end 0)) + (match-end 0)) + + ;; Search failed. Set point as appropriate. + (if (eq noerror t) + (goto-char start) + (goto-char bound)) + nil))) + +(cc-bytecomp-defvar safe-pos-list) +(defsubst c-ssb-lit-begin () + ;; Return the start of the literal point is in, or nil. + ;; We read and write the variables `safe-pos', `safe-pos-list', `state' + ;; bound in the caller. + + ;; Use `parse-partial-sexp' from a safe position down to the point to check + ;; if it's outside comments and strings. + (save-excursion + (let ((pos (point)) safe-pos state) + ;; Pick a safe position as close to the point as possible. + ;; + ;; FIXME: Consult `syntax-ppss' here if our cache doesn't give a good + ;; position. + + (while (and safe-pos-list + (> (car safe-pos-list) (point))) + (setq safe-pos-list (cdr safe-pos-list))) + (unless (setq safe-pos (car-safe safe-pos-list)) + (setq safe-pos (max (or (c-safe-position + (point) (or c-state-cache + (c-parse-state))) + 0) + (point-min)) + safe-pos-list (list safe-pos))) + + ;; Cache positions along the way to use if we have to back up more. We + ;; cache every closing paren on the same level. If the paren cache is + ;; relevant in this region then we're typically already on the same + ;; level as the target position. Note that we might cache positions + ;; after opening parens in case safe-pos is in a nested list. That's + ;; both uncommon and harmless. + (while (progn + (setq state (parse-partial-sexp + safe-pos pos 0)) + (< (point) pos)) + (setq safe-pos (point) + safe-pos-list (cons safe-pos safe-pos-list))) + + ;; If the state contains the start of the containing sexp we cache that + ;; position too, so that parse-partial-sexp in the next run has a bigger + ;; chance of starting at the same level as the target position and thus + ;; will get more good safe positions into the list. + (if (elt state 1) + (setq safe-pos (1+ (elt state 1)) + safe-pos-list (cons safe-pos safe-pos-list))) + + (if (or (elt state 3) (elt state 4)) + ;; Inside string or comment. Continue search at the + ;; beginning of it. + (elt state 8))))) + +(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level) + "Like `skip-chars-backward' but only look at syntactically relevant chars, +i.e. don't stop at positions inside syntactic whitespace or string +literals. Preprocessor directives are also ignored, with the exception +of the one that the point starts within, if any. If LIMIT is given, +it's assumed to be at a syntactically relevant position. + +If PAREN-LEVEL is non-nil, the function won't stop in nested paren +sexps, and the search will also not go outside the current paren sexp. +However, if LIMIT or the buffer limit is reached inside a nested paren +then the point will be left at the limit. + +Non-nil is returned if the point moved, nil otherwise. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (let ((start (point)) + state-2 + ;; A list of syntactically relevant positions in descending + ;; order. It's used to avoid scanning repeatedly over + ;; potentially large regions with `parse-partial-sexp' to verify + ;; each position. Used in `c-ssb-lit-begin' + safe-pos-list + ;; The result from `c-beginning-of-macro' at the start position or the + ;; start position itself if it isn't within a macro. Evaluated on + ;; demand. + start-macro-beg + ;; The earliest position after the current one with the same paren + ;; level. Used only when `paren-level' is set. + lit-beg + (paren-level-pos (point))) + + (while + (progn + ;; The next loop "tries" to find the end point each time round, + ;; loops when it hasn't succeeded. + (while + (and + (< (skip-chars-backward skip-chars limit) 0) + + (let ((pos (point)) state-2 pps-end-pos) + + (cond + ;; Don't stop inside a literal + ((setq lit-beg (c-ssb-lit-begin)) + (goto-char lit-beg) + t) + + ((and paren-level + (save-excursion + (setq state-2 (parse-partial-sexp + pos paren-level-pos -1) + pps-end-pos (point)) + (/= (car state-2) 0))) + ;; Not at the right level. + + (if (and (< (car state-2) 0) + ;; We stop above if we go out of a paren. + ;; Now check whether it precedes or is + ;; nested in the starting sexp. + (save-excursion + (setq state-2 + (parse-partial-sexp + pps-end-pos paren-level-pos + nil nil state-2)) + (< (car state-2) 0))) + + ;; We've stopped short of the starting position + ;; so the hit was inside a nested list. Go up + ;; until we are at the right level. + (condition-case nil + (progn + (goto-char (scan-lists pos -1 + (- (car state-2)))) + (setq paren-level-pos (point)) + (if (and limit (>= limit paren-level-pos)) + (progn + (goto-char limit) + nil) + t)) + (error + (goto-char (or limit (point-min))) + nil)) + + ;; The hit was outside the list at the start + ;; position. Go to the start of the list and exit. + (goto-char (1+ (elt state-2 1))) + nil)) + + ((c-beginning-of-macro limit) + ;; Inside a macro. + (if (< (point) + (or start-macro-beg + (setq start-macro-beg + (save-excursion + (goto-char start) + (c-beginning-of-macro limit) + (point))))) + t + + ;; It's inside the same macro we started in so it's + ;; a relevant match. + (goto-char pos) + nil)))))) + + (> (point) + (progn + ;; Skip syntactic ws afterwards so that we don't stop at the + ;; end of a comment if `skip-chars' is something like "^/". + (c-backward-syntactic-ws) + (point))))) + + ;; We might want to extend this with more useful return values in + ;; the future. + (/= (point) start))) + +;; The following is an alternative implementation of +;; `c-syntactic-skip-backward' that uses backward movement to keep +;; track of the syntactic context. It turned out to be generally +;; slower than the one above which uses forward checks from earlier +;; safe positions. +;; +;;(defconst c-ssb-stop-re +;; ;; The regexp matching chars `c-syntactic-skip-backward' needs to +;; ;; stop at to avoid going into comments and literals. +;; (concat +;; ;; Match comment end syntax and string literal syntax. Also match +;; ;; '/' for block comment endings (not covered by comment end +;; ;; syntax). +;; "\\s>\\|/\\|\\s\"" +;; (if (memq 'gen-string-delim c-emacs-features) +;; "\\|\\s|" +;; "") +;; (if (memq 'gen-comment-delim c-emacs-features) +;; "\\|\\s!" +;; ""))) +;; +;;(defconst c-ssb-stop-paren-re +;; ;; Like `c-ssb-stop-re' but also stops at paren chars. +;; (concat c-ssb-stop-re "\\|\\s(\\|\\s)")) +;; +;;(defconst c-ssb-sexp-end-re +;; ;; Regexp matching the ending syntax of a complex sexp. +;; (concat c-string-limit-regexp "\\|\\s)")) +;; +;;(defun c-syntactic-skip-backward (skip-chars &optional limit paren-level) +;; "Like `skip-chars-backward' but only look at syntactically relevant chars, +;;i.e. don't stop at positions inside syntactic whitespace or string +;;literals. Preprocessor directives are also ignored. However, if the +;;point is within a comment, string literal or preprocessor directory to +;;begin with, its contents is treated as syntactically relevant chars. +;;If LIMIT is given, it limits the backward search and the point will be +;;left there if no earlier position is found. +;; +;;If PAREN-LEVEL is non-nil, the function won't stop in nested paren +;;sexps, and the search will also not go outside the current paren sexp. +;;However, if LIMIT or the buffer limit is reached inside a nested paren +;;then the point will be left at the limit. +;; +;;Non-nil is returned if the point moved, nil otherwise. +;; +;;Note that this function might do hidden buffer changes. See the +;;comment at the start of cc-engine.el for more info." +;; +;; (save-restriction +;; (when limit +;; (narrow-to-region limit (point-max))) +;; +;; (let ((start (point))) +;; (catch 'done +;; (while (let ((last-pos (point)) +;; (stop-pos (progn +;; (skip-chars-backward skip-chars) +;; (point)))) +;; +;; ;; Skip back over the same region as +;; ;; `skip-chars-backward' above, but keep to +;; ;; syntactically relevant positions. +;; (goto-char last-pos) +;; (while (and +;; ;; `re-search-backward' with a single char regexp +;; ;; should be fast. +;; (re-search-backward +;; (if paren-level c-ssb-stop-paren-re c-ssb-stop-re) +;; stop-pos 'move) +;; +;; (progn +;; (cond +;; ((looking-at "\\s(") +;; ;; `paren-level' is set and we've found the +;; ;; start of the containing paren. +;; (forward-char) +;; (throw 'done t)) +;; +;; ((looking-at c-ssb-sexp-end-re) +;; ;; We're at the end of a string literal or paren +;; ;; sexp (if `paren-level' is set). +;; (forward-char) +;; (condition-case nil +;; (c-backward-sexp) +;; (error +;; (goto-char limit) +;; (throw 'done t)))) +;; +;; (t +;; (forward-char) +;; ;; At the end of some syntactic ws or possibly +;; ;; after a plain '/' operator. +;; (let ((pos (point))) +;; (c-backward-syntactic-ws) +;; (if (= pos (point)) +;; ;; Was a plain '/' operator. Go past it. +;; (backward-char))))) +;; +;; (> (point) stop-pos)))) +;; +;; ;; Now the point is either at `stop-pos' or at some +;; ;; position further back if `stop-pos' was at a +;; ;; syntactically irrelevant place. +;; +;; ;; Skip additional syntactic ws so that we don't stop +;; ;; at the end of a comment if `skip-chars' is +;; ;; something like "^/". +;; (c-backward-syntactic-ws) +;; +;; (< (point) stop-pos)))) +;; +;; ;; We might want to extend this with more useful return values +;; ;; in the future. +;; (/= (point) start)))) + + +;; Tools for handling comments and string literals. + +(defun c-in-literal (&optional lim detect-cpp) + "Return the type of literal point is in, if any. +The return value is `c' if in a C-style comment, `c++' if in a C++ +style comment, `string' if in a string literal, `pound' if DETECT-CPP +is non-nil and in a preprocessor line, or nil if somewhere else. +Optional LIM is used as the backward limit of the search. If omitted, +or nil, `c-beginning-of-defun' is used. + +The last point calculated is cached if the cache is enabled, i.e. if +`c-in-literal-cache' is bound to a two element vector. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (save-restriction + (widen) + (let* ((safe-place (c-state-semi-safe-place (point))) + (lit (c-state-pp-to-literal safe-place (point)))) + (or (cadr lit) + (and detect-cpp + (save-excursion (c-beginning-of-macro)) + 'pound))))) + +(defun c-literal-limits (&optional lim near not-in-delimiter) + "Return a cons of the beginning and end positions of the comment or +string surrounding point (including both delimiters), or nil if point +isn't in one. If LIM is non-nil, it's used as the \"safe\" position +to start parsing from. If NEAR is non-nil, then the limits of any +literal next to point is returned. \"Next to\" means there's only +spaces and tabs between point and the literal. The search for such a +literal is done first in forward direction. If NOT-IN-DELIMITER is +non-nil, the case when point is inside a starting delimiter won't be +recognized. This only has effect for comments which have starting +delimiters with more than one character. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (save-excursion + (let* ((pos (point)) + (lim (or lim (c-state-semi-safe-place pos))) + (pp-to-lit (save-restriction + (widen) + (c-state-pp-to-literal lim pos))) + (state (car pp-to-lit)) + (lit-limits (car (cddr pp-to-lit)))) + + (cond + (lit-limits) + ((and (not not-in-delimiter) + (not (elt state 5)) + (eq (char-before) ?/) + (looking-at "[/*]")) ; FIXME!!! use c-line/block-comment-starter. 2008-09-28. + ;; We're standing in a comment starter. + (backward-char 1) + (cons (point) (progn (c-forward-single-comment) (point)))) + + (near + (goto-char pos) + ;; Search forward for a literal. + (skip-chars-forward " \t") + (cond + ((looking-at c-string-limit-regexp) ; String. + (cons (point) (or (c-safe (c-forward-sexp 1) (point)) + (point-max)))) + + ((looking-at c-comment-start-regexp) ; Line or block comment. + (cons (point) (progn (c-forward-single-comment) (point)))) + + (t + ;; Search backward. + (skip-chars-backward " \t") + + (let ((end (point)) beg) + (cond + ((save-excursion + (< (skip-syntax-backward c-string-syntax) 0)) ; String. + (setq beg (c-safe (c-backward-sexp 1) (point)))) + + ((and (c-safe (forward-char -2) t) + (looking-at "*/")) + ;; Block comment. Due to the nature of line + ;; comments, they will always be covered by the + ;; normal case above. + (goto-char end) + (c-backward-single-comment) + ;; If LIM is bogus, beg will be bogus. + (setq beg (point)))) + + (if beg (cons beg end)))))) + )))) + +;; In case external callers use this; it did have a docstring. +(defalias 'c-literal-limits-fast 'c-literal-limits) + +(defun c-collect-line-comments (range) + "If the argument is a cons of two buffer positions (such as returned by +`c-literal-limits'), and that range contains a C++ style line comment, +then an extended range is returned that contains all adjacent line +comments (i.e. all comments that starts in the same column with no +empty lines or non-whitespace characters between them). Otherwise the +argument is returned. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (save-excursion + (condition-case nil + (if (and (consp range) (progn + (goto-char (car range)) + (looking-at c-line-comment-starter))) + (let ((col (current-column)) + (beg (point)) + (bopl (c-point 'bopl)) + (end (cdr range))) + ;; Got to take care in the backward direction to handle + ;; comments which are preceded by code. + (while (and (c-backward-single-comment) + (>= (point) bopl) + (looking-at c-line-comment-starter) + (= col (current-column))) + (setq beg (point) + bopl (c-point 'bopl))) + (goto-char end) + (while (and (progn (skip-chars-forward " \t") + (looking-at c-line-comment-starter)) + (= col (current-column)) + (prog1 (zerop (forward-line 1)) + (setq end (point))))) + (cons beg end)) + range) + (error range)))) + +(defun c-literal-type (range) + "Convenience function that given the result of `c-literal-limits', +returns nil or the type of literal that the range surrounds, one +of the symbols 'c, 'c++ or 'string. It's much faster than using +`c-in-literal' and is intended to be used when you need both the +type of a literal and its limits. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (if (consp range) + (save-excursion + (goto-char (car range)) + (cond ((looking-at c-string-limit-regexp) 'string) + ((or (looking-at "//") ; c++ line comment + (and (looking-at "\\s<") ; comment starter + (looking-at "#"))) ; awk comment. + 'c++) + (t 'c))) ; Assuming the range is valid. + range)) + +(defsubst c-determine-limit-get-base (start try-size) + ;; Get a "safe place" approximately TRY-SIZE characters before START. + ;; This doesn't preserve point. + (let* ((pos (max (- start try-size) (point-min))) + (base (c-state-semi-safe-place pos)) + (s (parse-partial-sexp base pos))) + (if (or (nth 4 s) (nth 3 s)) ; comment or string + (nth 8 s) + (point)))) + +(defun c-determine-limit (how-far-back &optional start try-size) + ;; Return a buffer position HOW-FAR-BACK non-literal characters from START + ;; (default point). This is done by going back further in the buffer then + ;; searching forward for literals. The position found won't be in a + ;; literal. We start searching for the sought position TRY-SIZE (default + ;; twice HOW-FAR-BACK) bytes back from START. This function must be fast. + ;; :-) + (save-excursion + (let* ((start (or start (point))) + (try-size (or try-size (* 2 how-far-back))) + (base (c-determine-limit-get-base start try-size)) + (pos base) + + (s (parse-partial-sexp pos pos)) ; null state. + stack elt size + (count 0)) + (while (< pos start) + ;; Move forward one literal each time round this loop. + ;; Move forward to the start of a comment or string. + (setq s (parse-partial-sexp + pos + start + nil ; target-depth + nil ; stop-before + s ; state + 'syntax-table)) ; stop-comment + + ;; Gather details of the non-literal-bit - starting pos and size. + (setq size (- (if (or (nth 4 s) (nth 3 s)) + (nth 8 s) + (point)) + pos)) + (if (> size 0) + (setq stack (cons (cons pos size) stack))) + + ;; Move forward to the end of the comment/string. + (if (or (nth 4 s) (nth 3 s)) + (setq s (parse-partial-sexp + (point) + start + nil ; target-depth + nil ; stop-before + s ; state + 'syntax-table))) ; stop-comment + (setq pos (point))) + + ;; Now try and find enough non-literal characters recorded on the stack. + ;; Go back one recorded literal each time round this loop. + (while (and (< count how-far-back) + stack) + (setq elt (car stack) + stack (cdr stack)) + (setq count (+ count (cdr elt)))) + + ;; Have we found enough yet? + (cond + ((>= count how-far-back) + (+ (car elt) (- count how-far-back))) + ((eq base (point-min)) + (point-min)) + (t + (c-determine-limit (- how-far-back count) base try-size)))))) + +(defun c-determine-+ve-limit (how-far &optional start-pos) + ;; Return a buffer position about HOW-FAR non-literal characters forward + ;; from START-POS (default point), which must not be inside a literal. + (save-excursion + (let ((pos (or start-pos (point))) + (count how-far) + (s (parse-partial-sexp (point) (point)))) ; null state + (while (and (not (eobp)) + (> count 0)) + ;; Scan over counted characters. + (setq s (parse-partial-sexp + pos + (min (+ pos count) (point-max)) + nil ; target-depth + nil ; stop-before + s ; state + 'syntax-table)) ; stop-comment + (setq count (- count (- (point) pos) 1) + pos (point)) + ;; Scan over literal characters. + (if (nth 8 s) + (setq s (parse-partial-sexp + pos + (point-max) + nil ; target-depth + nil ; stop-before + s ; state + 'syntax-table) ; stop-comment + pos (point)))) + (point)))) + + +;; `c-find-decl-spots' and accompanying stuff. + +;; Variables used in `c-find-decl-spots' to cache the search done for +;; the first declaration in the last call. When that function starts, +;; it needs to back up over syntactic whitespace to look at the last +;; token before the region being searched. That can sometimes cause +;; moves back and forth over a quite large region of comments and +;; macros, which would be repeated for each changed character when +;; we're called during fontification, since font-lock refontifies the +;; current line for each change. Thus it's worthwhile to cache the +;; first match. +;; +;; `c-find-decl-syntactic-pos' is a syntactically relevant position in +;; the syntactic whitespace less or equal to some start position. +;; There's no cached value if it's nil. +;; +;; `c-find-decl-match-pos' is the match position if +;; `c-find-decl-prefix-search' matched before the syntactic whitespace +;; at `c-find-decl-syntactic-pos', or nil if there's no such match. +(defvar c-find-decl-syntactic-pos nil) +(make-variable-buffer-local 'c-find-decl-syntactic-pos) +(defvar c-find-decl-match-pos nil) +(make-variable-buffer-local 'c-find-decl-match-pos) + +(defsubst c-invalidate-find-decl-cache (change-min-pos) + (and c-find-decl-syntactic-pos + (< change-min-pos c-find-decl-syntactic-pos) + (setq c-find-decl-syntactic-pos nil))) + +; (defface c-debug-decl-spot-face +; '((t (:background "Turquoise"))) +; "Debug face to mark the spots where `c-find-decl-spots' stopped.") +; (defface c-debug-decl-sws-face +; '((t (:background "Khaki"))) +; "Debug face to mark the syntactic whitespace between the declaration +; spots and the preceding token end.") + +(defmacro c-debug-put-decl-spot-faces (match-pos decl-pos) + (when (facep 'c-debug-decl-spot-face) + `(c-save-buffer-state ((match-pos ,match-pos) (decl-pos ,decl-pos)) + (c-debug-add-face (max match-pos (point-min)) decl-pos + 'c-debug-decl-sws-face) + (c-debug-add-face decl-pos (min (1+ decl-pos) (point-max)) + 'c-debug-decl-spot-face)))) +(defmacro c-debug-remove-decl-spot-faces (beg end) + (when (facep 'c-debug-decl-spot-face) + `(c-save-buffer-state () + (c-debug-remove-face ,beg ,end 'c-debug-decl-spot-face) + (c-debug-remove-face ,beg ,end 'c-debug-decl-sws-face)))) + +(defmacro c-find-decl-prefix-search () + ;; Macro used inside `c-find-decl-spots'. It ought to be a defun, + ;; but it contains lots of free variables that refer to things + ;; inside `c-find-decl-spots'. The point is left at `cfd-match-pos' + ;; if there is a match, otherwise at `cfd-limit'. + ;; + ;; This macro might do hidden buffer changes. + + '(progn + ;; Find the next property match position if we haven't got one already. + (unless cfd-prop-match + (save-excursion + (while (progn + (goto-char (c-next-single-property-change + (point) 'c-type nil cfd-limit)) + (and (< (point) cfd-limit) + (not (eq (c-get-char-property (1- (point)) 'c-type) + 'c-decl-end))))) + (setq cfd-prop-match (point)))) + + ;; Find the next `c-decl-prefix-or-start-re' match if we haven't + ;; got one already. + (unless cfd-re-match + + (if (> cfd-re-match-end (point)) + (goto-char cfd-re-match-end)) + + (while (if (setq cfd-re-match-end + (re-search-forward c-decl-prefix-or-start-re + cfd-limit 'move)) + + ;; Match. Check if it's inside a comment or string literal. + (c-got-face-at + (if (setq cfd-re-match (match-end 1)) + ;; Matched the end of a token preceding a decl spot. + (progn + (goto-char cfd-re-match) + (1- cfd-re-match)) + ;; Matched a token that start a decl spot. + (goto-char (match-beginning 0)) + (point)) + c-literal-faces) + + ;; No match. Finish up and exit the loop. + (setq cfd-re-match cfd-limit) + nil) + + ;; Skip out of comments and string literals. + (while (progn + (goto-char (c-next-single-property-change + (point) 'face nil cfd-limit)) + (and (< (point) cfd-limit) + (c-got-face-at (point) c-literal-faces))))) + + ;; If we matched at the decl start, we have to back up over the + ;; preceding syntactic ws to set `cfd-match-pos' and to catch + ;; any decl spots in the syntactic ws. + (unless cfd-re-match + (c-backward-syntactic-ws) + (setq cfd-re-match (point)))) + + ;; Choose whichever match is closer to the start. + (if (< cfd-re-match cfd-prop-match) + (setq cfd-match-pos cfd-re-match + cfd-re-match nil) + (setq cfd-match-pos cfd-prop-match + cfd-prop-match nil)) + + (goto-char cfd-match-pos) + + (when (< cfd-match-pos cfd-limit) + ;; Skip forward past comments only so we don't skip macros. + (c-forward-comments) + ;; Set the position to continue at. We can avoid going over + ;; the comments skipped above a second time, but it's possible + ;; that the comment skipping has taken us past `cfd-prop-match' + ;; since the property might be used inside comments. + (setq cfd-continue-pos (if cfd-prop-match + (min cfd-prop-match (point)) + (point)))))) + +(defun c-find-decl-spots (cfd-limit cfd-decl-re cfd-face-checklist cfd-fun) + ;; Call CFD-FUN for each possible spot for a declaration, cast or + ;; label from the point to CFD-LIMIT. + ;; + ;; CFD-FUN is called with point at the start of the spot. It's passed two + ;; arguments: The first is the end position of the token preceding the spot, + ;; or 0 for the implicit match at bob. The second is a flag that is t when + ;; the match is inside a macro. Point should be moved forward by at least + ;; one token. + ;; + ;; If CFD-FUN adds `c-decl-end' properties somewhere below the current spot, + ;; it should return non-nil to ensure that the next search will find them. + ;; + ;; Such a spot is: + ;; o The first token after bob. + ;; o The first token after the end of submatch 1 in + ;; `c-decl-prefix-or-start-re' when that submatch matches. This + ;; submatch is typically a (L or R) brace or paren, a ;, or a ,. + ;; o The start of each `c-decl-prefix-or-start-re' match when + ;; submatch 1 doesn't match. This is, for example, the keyword + ;; "class" in Pike. + ;; o The start of a previously recognized declaration; "recognized" + ;; means that the last char of the previous token has a `c-type' + ;; text property with the value `c-decl-end'; this only holds + ;; when `c-type-decl-end-used' is set. + ;; + ;; Only a spot that match CFD-DECL-RE and whose face is in the + ;; CFD-FACE-CHECKLIST list causes CFD-FUN to be called. The face + ;; check is disabled if CFD-FACE-CHECKLIST is nil. + ;; + ;; If the match is inside a macro then the buffer is narrowed to the + ;; end of it, so that CFD-FUN can investigate the following tokens + ;; without matching something that begins inside a macro and ends + ;; outside it. It's to avoid this work that the CFD-DECL-RE and + ;; CFD-FACE-CHECKLIST checks exist. + ;; + ;; The spots are visited approximately in order from top to bottom. + ;; It's however the positions where `c-decl-prefix-or-start-re' + ;; matches and where `c-decl-end' properties are found that are in + ;; order. Since the spots often are at the following token, they + ;; might be visited out of order insofar as more spots are reported + ;; later on within the syntactic whitespace between the match + ;; positions and their spots. + ;; + ;; It's assumed that comments and strings are fontified in the + ;; searched range. + ;; + ;; This is mainly used in fontification, and so has an elaborate + ;; cache to handle repeated calls from the same start position; see + ;; the variables above. + ;; + ;; All variables in this function begin with `cfd-' to avoid name + ;; collision with the (dynamically bound) variables used in CFD-FUN. + ;; + ;; This function might do hidden buffer changes. + + (let ((cfd-start-pos (point)) ; never changed + (cfd-buffer-end (point-max)) + ;; The end of the token preceding the decl spot last found + ;; with `c-decl-prefix-or-start-re'. `cfd-limit' if there's + ;; no match. + cfd-re-match + ;; The end position of the last `c-decl-prefix-or-start-re' + ;; match. If this is greater than `cfd-continue-pos', the + ;; next regexp search is started here instead. + (cfd-re-match-end (point-min)) + ;; The end of the last `c-decl-end' found by + ;; `c-find-decl-prefix-search'. `cfd-limit' if there's no + ;; match. If searching for the property isn't needed then we + ;; disable it by setting it to `cfd-limit' directly. + (cfd-prop-match + (if c-type-decl-end-used + (save-excursion + (c-backward-syntactic-ws) + (and + (not (bobp)) + (eq (c-get-char-property (1- (point)) 'c-type) + 'c-decl-end) + (point))) + cfd-limit)) + ;; The end of the token preceding the decl spot last found by + ;; `c-find-decl-prefix-search'. 0 for the implicit match at + ;; bob. `cfd-limit' if there's no match. In other words, + ;; this is the minimum of `cfd-re-match' and `cfd-prop-match'. + (cfd-match-pos cfd-limit) + ;; The position to continue searching at. + cfd-continue-pos + ;; The position of the last "real" token we've stopped at. + ;; This can be greater than `cfd-continue-pos' when we get + ;; hits inside macros or at `c-decl-end' positions inside + ;; comments. + (cfd-token-pos 0) + ;; The end position of the last entered macro. + (cfd-macro-end 0)) + + ;; Initialize by finding a syntactically relevant start position + ;; before the point, and do the first `c-decl-prefix-or-start-re' + ;; search unless we're at bob. + + (let (start-in-literal start-in-macro syntactic-pos) + ;; Must back up a bit since we look for the end of the previous + ;; statement or declaration, which is earlier than the first + ;; returned match. + + ;; This `cond' moves back over any literals or macros. It has special + ;; handling for when the region being searched is entirely within a + ;; macro. It sets `cfd-continue-pos' (unless we've reached + ;; `cfd-limit'). + (cond + ;; First we need to move to a syntactically relevant position. + ;; Begin by backing out of comment or string literals. + ;; + ;; This arm of the cond actually triggers if we're in a literal, + ;; and cfd-limit is at most at BONL. + ((and + ;; This arm of the `and' moves backwards out of a literal when + ;; the face at point is a literal face. In this case, its value + ;; is always non-nil. + (when (c-got-face-at (point) c-literal-faces) + ;; Try to use the faces to back up to the start of the + ;; literal. FIXME: What if the point is on a declaration + ;; inside a comment? + (while (and (not (bobp)) + (c-got-face-at (1- (point)) c-literal-faces)) + (goto-char (previous-single-property-change + (point) 'face nil (point-min)))) + + ;; XEmacs doesn't fontify the quotes surrounding string + ;; literals. + (and (featurep 'xemacs) + (eq (get-text-property (point) 'face) + 'font-lock-string-face) + (not (bobp)) + (progn (backward-char) + (not (looking-at c-string-limit-regexp))) + (forward-char)) + + ;; Don't trust the literal to contain only literal faces + ;; (the font lock package might not have fontified the + ;; start of it at all, for instance) so check that we have + ;; arrived at something that looks like a start or else + ;; resort to `c-literal-limits'. + (unless (looking-at c-literal-start-regexp) + (let ((range (c-literal-limits))) + (if range (goto-char (car range))))) + + (setq start-in-literal (point))) ; end of `and' arm. + + ;; The start is in a literal. If the limit is in the same + ;; one we don't have to find a syntactic position etc. We + ;; only check that if the limit is at or before bonl to save + ;; time; it covers the by far most common case when font-lock + ;; refontifies the current line only. + (<= cfd-limit (c-point 'bonl cfd-start-pos)) + (save-excursion + (goto-char cfd-start-pos) + (while (progn + (goto-char (c-next-single-property-change + (point) 'face nil cfd-limit)) + (and (< (point) cfd-limit) + (c-got-face-at (point) c-literal-faces)))) + (= (point) cfd-limit))) ; end of `cond' arm condition + + ;; Completely inside a literal. Set up variables to trig the + ;; (< cfd-continue-pos cfd-start-pos) case below and it'll + ;; find a suitable start position. + (setq cfd-continue-pos start-in-literal)) ; end of `cond' arm + + ;; Check if the region might be completely inside a macro, to + ;; optimize that like the completely-inside-literal above. + ((save-excursion + (and (= (forward-line 1) 0) + (bolp) ; forward-line has funny behavior at eob. + (>= (point) cfd-limit) + (progn (backward-char) + (eq (char-before) ?\\)))) + ;; (Maybe) completely inside a macro. Only need to trig the + ;; (< cfd-continue-pos cfd-start-pos) case below to make it + ;; set things up. + (setq cfd-continue-pos (1- cfd-start-pos) + start-in-macro t)) + + ;; The default arm of the `cond' moves back over any macro we're in + ;; and over any syntactic WS. It sets `c-find-decl-syntactic-pos'. + (t + ;; Back out of any macro so we don't miss any declaration + ;; that could follow after it. + (when (c-beginning-of-macro) + (setq start-in-macro t)) + + ;; Now we're at a proper syntactically relevant position so we + ;; can use the cache. But first clear it if it applied + ;; further down. + (c-invalidate-find-decl-cache cfd-start-pos) + + (setq syntactic-pos (point)) + (unless (eq syntactic-pos c-find-decl-syntactic-pos) + ;; Don't have to do this if the cache is relevant here, + ;; typically if the same line is refontified again. If + ;; we're just some syntactic whitespace further down we can + ;; still use the cache to limit the skipping. + (c-backward-syntactic-ws c-find-decl-syntactic-pos)) + + ;; If we hit `c-find-decl-syntactic-pos' and + ;; `c-find-decl-match-pos' is set then we install the cached + ;; values. If we hit `c-find-decl-syntactic-pos' and + ;; `c-find-decl-match-pos' is nil then we know there's no decl + ;; prefix in the whitespace before `c-find-decl-syntactic-pos' + ;; and so we can continue the search from this point. If we + ;; didn't hit `c-find-decl-syntactic-pos' then we're now in + ;; the right spot to begin searching anyway. + (if (and (eq (point) c-find-decl-syntactic-pos) + c-find-decl-match-pos) + (setq cfd-match-pos c-find-decl-match-pos + cfd-continue-pos syntactic-pos) + + (setq c-find-decl-syntactic-pos syntactic-pos) + + (when (if (bobp) + ;; Always consider bob a match to get the first + ;; declaration in the file. Do this separately instead of + ;; letting `c-decl-prefix-or-start-re' match bob, so that + ;; regexp always can consume at least one character to + ;; ensure that we won't get stuck in an infinite loop. + (setq cfd-re-match 0) + (backward-char) + (c-beginning-of-current-token) + (< (point) cfd-limit)) + ;; Do an initial search now. In the bob case above it's + ;; only done to search for a `c-decl-end' spot. + (c-find-decl-prefix-search)) ; sets cfd-continue-pos + + (setq c-find-decl-match-pos (and (< cfd-match-pos cfd-start-pos) + cfd-match-pos))))) ; end of `cond' + + ;; Advance `cfd-continue-pos' if it's before the start position. + ;; The closest continue position that might have effect at or + ;; after the start depends on what we started in. This also + ;; finds a suitable start position in the special cases when the + ;; region is completely within a literal or macro. + (when (and cfd-continue-pos (< cfd-continue-pos cfd-start-pos)) + + (cond + (start-in-macro + ;; If we're in a macro then it's the closest preceding token + ;; in the macro. Check this before `start-in-literal', + ;; since if we're inside a literal in a macro, the preceding + ;; token is earlier than any `c-decl-end' spot inside the + ;; literal (comment). + (goto-char (or start-in-literal cfd-start-pos)) + ;; The only syntactic ws in macros are comments. + (c-backward-comments) + (backward-char) + (c-beginning-of-current-token)) + + (start-in-literal + ;; If we're in a comment it can only be the closest + ;; preceding `c-decl-end' position within that comment, if + ;; any. Go back to the beginning of such a property so that + ;; `c-find-decl-prefix-search' will find the end of it. + ;; (Can't stop at the end and install it directly on + ;; `cfd-prop-match' since that variable might be cleared + ;; after `cfd-fun' below.) + ;; + ;; Note that if the literal is a string then the property + ;; search will simply skip to the beginning of it right + ;; away. + (if (not c-type-decl-end-used) + (goto-char start-in-literal) + (goto-char cfd-start-pos) + (while (progn + (goto-char (previous-single-property-change + (point) 'c-type nil start-in-literal)) + (and (> (point) start-in-literal) + (not (eq (c-get-char-property (point) 'c-type) + 'c-decl-end)))))) + + (when (= (point) start-in-literal) + ;; Didn't find any property inside the comment, so we can + ;; skip it entirely. (This won't skip past a string, but + ;; that'll be handled quickly by the next + ;; `c-find-decl-prefix-search' anyway.) + (c-forward-single-comment) + (if (> (point) cfd-limit) + (goto-char cfd-limit)))) + + (t + ;; If we started in normal code, the only match that might + ;; apply before the start is what we already got in + ;; `cfd-match-pos' so we can continue at the start position. + ;; (Note that we don't get here if the first match is below + ;; it.) + (goto-char cfd-start-pos))) ; end of `cond' + + ;; Delete found matches if they are before our new continue + ;; position, so that `c-find-decl-prefix-search' won't back up + ;; to them later on. + (setq cfd-continue-pos (point)) + (when (and cfd-re-match (< cfd-re-match cfd-continue-pos)) + (setq cfd-re-match nil)) + (when (and cfd-prop-match (< cfd-prop-match cfd-continue-pos)) + (setq cfd-prop-match nil))) ; end of `when' + + (if syntactic-pos + ;; This is the normal case and we got a proper syntactic + ;; position. If there's a match then it's always outside + ;; macros and comments, so advance to the next token and set + ;; `cfd-token-pos'. The loop below will later go back using + ;; `cfd-continue-pos' to fix declarations inside the + ;; syntactic ws. + (when (and cfd-match-pos (< cfd-match-pos syntactic-pos)) + (goto-char syntactic-pos) + (c-forward-syntactic-ws) + (and cfd-continue-pos + (< cfd-continue-pos (point)) + (setq cfd-token-pos (point)))) + + ;; Have one of the special cases when the region is completely + ;; within a literal or macro. `cfd-continue-pos' is set to a + ;; good start position for the search, so do it. + (c-find-decl-prefix-search))) + + ;; Now loop, one decl spot per iteration. We already have the first + ;; match in `cfd-match-pos'. + (while (progn + ;; Go foward over "false matches", one per iteration. + (while (and + (< cfd-match-pos cfd-limit) + + (or + ;; Kludge to filter out matches on the "<" that + ;; aren't open parens, for the sake of languages + ;; that got `c-recognize-<>-arglists' set. + (and (eq (char-before cfd-match-pos) ?<) + (not (c-get-char-property (1- cfd-match-pos) + 'syntax-table))) + + ;; If `cfd-continue-pos' is less or equal to + ;; `cfd-token-pos', we've got a hit inside a macro + ;; that's in the syntactic whitespace before the last + ;; "real" declaration we've checked. If they're equal + ;; we've arrived at the declaration a second time, so + ;; there's nothing to do. + (= cfd-continue-pos cfd-token-pos) + + (progn + ;; If `cfd-continue-pos' is less than `cfd-token-pos' + ;; we're still searching for declarations embedded in + ;; the syntactic whitespace. In that case we need + ;; only to skip comments and not macros, since they + ;; can't be nested, and that's already been done in + ;; `c-find-decl-prefix-search'. + (when (> cfd-continue-pos cfd-token-pos) + (c-forward-syntactic-ws) + (setq cfd-token-pos (point))) + + ;; Continue if the following token fails the + ;; CFD-DECL-RE and CFD-FACE-CHECKLIST checks. + (when (or (>= (point) cfd-limit) + (not (looking-at cfd-decl-re)) + (and cfd-face-checklist + (not (c-got-face-at + (point) cfd-face-checklist)))) + (goto-char cfd-continue-pos) + t))) + + (< (point) cfd-limit)) ; end of "false matches" condition + (c-find-decl-prefix-search)) ; end of "false matches" loop + + (< (point) cfd-limit)) ; end of condition for "decl-spot" while + + (when (and + (>= (point) cfd-start-pos) + + (progn + ;; Narrow to the end of the macro if we got a hit inside + ;; one, to avoid recognizing things that start inside the + ;; macro and end outside it. + (when (> cfd-match-pos cfd-macro-end) + ;; Not in the same macro as in the previous round. + (save-excursion + (goto-char cfd-match-pos) + (setq cfd-macro-end + (if (save-excursion (and (c-beginning-of-macro) + (< (point) cfd-match-pos))) + (progn (c-end-of-macro) + (point)) + 0)))) + + (if (zerop cfd-macro-end) + t + (if (> cfd-macro-end (point)) + (progn (narrow-to-region (point-min) cfd-macro-end) + t) + ;; The matched token was the last thing in the macro, + ;; so the whole match is bogus. + (setq cfd-macro-end 0) + nil)))) ; end of when condition + + (c-debug-put-decl-spot-faces cfd-match-pos (point)) + (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0)) + (setq cfd-prop-match nil)) + + (when (/= cfd-macro-end 0) + ;; Restore limits if we did macro narrowment above. + (narrow-to-region (point-min) cfd-buffer-end))) + + (goto-char cfd-continue-pos) + (if (= cfd-continue-pos cfd-limit) + (setq cfd-match-pos cfd-limit) + (c-find-decl-prefix-search))))) ; Moves point, sets cfd-continue-pos, + ; cfd-match-pos, etc. + + +;; A cache for found types. + +;; Buffer local variable that contains an obarray with the types we've +;; found. If a declaration is recognized somewhere we record the +;; fully qualified identifier in it to recognize it as a type +;; elsewhere in the file too. This is not accurate since we do not +;; bother with the scoping rules of the languages, but in practice the +;; same name is seldom used as both a type and something else in a +;; file, and we only use this as a last resort in ambiguous cases (see +;; `c-forward-decl-or-cast-1'). +;; +;; Not every type need be in this cache. However, things which have +;; ceased to be types must be removed from it. +;; +;; Template types in C++ are added here too but with the template +;; arglist replaced with "<>" in references or "<" for the one in the +;; primary type. E.g. the type "Foo::Bar" is stored as +;; "Foo<>::Bar<". This avoids storing very long strings (since C++ +;; template specs can be fairly sized programs in themselves) and +;; improves the hit ratio (it's a type regardless of the template +;; args; it's just not the same type, but we're only interested in +;; recognizing types, not telling distinct types apart). Note that +;; template types in references are added here too; from the example +;; above there will also be an entry "Foo<". +(defvar c-found-types nil) +(make-variable-buffer-local 'c-found-types) + +(defsubst c-clear-found-types () + ;; Clears `c-found-types'. + (setq c-found-types (make-vector 53 0))) + +(defun c-add-type (from to) + ;; Add the given region as a type in `c-found-types'. If the region + ;; doesn't match an existing type but there is a type which is equal + ;; to the given one except that the last character is missing, then + ;; the shorter type is removed. That's done to avoid adding all + ;; prefixes of a type as it's being entered and font locked. This + ;; doesn't cover cases like when characters are removed from a type + ;; or added in the middle. We'd need the position of point when the + ;; font locking is invoked to solve this well. + ;; + ;; This function might do hidden buffer changes. + (let ((type (c-syntactic-content from to c-recognize-<>-arglists))) + (unless (intern-soft type c-found-types) + (unintern (substring type 0 -1) c-found-types) + (intern type c-found-types)))) + +(defun c-unfind-type (name) + ;; Remove the "NAME" from c-found-types, if present. + (unintern name c-found-types)) + +(defsubst c-check-type (from to) + ;; Return non-nil if the given region contains a type in + ;; `c-found-types'. + ;; + ;; This function might do hidden buffer changes. + (intern-soft (c-syntactic-content from to c-recognize-<>-arglists) + c-found-types)) + +(defun c-list-found-types () + ;; Return all the types in `c-found-types' as a sorted list of + ;; strings. + (let (type-list) + (mapatoms (lambda (type) + (setq type-list (cons (symbol-name type) + type-list))) + c-found-types) + (sort type-list 'string-lessp))) + +(defun c-trim-found-types (beg end old-len) + ;; An after change function which, in conjunction with the info in + ;; c-maybe-stale-found-type (set in c-before-change), removes a type + ;; from `c-found-types', should this type have become stale. For + ;; example, this happens to "foo" when "foo \n bar();" becomes + ;; "foo(); \n bar();". Such stale types, if not removed, foul up + ;; the fontification. + ;; + ;; Have we, perhaps, added non-ws characters to the front/back of a found + ;; type? + (when (> end beg) + (save-excursion + (when (< end (point-max)) + (goto-char end) + (if (and (c-beginning-of-current-token) ; only moves when we started in the middle + (progn (goto-char end) + (c-end-of-current-token))) + (c-unfind-type (buffer-substring-no-properties + end (point))))) + (when (> beg (point-min)) + (goto-char beg) + (if (and (c-end-of-current-token) ; only moves when we started in the middle + (progn (goto-char beg) + (c-beginning-of-current-token))) + (c-unfind-type (buffer-substring-no-properties + (point) beg)))))) + + (if c-maybe-stale-found-type ; e.g. (c-decl-id-start "foo" 97 107 " (* ooka) " "o") + (cond + ;; Changing the amount of (already existing) whitespace - don't do anything. + ((and (c-partial-ws-p beg end) + (or (= beg end) ; removal of WS + (string-match "^[ \t\n\r\f\v]*$" (nth 5 c-maybe-stale-found-type))))) + + ;; The syntactic relationship which defined a "found type" has been + ;; destroyed. + ((eq (car c-maybe-stale-found-type) 'c-decl-id-start) + (c-unfind-type (cadr c-maybe-stale-found-type))) +;; ((eq (car c-maybe-stale-found-type) 'c-decl-type-start) FIXME!!! + ))) + + +;; Setting and removing syntax properties on < and > in languages (C++ +;; and Java) where they can be template/generic delimiters as well as +;; their normal meaning of "less/greater than". + +;; Normally, < and > have syntax 'punctuation'. When they are found to +;; be delimiters, they are marked as such with the category properties +;; c-<-as-paren-syntax, c->-as-paren-syntax respectively. + +;; STRATEGY: +;; +;; It is impossible to determine with certainty whether a <..> pair in +;; C++ is two comparison operators or is template delimiters, unless +;; one duplicates a lot of a C++ compiler. For example, the following +;; code fragment: +;; +;; foo (a < b, c > d) ; +;; +;; could be a function call with two integer parameters (each a +;; relational expression), or it could be a constructor for class foo +;; taking one parameter d of templated type "a < b, c >". They are +;; somewhat easier to distinguish in Java. +;; +;; The strategy now (2010-01) adopted is to mark and unmark < and +;; > IN MATCHING PAIRS ONLY. [Previously, they were marked +;; individually when their context so indicated. This gave rise to +;; intractible problems when one of a matching pair was deleted, or +;; pulled into a literal.] +;; +;; At each buffer change, the syntax-table properties are removed in a +;; before-change function and reapplied, when needed, in an +;; after-change function. It is far more important that the +;; properties get removed when they they are spurious than that they +;; be present when wanted. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defun c-clear-<-pair-props (&optional pos) + ;; POS (default point) is at a < character. If it is marked with + ;; open paren syntax-table text property, remove the property, + ;; together with the close paren property on the matching > (if + ;; any). + (save-excursion + (if pos + (goto-char pos) + (setq pos (point))) + (when (equal (c-get-char-property (point) 'syntax-table) + c-<-as-paren-syntax) + (with-syntax-table c-no-parens-syntax-table ; ignore unbalanced [,{,(,.. + (c-go-list-forward)) + (when (equal (c-get-char-property (1- (point)) 'syntax-table) + c->-as-paren-syntax) ; should always be true. + (c-unmark-<->-as-paren (1- (point)))) + (c-unmark-<->-as-paren pos)))) + +(defun c-clear->-pair-props (&optional pos) + ;; POS (default point) is at a > character. If it is marked with + ;; close paren syntax-table property, remove the property, together + ;; with the open paren property on the matching < (if any). + (save-excursion + (if pos + (goto-char pos) + (setq pos (point))) + (when (equal (c-get-char-property (point) 'syntax-table) + c->-as-paren-syntax) + (with-syntax-table c-no-parens-syntax-table ; ignore unbalanced [,{,(,.. + (c-go-up-list-backward)) + (when (equal (c-get-char-property (point) 'syntax-table) + c-<-as-paren-syntax) ; should always be true. + (c-unmark-<->-as-paren (point))) + (c-unmark-<->-as-paren (point))))) + +(defun c-clear-<>-pair-props (&optional pos) + ;; POS (default point) is at a < or > character. If it has an + ;; open/close paren syntax-table property, remove this property both + ;; from the current character and its partner (which will also be + ;; thusly marked). + (cond + ((eq (char-after) ?\<) + (c-clear-<-pair-props pos)) + ((eq (char-after) ?\>) + (c-clear->-pair-props pos)) + (t (c-benign-error + "c-clear-<>-pair-props called from wrong position")))) + +(defun c-clear-<-pair-props-if-match-after (lim &optional pos) + ;; POS (default point) is at a < character. If it is both marked + ;; with open/close paren syntax-table property, and has a matching > + ;; (also marked) which is after LIM, remove the property both from + ;; the current > and its partner. Return t when this happens, nil + ;; when it doesn't. + (save-excursion + (if pos + (goto-char pos) + (setq pos (point))) + (when (equal (c-get-char-property (point) 'syntax-table) + c-<-as-paren-syntax) + (with-syntax-table c-no-parens-syntax-table ; ignore unbalanced [,{,(,.. + (c-go-list-forward)) + (when (and (>= (point) lim) + (equal (c-get-char-property (1- (point)) 'syntax-table) + c->-as-paren-syntax)) ; should always be true. + (c-unmark-<->-as-paren (1- (point))) + (c-unmark-<->-as-paren pos)) + t))) + +(defun c-clear->-pair-props-if-match-before (lim &optional pos) + ;; POS (default point) is at a > character. If it is both marked + ;; with open/close paren syntax-table property, and has a matching < + ;; (also marked) which is before LIM, remove the property both from + ;; the current < and its partner. Return t when this happens, nil + ;; when it doesn't. + (save-excursion + (if pos + (goto-char pos) + (setq pos (point))) + (when (equal (c-get-char-property (point) 'syntax-table) + c->-as-paren-syntax) + (with-syntax-table c-no-parens-syntax-table ; ignore unbalanced [,{,(,.. + (c-go-up-list-backward)) + (when (and (<= (point) lim) + (equal (c-get-char-property (point) 'syntax-table) + c-<-as-paren-syntax)) ; should always be true. + (c-unmark-<->-as-paren (point)) + (c-unmark-<->-as-paren pos)) + t))) + +(defun c-before-change-check-<>-operators (beg end) + ;; Unmark certain pairs of "< .... >" which are currently marked as + ;; template/generic delimiters. (This marking is via syntax-table + ;; text properties). + ;; + ;; These pairs are those which are in the current "statement" (i.e., + ;; the region between the {, }, or ; before BEG and the one after + ;; END), and which enclose any part of the interval (BEG END). + ;; + ;; Note that in C++ (?and Java), template/generic parens cannot + ;; enclose a brace or semicolon, so we use these as bounds on the + ;; region we must work on. + ;; + ;; This function is called from before-change-functions (via + ;; c-get-state-before-change-functions). Thus the buffer is widened, + ;; and point is undefined, both at entry and exit. + ;; + ;; FIXME!!! This routine ignores the possibility of macros entirely. + ;; 2010-01-29. + (save-excursion + (let ((beg-lit-limits (progn (goto-char beg) (c-literal-limits))) + (end-lit-limits (progn (goto-char end) (c-literal-limits))) + new-beg new-end need-new-beg need-new-end) + ;; Locate the barrier before the changed region + (goto-char (if beg-lit-limits (car beg-lit-limits) beg)) + (c-syntactic-skip-backward "^;{}" (c-determine-limit 512)) + (setq new-beg (point)) + + ;; Remove the syntax-table/category properties from each pertinent <...> + ;; pair. Firsly, the ones with the < before beg and > after beg. + (while + (c-search-forward-char-property 'syntax-table c-<-as-paren-syntax beg) + (if (c-clear-<-pair-props-if-match-after beg (1- (point))) + (setq need-new-beg t))) + + ;; Locate the barrier after END. + (goto-char (if end-lit-limits (cdr end-lit-limits) end)) + (c-syntactic-re-search-forward "[;{}]" (c-determine-+ve-limit 512) 'end) + (setq new-end (point)) + + ;; Remove syntax-table properties from the remaining pertinent <...> + ;; pairs, those with a > after end and < before end. + (while (c-search-backward-char-property 'syntax-table c->-as-paren-syntax end) + (if (c-clear->-pair-props-if-match-before end) + (setq need-new-end t))) + + ;; Extend the fontification region, if needed. + (when need-new-beg + (goto-char new-beg) + (c-forward-syntactic-ws) + (and (< (point) c-new-BEG) (setq c-new-BEG (point)))) + + (when need-new-end + (and (> new-end c-new-END) (setq c-new-END new-end)))))) + +(defun c-after-change-check-<>-operators (beg end) + ;; This is called from `after-change-functions' when + ;; c-recognize-<>-arglists' is set. It ensures that no "<" or ">" + ;; chars with paren syntax become part of another operator like "<<" + ;; or ">=". + ;; + ;; This function might do hidden buffer changes. + + (save-excursion + (goto-char beg) + (when (or (looking-at "[<>]") + (< (skip-chars-backward "<>") 0)) + + (goto-char beg) + (c-beginning-of-current-token) + (when (and (< (point) beg) + (looking-at c-<>-multichar-token-regexp) + (< beg (setq beg (match-end 0)))) + (while (progn (skip-chars-forward "^<>" beg) + (< (point) beg)) + (c-clear-<>-pair-props) + (forward-char)))) + + (when (< beg end) + (goto-char end) + (when (or (looking-at "[<>]") + (< (skip-chars-backward "<>") 0)) + + (goto-char end) + (c-beginning-of-current-token) + (when (and (< (point) end) + (looking-at c-<>-multichar-token-regexp) + (< end (setq end (match-end 0)))) + (while (progn (skip-chars-forward "^<>" end) + (< (point) end)) + (c-clear-<>-pair-props) + (forward-char))))))) + + + +;; Handling of small scale constructs like types and names. + +;; Dynamically bound variable that instructs `c-forward-type' to also +;; treat possible types (i.e. those that it normally returns 'maybe or +;; 'found for) as actual types (and always return 'found for them). +;; This means that it records them in `c-record-type-identifiers' if +;; that is set, and that it adds them to `c-found-types'. +(defvar c-promote-possible-types nil) + +;; Dynamically bound variable that instructs `c-forward-<>-arglist' to +;; mark up successfully parsed arglists with paren syntax properties on +;; the surrounding angle brackets and with `c-<>-arg-sep' in the +;; `c-type' property of each argument separating comma. +;; +;; Setting this variable also makes `c-forward-<>-arglist' recurse into +;; all arglists for side effects (i.e. recording types), otherwise it +;; exploits any existing paren syntax properties to quickly jump to the +;; end of already parsed arglists. +;; +;; Marking up the arglists is not the default since doing that correctly +;; depends on a proper value for `c-restricted-<>-arglists'. +(defvar c-parse-and-markup-<>-arglists nil) + +;; Dynamically bound variable that instructs `c-forward-<>-arglist' to +;; not accept arglists that contain binary operators. +;; +;; This is primarily used to handle C++ template arglists. C++ +;; disambiguates them by checking whether the preceding name is a +;; template or not. We can't do that, so we assume it is a template +;; if it can be parsed as one. That usually works well since +;; comparison expressions on the forms "a < b > c" or "a < b, c > d" +;; in almost all cases would be pointless. +;; +;; However, in function arglists, e.g. in "foo (a < b, c > d)", we +;; should let the comma separate the function arguments instead. And +;; in a context where the value of the expression is taken, e.g. in +;; "if (a < b || c > d)", it's probably not a template. +(defvar c-restricted-<>-arglists nil) + +;; Dynamically bound variables that instructs +;; `c-forward-keyword-clause', `c-forward-<>-arglist', +;; `c-forward-name', `c-forward-type', `c-forward-decl-or-cast-1', and +;; `c-forward-label' to record the ranges of all the type and +;; reference identifiers they encounter. They will build lists on +;; these variables where each element is a cons of the buffer +;; positions surrounding each identifier. This recording is only +;; activated when `c-record-type-identifiers' is non-nil. +;; +;; All known types that can't be identifiers are recorded, and also +;; other possible types if `c-promote-possible-types' is set. +;; Recording is however disabled inside angle bracket arglists that +;; are encountered inside names and other angle bracket arglists. +;; Such occurrences are taken care of by `c-font-lock-<>-arglists' +;; instead. +;; +;; Only the names in C++ template style references (e.g. "tmpl" in +;; "tmpl::foo") are recorded as references, other references +;; aren't handled here. +;; +;; `c-forward-label' records the label identifier(s) on +;; `c-record-ref-identifiers'. +(defvar c-record-type-identifiers nil) +(defvar c-record-ref-identifiers nil) + +;; This variable will receive a cons cell of the range of the last +;; single identifier symbol stepped over by `c-forward-name' if it's +;; successful. This is the range that should be put on one of the +;; record lists above by the caller. It's assigned nil if there's no +;; such symbol in the name. +(defvar c-last-identifier-range nil) + +(defmacro c-record-type-id (range) + (if (eq (car-safe range) 'cons) + ;; Always true. + `(setq c-record-type-identifiers + (cons ,range c-record-type-identifiers)) + `(let ((range ,range)) + (if range + (setq c-record-type-identifiers + (cons range c-record-type-identifiers)))))) + +(defmacro c-record-ref-id (range) + (if (eq (car-safe range) 'cons) + ;; Always true. + `(setq c-record-ref-identifiers + (cons ,range c-record-ref-identifiers)) + `(let ((range ,range)) + (if range + (setq c-record-ref-identifiers + (cons range c-record-ref-identifiers)))))) + +;; Dynamically bound variable that instructs `c-forward-type' to +;; record the ranges of types that only are found. Behaves otherwise +;; like `c-record-type-identifiers'. +(defvar c-record-found-types nil) + +(defmacro c-forward-keyword-prefixed-id (type) + ;; Used internally in `c-forward-keyword-clause' to move forward + ;; over a type (if TYPE is 'type) or a name (otherwise) which + ;; possibly is prefixed by keywords and their associated clauses. + ;; Try with a type/name first to not trip up on those that begin + ;; with a keyword. Return t if a known or found type is moved + ;; over. The point is clobbered if nil is returned. If range + ;; recording is enabled, the identifier is recorded on as a type + ;; if TYPE is 'type or as a reference if TYPE is 'ref. + ;; + ;; This macro might do hidden buffer changes. + `(let (res) + (while (if (setq res ,(if (eq type 'type) + `(c-forward-type) + `(c-forward-name))) + nil + (and (looking-at c-keywords-regexp) + (c-forward-keyword-clause 1)))) + (when (memq res '(t known found prefix)) + ,(when (eq type 'ref) + `(when c-record-type-identifiers + (c-record-ref-id c-last-identifier-range))) + t))) + +(defmacro c-forward-id-comma-list (type update-safe-pos) + ;; Used internally in `c-forward-keyword-clause' to move forward + ;; over a comma separated list of types or names using + ;; `c-forward-keyword-prefixed-id'. + ;; + ;; This macro might do hidden buffer changes. + `(while (and (progn + ,(when update-safe-pos + `(setq safe-pos (point))) + (eq (char-after) ?,)) + (progn + (forward-char) + (c-forward-syntactic-ws) + (c-forward-keyword-prefixed-id ,type))))) + +(defun c-forward-keyword-clause (match) + ;; Submatch MATCH in the current match data is assumed to surround a + ;; token. If it's a keyword, move over it and any immediately + ;; following clauses associated with it, stopping at the start of + ;; the next token. t is returned in that case, otherwise the point + ;; stays and nil is returned. The kind of clauses that are + ;; recognized are those specified by `c-type-list-kwds', + ;; `c-ref-list-kwds', `c-colon-type-list-kwds', + ;; `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds', + ;; and `c-<>-arglist-kwds'. + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; Note that for `c-colon-type-list-kwds', which doesn't necessary + ;; apply directly after the keyword, the type list is moved over + ;; only when there is no unaccounted token before it (i.e. a token + ;; that isn't moved over due to some other keyword list). The + ;; identifier ranges in the list are still recorded if that should + ;; be done, though. + ;; + ;; This function might do hidden buffer changes. + + (let ((kwd-sym (c-keyword-sym (match-string match))) safe-pos pos + ;; The call to `c-forward-<>-arglist' below is made after + ;; `c-<>-sexp-kwds' keywords, so we're certain they actually + ;; are angle bracket arglists and `c-restricted-<>-arglists' + ;; should therefore be nil. + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists) + + (when kwd-sym + (goto-char (match-end match)) + (c-forward-syntactic-ws) + (setq safe-pos (point)) + + (cond + ((and (c-keyword-member kwd-sym 'c-type-list-kwds) + (c-forward-keyword-prefixed-id type)) + ;; There's a type directly after a keyword in `c-type-list-kwds'. + (c-forward-id-comma-list type t)) + + ((and (c-keyword-member kwd-sym 'c-ref-list-kwds) + (c-forward-keyword-prefixed-id ref)) + ;; There's a name directly after a keyword in `c-ref-list-kwds'. + (c-forward-id-comma-list ref t)) + + ((and (c-keyword-member kwd-sym 'c-paren-any-kwds) + (eq (char-after) ?\()) + ;; There's an open paren after a keyword in `c-paren-any-kwds'. + + (forward-char) + (when (and (setq pos (c-up-list-forward)) + (eq (char-before pos) ?\))) + (when (and c-record-type-identifiers + (c-keyword-member kwd-sym 'c-paren-type-kwds)) + ;; Use `c-forward-type' on every identifier we can find + ;; inside the paren, to record the types. + (while (c-syntactic-re-search-forward c-symbol-start pos t) + (goto-char (match-beginning 0)) + (unless (c-forward-type) + (looking-at c-symbol-key) ; Always matches. + (goto-char (match-end 0))))) + + (goto-char pos) + (c-forward-syntactic-ws) + (setq safe-pos (point)))) + + ((and (c-keyword-member kwd-sym 'c-<>-sexp-kwds) + (eq (char-after) ?<) + (c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds))) + (c-forward-syntactic-ws) + (setq safe-pos (point))) + + ((and (c-keyword-member kwd-sym 'c-nonsymbol-sexp-kwds) + (not (looking-at c-symbol-start)) + (c-safe (c-forward-sexp) t)) + (c-forward-syntactic-ws) + (setq safe-pos (point)))) + + (when (c-keyword-member kwd-sym 'c-colon-type-list-kwds) + (if (eq (char-after) ?:) + ;; If we are at the colon already, we move over the type + ;; list after it. + (progn + (forward-char) + (c-forward-syntactic-ws) + (when (c-forward-keyword-prefixed-id type) + (c-forward-id-comma-list type t))) + ;; Not at the colon, so stop here. But the identifier + ;; ranges in the type list later on should still be + ;; recorded. + (and c-record-type-identifiers + (progn + ;; If a keyword matched both one of the types above and + ;; this one, we match `c-colon-type-list-re' after the + ;; clause matched above. + (goto-char safe-pos) + (looking-at c-colon-type-list-re)) + (progn + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + (c-forward-keyword-prefixed-id type)) + ;; There's a type after the `c-colon-type-list-re' match + ;; after a keyword in `c-colon-type-list-kwds'. + (c-forward-id-comma-list type nil)))) + + (goto-char safe-pos) + t))) + + +(defun c-forward-<>-arglist (all-types) + ;; The point is assumed to be at a "<". Try to treat it as the open + ;; paren of an angle bracket arglist and move forward to the the + ;; corresponding ">". If successful, the point is left after the + ;; ">" and t is returned, otherwise the point isn't moved and nil is + ;; returned. If ALL-TYPES is t then all encountered arguments in + ;; the arglist that might be types are treated as found types. + ;; + ;; The variable `c-parse-and-markup-<>-arglists' controls how this + ;; function handles text properties on the angle brackets and argument + ;; separating commas. + ;; + ;; `c-restricted-<>-arglists' controls how lenient the template + ;; arglist recognition should be. + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let ((start (point)) + ;; If `c-record-type-identifiers' is set then activate + ;; recording of any found types that constitute an argument in + ;; the arglist. + (c-record-found-types (if c-record-type-identifiers t))) + (if (catch 'angle-bracket-arglist-escape + (setq c-record-found-types + (c-forward-<>-arglist-recur all-types))) + (progn + (when (consp c-record-found-types) + (setq c-record-type-identifiers + ;; `nconc' doesn't mind that the tail of + ;; `c-record-found-types' is t. + (nconc c-record-found-types c-record-type-identifiers))) + (if (c-major-mode-is 'java-mode) (c-fontify-recorded-types-and-refs)) + t) + + (goto-char start) + nil))) + +(defun c-forward-<>-arglist-recur (all-types) + ;; Recursive part of `c-forward-<>-arglist'. + ;; + ;; This function might do hidden buffer changes. + (let ((start (point)) res pos tmp + ;; Cover this so that any recorded found type ranges are + ;; automatically lost if it turns out to not be an angle + ;; bracket arglist. It's propagated through the return value + ;; on successful completion. + (c-record-found-types c-record-found-types) + ;; List that collects the positions after the argument + ;; separating ',' in the arglist. + arg-start-pos) + ;; If the '<' has paren open syntax then we've marked it as an angle + ;; bracket arglist before, so skip to the end. + (if (and (not c-parse-and-markup-<>-arglists) + (c-get-char-property (point) 'syntax-table)) + + (progn + (forward-char) + (if (and (c-go-up-list-forward) + (eq (char-before) ?>)) + t + ;; Got unmatched paren angle brackets. We don't clear the paren + ;; syntax properties and retry, on the basis that it's very + ;; unlikely that paren angle brackets become operators by code + ;; manipulation. It's far more likely that it doesn't match due + ;; to narrowing or some temporary change. + (goto-char start) + nil)) + + (forward-char) ; Forward over the opening '<'. + + (unless (looking-at c-<-op-cont-regexp) + ;; go forward one non-alphanumeric character (group) per iteration of + ;; this loop. + (while (and + (progn + (c-forward-syntactic-ws) + (when (or (and c-record-type-identifiers all-types) + (c-major-mode-is 'java-mode)) + ;; All encountered identifiers are types, so set the + ;; promote flag and parse the type. + (progn + (c-forward-syntactic-ws) + (if (looking-at "\\?") + (forward-char) + (when (looking-at c-identifier-start) + (let ((c-promote-possible-types t) + (c-record-found-types t)) + (c-forward-type)))) + + (c-forward-syntactic-ws) + + (when (or (looking-at "extends") + (looking-at "super")) + (forward-word) + (c-forward-syntactic-ws) + (let ((c-promote-possible-types t) + (c-record-found-types t)) + (c-forward-type) + (c-forward-syntactic-ws))))) + + (setq pos (point)) ; e.g. first token inside the '<' + + ;; Note: These regexps exploit the match order in \| so + ;; that "<>" is matched by "<" rather than "[^>:-]>". + (c-syntactic-re-search-forward + ;; Stop on ',', '|', '&', '+' and '-' to catch + ;; common binary operators that could be between + ;; two comparison expressions "ad". + "[<;{},|+&-]\\|[>)]" + nil t t)) + + (cond + ((eq (char-before) ?>) + ;; Either an operator starting with '>' or the end of + ;; the angle bracket arglist. + + (if (looking-at c->-op-cont-regexp) + (progn + (goto-char (match-end 0)) + t) ; Continue the loop. + + ;; The angle bracket arglist is finished. + (when c-parse-and-markup-<>-arglists + (while arg-start-pos + (c-put-c-type-property (1- (car arg-start-pos)) + 'c-<>-arg-sep) + (setq arg-start-pos (cdr arg-start-pos))) + (c-mark-<-as-paren start) + (c-mark->-as-paren (1- (point)))) + (setq res t) + nil)) ; Exit the loop. + + ((eq (char-before) ?<) + ;; Either an operator starting with '<' or a nested arglist. + (setq pos (point)) + (let (id-start id-end subres keyword-match) + (cond + ;; The '<' begins a multi-char operator. + ((looking-at c-<-op-cont-regexp) + (setq tmp (match-end 0)) + (goto-char (match-end 0))) + ;; We're at a nested <.....> + ((progn + (setq tmp pos) + (backward-char) ; to the '<' + (and + (save-excursion + ;; There's always an identifier before an angle + ;; bracket arglist, or a keyword in `c-<>-type-kwds' + ;; or `c-<>-arglist-kwds'. + (c-backward-syntactic-ws) + (setq id-end (point)) + (c-simple-skip-symbol-backward) + (when (or (setq keyword-match + (looking-at c-opt-<>-sexp-key)) + (not (looking-at c-keywords-regexp))) + (setq id-start (point)))) + (setq subres + (let ((c-promote-possible-types t) + (c-record-found-types t)) + (c-forward-<>-arglist-recur + (and keyword-match + (c-keyword-member + (c-keyword-sym (match-string 1)) + 'c-<>-type-kwds))))))) + ;; It was an angle bracket arglist. + (setq c-record-found-types subres) + + ;; Record the identifier before the template as a type + ;; or reference depending on whether the arglist is last + ;; in a qualified identifier. + (when (and c-record-type-identifiers + (not keyword-match)) + (if (and c-opt-identifier-concat-key + (progn + (c-forward-syntactic-ws) + (looking-at c-opt-identifier-concat-key))) + (c-record-ref-id (cons id-start id-end)) + (c-record-type-id (cons id-start id-end))))) + + ;; At a "less than" operator. + (t + (forward-char) + ))) + t) ; carry on looping. + + ((and (not c-restricted-<>-arglists) + (or (and (eq (char-before) ?&) + (not (eq (char-after) ?&))) + (eq (char-before) ?,))) + ;; Just another argument. Record the position. The + ;; type check stuff that made us stop at it is at + ;; the top of the loop. + (setq arg-start-pos (cons (point) arg-start-pos))) + + (t + ;; Got a character that can't be in an angle bracket + ;; arglist argument. Abort using `throw', since + ;; it's useless to try to find a surrounding arglist + ;; if we're nested. + (throw 'angle-bracket-arglist-escape nil)))))) + (if res + (or c-record-found-types t))))) + +(defun c-backward-<>-arglist (all-types &optional limit) + ;; The point is assumed to be directly after a ">". Try to treat it + ;; as the close paren of an angle bracket arglist and move back to + ;; the corresponding "<". If successful, the point is left at + ;; the "<" and t is returned, otherwise the point isn't moved and + ;; nil is returned. ALL-TYPES is passed on to + ;; `c-forward-<>-arglist'. + ;; + ;; If the optional LIMIT is given, it bounds the backward search. + ;; It's then assumed to be at a syntactically relevant position. + ;; + ;; This is a wrapper around `c-forward-<>-arglist'. See that + ;; function for more details. + + (let ((start (point))) + (backward-char) + (if (and (not c-parse-and-markup-<>-arglists) + (c-get-char-property (point) 'syntax-table)) + + (if (and (c-go-up-list-backward) + (eq (char-after) ?<)) + t + ;; See corresponding note in `c-forward-<>-arglist'. + (goto-char start) + nil) + + (while (progn + (c-syntactic-skip-backward "^<;{}" limit t) + + (and + (if (eq (char-before) ?<) + t + ;; Stopped at bob or a char that isn't allowed in an + ;; arglist, so we've failed. + (goto-char start) + nil) + + (if (> (point) + (progn (c-beginning-of-current-token) + (point))) + ;; If we moved then the "<" was part of some + ;; multicharacter token. + t + + (backward-char) + (let ((beg-pos (point))) + (if (c-forward-<>-arglist all-types) + (cond ((= (point) start) + ;; Matched the arglist. Break the while. + (goto-char beg-pos) + nil) + ((> (point) start) + ;; We started from a non-paren ">" inside an + ;; arglist. + (goto-char start) + nil) + (t + ;; Matched a shorter arglist. Can be a nested + ;; one so continue looking. + (goto-char beg-pos) + t)) + t)))))) + + (/= (point) start)))) + +(defun c-forward-name () + ;; Move forward over a complete name if at the beginning of one, + ;; stopping at the next following token. A keyword, as such, + ;; doesn't count as a name. If the point is not at something that + ;; is recognized as a name then it stays put. + ;; + ;; A name could be something as simple as "foo" in C or something as + ;; complex as "X::B, BIT_MAX >> b>, ::operator<> :: + ;; Z<(a>b)> :: operator const X<&foo>::T Q::G::*volatile const" in C++ (this function is actually little + ;; more than a `looking-at' call in all modes except those that, + ;; like C++, have `c-recognize-<>-arglists' set). + ;; + ;; Return + ;; o - nil if no name is found; + ;; o - 'template if it's an identifier ending with an angle bracket + ;; arglist; + ;; o - 'operator of it's an operator identifier; + ;; o - t if it's some other kind of name. + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let ((pos (point)) (start (point)) res id-start id-end + ;; Turn off `c-promote-possible-types' here since we might + ;; call `c-forward-<>-arglist' and we don't want it to promote + ;; every suspect thing in the arglist to a type. We're + ;; typically called from `c-forward-type' in this case, and + ;; the caller only wants the top level type that it finds to + ;; be promoted. + c-promote-possible-types) + (while + (and + (looking-at c-identifier-key) + + (progn + ;; Check for keyword. We go to the last symbol in + ;; `c-identifier-key' first. + (goto-char (setq id-end (match-end 0))) + (c-simple-skip-symbol-backward) + (setq id-start (point)) + + (if (looking-at c-keywords-regexp) + (when (and (c-major-mode-is 'c++-mode) + (looking-at + (cc-eval-when-compile + (concat "\\(operator\\|\\(template\\)\\)" + "\\(" (c-lang-const c-nonsymbol-key c++) + "\\|$\\)"))) + (if (match-beginning 2) + ;; "template" is only valid inside an + ;; identifier if preceded by "::". + (save-excursion + (c-backward-syntactic-ws) + (and (c-safe (backward-char 2) t) + (looking-at "::"))) + t)) + + ;; Handle a C++ operator or template identifier. + (goto-char id-end) + (c-forward-syntactic-ws) + (cond ((eq (char-before id-end) ?e) + ;; Got "... ::template". + (let ((subres (c-forward-name))) + (when subres + (setq pos (point) + res subres)))) + + ((looking-at c-identifier-start) + ;; Got a cast operator. + (when (c-forward-type) + (setq pos (point) + res 'operator) + ;; Now we should match a sequence of either + ;; '*', '&' or a name followed by ":: *", + ;; where each can be followed by a sequence + ;; of `c-opt-type-modifier-key'. + (while (cond ((looking-at "[*&]") + (goto-char (match-end 0)) + t) + ((looking-at c-identifier-start) + (and (c-forward-name) + (looking-at "::") + (progn + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + (eq (char-after) ?*)) + (progn + (forward-char) + t)))) + (while (progn + (c-forward-syntactic-ws) + (setq pos (point)) + (looking-at c-opt-type-modifier-key)) + (goto-char (match-end 1)))))) + + ((looking-at c-overloadable-operators-regexp) + ;; Got some other operator. + (setq c-last-identifier-range + (cons (point) (match-end 0))) + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + (setq pos (point) + res 'operator))) + + nil) + + ;; `id-start' is equal to `id-end' if we've jumped over + ;; an identifier that doesn't end with a symbol token. + ;; That can occur e.g. for Java import directives on the + ;; form "foo.bar.*". + (when (and id-start (/= id-start id-end)) + (setq c-last-identifier-range + (cons id-start id-end))) + (goto-char id-end) + (c-forward-syntactic-ws) + (setq pos (point) + res t))) + + (progn + (goto-char pos) + (when (or c-opt-identifier-concat-key + c-recognize-<>-arglists) + + (cond + ((and c-opt-identifier-concat-key + (looking-at c-opt-identifier-concat-key)) + ;; Got a concatenated identifier. This handles the + ;; cases with tricky syntactic whitespace that aren't + ;; covered in `c-identifier-key'. + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + t) + + ((and c-recognize-<>-arglists + (eq (char-after) ?<)) + ;; Maybe an angle bracket arglist. + (when (let ((c-record-type-identifiers t) + (c-record-found-types t)) + (c-forward-<>-arglist nil)) + + (c-add-type start (1+ pos)) + (c-forward-syntactic-ws) + (setq pos (point) + c-last-identifier-range nil) + + (if (and c-opt-identifier-concat-key + (looking-at c-opt-identifier-concat-key)) + + ;; Continue if there's an identifier concatenation + ;; operator after the template argument. + (progn + (when (and c-record-type-identifiers id-start) + (c-record-ref-id (cons id-start id-end))) + (forward-char 2) + (c-forward-syntactic-ws) + t) + + (when (and c-record-type-identifiers id-start) + (c-record-type-id (cons id-start id-end))) + (setq res 'template) + nil))) + ))))) + + (goto-char pos) + res)) + +(defun c-forward-type (&optional brace-block-too) + ;; Move forward over a type spec if at the beginning of one, + ;; stopping at the next following token. The keyword "typedef" + ;; isn't part of a type spec here. + ;; + ;; BRACE-BLOCK-TOO, when non-nil, means move over the brace block in + ;; constructs like "struct foo {...} bar ;" or "struct {...} bar;". + ;; The current (2009-03-10) intention is to convert all uses of + ;; `c-forward-type' to call with this parameter set, then to + ;; eliminate it. + ;; + ;; Return + ;; o - t if it's a known type that can't be a name or other + ;; expression; + ;; o - 'known if it's an otherwise known type (according to + ;; `*-font-lock-extra-types'); + ;; o - 'prefix if it's a known prefix of a type; + ;; o - 'found if it's a type that matches one in `c-found-types'; + ;; o - 'maybe if it's an identfier that might be a type; or + ;; o - nil if it can't be a type (the point isn't moved then). + ;; + ;; The point is assumed to be at the beginning of a token. + ;; + ;; Note that this function doesn't skip past the brace definition + ;; that might be considered part of the type, e.g. + ;; "enum {a, b, c} foo". + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + (when (and c-recognize-<>-arglists + (looking-at "<")) + (c-forward-<>-arglist t) + (c-forward-syntactic-ws)) + + (let ((start (point)) pos res name-res id-start id-end id-range) + + ;; Skip leading type modifiers. If any are found we know it's a + ;; prefix of a type. + (when c-opt-type-modifier-key ; e.g. "const" "volatile", but NOT "typedef" + (while (looking-at c-opt-type-modifier-key) + (goto-char (match-end 1)) + (c-forward-syntactic-ws) + (setq res 'prefix))) + + (cond + ((looking-at c-type-prefix-key) ; e.g. "struct", "class", but NOT + ; "typedef". + (goto-char (match-end 1)) + (c-forward-syntactic-ws) + (setq pos (point)) + + (setq name-res (c-forward-name)) + (setq res (not (null name-res))) + (when (eq name-res t) + ;; In many languages the name can be used without the + ;; prefix, so we add it to `c-found-types'. + (c-add-type pos (point)) + (when (and c-record-type-identifiers + c-last-identifier-range) + (c-record-type-id c-last-identifier-range))) + (when (and brace-block-too + (memq res '(t nil)) + (eq (char-after) ?\{) + (save-excursion + (c-safe + (progn (c-forward-sexp) + (c-forward-syntactic-ws) + (setq pos (point)))))) + (goto-char pos) + (setq res t)) + (unless res (goto-char start))) ; invalid syntax + + ((progn + (setq pos nil) + (if (looking-at c-identifier-start) + (save-excursion + (setq id-start (point) + name-res (c-forward-name)) + (when name-res + (setq id-end (point) + id-range c-last-identifier-range)))) + (and (cond ((looking-at c-primitive-type-key) + (setq res t)) + ((c-with-syntax-table c-identifier-syntax-table + (looking-at c-known-type-key)) + (setq res 'known))) + (or (not id-end) + (>= (save-excursion + (save-match-data + (goto-char (match-end 1)) + (c-forward-syntactic-ws) + (setq pos (point)))) + id-end) + (setq res nil)))) + ;; Looking at a primitive or known type identifier. We've + ;; checked for a name first so that we don't go here if the + ;; known type match only is a prefix of another name. + + (setq id-end (match-end 1)) + + (when (and c-record-type-identifiers + (or c-promote-possible-types (eq res t))) + (c-record-type-id (cons (match-beginning 1) (match-end 1)))) + + (if (and c-opt-type-component-key + (save-match-data + (looking-at c-opt-type-component-key))) + ;; There might be more keywords for the type. + (let (safe-pos) + (c-forward-keyword-clause 1) + (while (progn + (setq safe-pos (point)) + (looking-at c-opt-type-component-key)) + (when (and c-record-type-identifiers + (looking-at c-primitive-type-key)) + (c-record-type-id (cons (match-beginning 1) + (match-end 1)))) + (c-forward-keyword-clause 1)) + (if (looking-at c-primitive-type-key) + (progn + (when c-record-type-identifiers + (c-record-type-id (cons (match-beginning 1) + (match-end 1)))) + (c-forward-keyword-clause 1) + (setq res t)) + (goto-char safe-pos) + (setq res 'prefix))) + (unless (save-match-data (c-forward-keyword-clause 1)) + (if pos + (goto-char pos) + (goto-char (match-end 1)) + (c-forward-syntactic-ws))))) + + (name-res + (cond ((eq name-res t) + ;; A normal identifier. + (goto-char id-end) + (if (or res c-promote-possible-types) + (progn + (c-add-type id-start id-end) + (when (and c-record-type-identifiers id-range) + (c-record-type-id id-range)) + (unless res + (setq res 'found))) + (setq res (if (c-check-type id-start id-end) + ;; It's an identifier that has been used as + ;; a type somewhere else. + 'found + ;; It's an identifier that might be a type. + 'maybe)))) + ((eq name-res 'template) + ;; A template is a type. + (goto-char id-end) + (setq res t)) + (t + ;; Otherwise it's an operator identifier, which is not a type. + (goto-char start) + (setq res nil))))) + + (when res + ;; Skip trailing type modifiers. If any are found we know it's + ;; a type. + (when c-opt-type-modifier-key + (while (looking-at c-opt-type-modifier-key) ; e.g. "const", "volatile" + (goto-char (match-end 1)) + (c-forward-syntactic-ws) + (setq res t))) + + ;; Step over any type suffix operator. Do not let the existence + ;; of these alter the classification of the found type, since + ;; these operators typically are allowed in normal expressions + ;; too. + (when c-opt-type-suffix-key + (while (looking-at c-opt-type-suffix-key) + (goto-char (match-end 1)) + (c-forward-syntactic-ws))) + + (when c-opt-type-concat-key ; Only/mainly for pike. + ;; Look for a trailing operator that concatenates the type + ;; with a following one, and if so step past that one through + ;; a recursive call. Note that we don't record concatenated + ;; types in `c-found-types' - it's the component types that + ;; are recorded when appropriate. + (setq pos (point)) + (let* ((c-promote-possible-types (or (memq res '(t known)) + c-promote-possible-types)) + ;; If we can't promote then set `c-record-found-types' so that + ;; we can merge in the types from the second part afterwards if + ;; it turns out to be a known type there. + (c-record-found-types (and c-record-type-identifiers + (not c-promote-possible-types))) + subres) + (if (and (looking-at c-opt-type-concat-key) + + (progn + (goto-char (match-end 1)) + (c-forward-syntactic-ws) + (setq subres (c-forward-type)))) + + (progn + ;; If either operand certainly is a type then both are, but we + ;; don't let the existence of the operator itself promote two + ;; uncertain types to a certain one. + (cond ((eq res t)) + ((eq subres t) + (unless (eq name-res 'template) + (c-add-type id-start id-end)) + (when (and c-record-type-identifiers id-range) + (c-record-type-id id-range)) + (setq res t)) + ((eq res 'known)) + ((eq subres 'known) + (setq res 'known)) + ((eq res 'found)) + ((eq subres 'found) + (setq res 'found)) + (t + (setq res 'maybe))) + + (when (and (eq res t) + (consp c-record-found-types)) + ;; Merge in the ranges of any types found by the second + ;; `c-forward-type'. + (setq c-record-type-identifiers + ;; `nconc' doesn't mind that the tail of + ;; `c-record-found-types' is t. + (nconc c-record-found-types + c-record-type-identifiers)))) + + (goto-char pos)))) + + (when (and c-record-found-types (memq res '(known found)) id-range) + (setq c-record-found-types + (cons id-range c-record-found-types)))) + + ;;(message "c-forward-type %s -> %s: %s" start (point) res) + + res)) + +(defun c-forward-annotation () + ;; Used for Java code only at the moment. Assumes point is on the + ;; @, moves forward an annotation. returns nil if there is no + ;; annotation at point. + (and (looking-at "@") + (progn (forward-char) t) + (c-forward-type) + (progn (c-forward-syntactic-ws) t) + (if (looking-at "(") + (c-go-list-forward) + t))) + + +;; Handling of large scale constructs like statements and declarations. + +;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a +;; defsubst or perhaps even a defun, but it contains lots of free +;; variables that refer to things inside `c-forward-decl-or-cast-1'. +(defmacro c-fdoc-shift-type-backward (&optional short) + ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list + ;; of types when parsing a declaration, which means that it + ;; sometimes consumes the identifier in the declaration as a type. + ;; This is used to "backtrack" and make the last type be treated as + ;; an identifier instead. + `(progn + ,(unless short + ;; These identifiers are bound only in the inner let. + '(setq identifier-type at-type + identifier-start type-start + got-parens nil + got-identifier t + got-suffix t + got-suffix-after-parens id-start + paren-depth 0)) + + (if (setq at-type (if (eq backup-at-type 'prefix) + t + backup-at-type)) + (setq type-start backup-type-start + id-start backup-id-start) + (setq type-start start-pos + id-start start-pos)) + + ;; When these flags already are set we've found specifiers that + ;; unconditionally signal these attributes - backtracking doesn't + ;; change that. So keep them set in that case. + (or at-type-decl + (setq at-type-decl backup-at-type-decl)) + (or maybe-typeless + (setq maybe-typeless backup-maybe-typeless)) + + ,(unless short + ;; This identifier is bound only in the inner let. + '(setq start id-start)))) + +(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end) + ;; Move forward over a declaration or a cast if at the start of one. + ;; The point is assumed to be at the start of some token. Nil is + ;; returned if no declaration or cast is recognized, and the point + ;; is clobbered in that case. + ;; + ;; If a declaration is parsed: + ;; + ;; The point is left at the first token after the first complete + ;; declarator, if there is one. The return value is a cons where + ;; the car is the position of the first token in the declarator. (See + ;; below for the cdr.) + ;; Some examples: + ;; + ;; void foo (int a, char *b) stuff ... + ;; car ^ ^ point + ;; float (*a)[], b; + ;; car ^ ^ point + ;; unsigned int a = c_style_initializer, b; + ;; car ^ ^ point + ;; unsigned int a (cplusplus_style_initializer), b; + ;; car ^ ^ point (might change) + ;; class Foo : public Bar {} + ;; car ^ ^ point + ;; class PikeClass (int a, string b) stuff ... + ;; car ^ ^ point + ;; enum bool; + ;; car ^ ^ point + ;; enum bool flag; + ;; car ^ ^ point + ;; void cplusplus_function (int x) throw (Bad); + ;; car ^ ^ point + ;; Foo::Foo (int b) : Base (b) {} + ;; car ^ ^ point + ;; + ;; The cdr of the return value is non-nil when a + ;; `c-typedef-decl-kwds' specifier is found in the declaration. + ;; Specifically it is a dotted pair (A . B) where B is t when a + ;; `c-typedef-kwds' ("typedef") is present, and A is t when some + ;; other `c-typedef-decl-kwds' (e.g. class, struct, enum) + ;; specifier is present. I.e., (some of) the declared + ;; identifier(s) are types. + ;; + ;; If a cast is parsed: + ;; + ;; The point is left at the first token after the closing paren of + ;; the cast. The return value is `cast'. Note that the start + ;; position must be at the first token inside the cast parenthesis + ;; to recognize it. + ;; + ;; PRECEDING-TOKEN-END is the first position after the preceding + ;; token, i.e. on the other side of the syntactic ws from the point. + ;; Use a value less than or equal to (point-min) if the point is at + ;; the first token in (the visible part of) the buffer. + ;; + ;; CONTEXT is a symbol that describes the context at the point: + ;; 'decl In a comma-separated declaration context (typically + ;; inside a function declaration arglist). + ;; '<> In an angle bracket arglist. + ;; 'arglist Some other type of arglist. + ;; nil Some other context or unknown context. Includes + ;; within the parens of an if, for, ... construct. + ;; + ;; LAST-CAST-END is the first token after the closing paren of a + ;; preceding cast, or nil if none is known. If + ;; `c-forward-decl-or-cast-1' is used in succession, it should be + ;; the position after the closest preceding call where a cast was + ;; matched. In that case it's used to discover chains of casts like + ;; "(a) (b) c". + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let (;; `start-pos' is used below to point to the start of the + ;; first type, i.e. after any leading specifiers. It might + ;; also point at the beginning of the preceding syntactic + ;; whitespace. + (start-pos (point)) + ;; Set to the result of `c-forward-type'. + at-type + ;; The position of the first token in what we currently + ;; believe is the type in the declaration or cast, after any + ;; specifiers and their associated clauses. + type-start + ;; The position of the first token in what we currently + ;; believe is the declarator for the first identifier. Set + ;; when the type is found, and moved forward over any + ;; `c-decl-hangon-kwds' and their associated clauses that + ;; occurs after the type. + id-start + ;; These store `at-type', `type-start' and `id-start' of the + ;; identifier before the one in those variables. The previous + ;; identifier might turn out to be the real type in a + ;; declaration if the last one has to be the declarator in it. + ;; If `backup-at-type' is nil then the other variables have + ;; undefined values. + backup-at-type backup-type-start backup-id-start + ;; Set if we've found a specifier (apart from "typedef") that makes + ;; the defined identifier(s) types. + at-type-decl + ;; Set if we've a "typedef" keyword. + at-typedef + ;; Set if we've found a specifier that can start a declaration + ;; where there's no type. + maybe-typeless + ;; If a specifier is found that also can be a type prefix, + ;; these flags are set instead of those above. If we need to + ;; back up an identifier, they are copied to the real flag + ;; variables. Thus they only take effect if we fail to + ;; interpret it as a type. + backup-at-type-decl backup-maybe-typeless + ;; Whether we've found a declaration or a cast. We might know + ;; this before we've found the type in it. It's 'ids if we've + ;; found two consecutive identifiers (usually a sure sign, but + ;; we should allow that in labels too), and t if we've found a + ;; specifier keyword (a 100% sure sign). + at-decl-or-cast + ;; Set when we need to back up to parse this as a declaration + ;; but not as a cast. + backup-if-not-cast + ;; For casts, the return position. + cast-end + ;; Save `c-record-type-identifiers' and + ;; `c-record-ref-identifiers' since ranges are recorded + ;; speculatively and should be thrown away if it turns out + ;; that it isn't a declaration or cast. + (save-rec-type-ids c-record-type-identifiers) + (save-rec-ref-ids c-record-ref-identifiers)) + + (while (c-forward-annotation) + (c-forward-syntactic-ws)) + + ;; Check for a type. Unknown symbols are treated as possible + ;; types, but they could also be specifiers disguised through + ;; macros like __INLINE__, so we recognize both types and known + ;; specifiers after them too. + (while + (let* ((start (point)) kwd-sym kwd-clause-end found-type) + + ;; Look for a specifier keyword clause. + (when (or (looking-at c-prefix-spec-kwds-re) + (and (c-major-mode-is 'java-mode) + (looking-at "@[A-Za-z0-9]+"))) + (if (looking-at c-typedef-key) + (setq at-typedef t)) + (setq kwd-sym (c-keyword-sym (match-string 1))) + (save-excursion + (c-forward-keyword-clause 1) + (setq kwd-clause-end (point)))) + + (when (setq found-type (c-forward-type t)) ; brace-block-too + ;; Found a known or possible type or a prefix of a known type. + + (when at-type + ;; Got two identifiers with nothing but whitespace + ;; between them. That can only happen in declarations. + (setq at-decl-or-cast 'ids) + + (when (eq at-type 'found) + ;; If the previous identifier is a found type we + ;; record it as a real one; it might be some sort of + ;; alias for a prefix like "unsigned". + (save-excursion + (goto-char type-start) + (let ((c-promote-possible-types t)) + (c-forward-type))))) + + (setq backup-at-type at-type + backup-type-start type-start + backup-id-start id-start + at-type found-type + type-start start + id-start (point) + ;; The previous ambiguous specifier/type turned out + ;; to be a type since we've parsed another one after + ;; it, so clear these backup flags. + backup-at-type-decl nil + backup-maybe-typeless nil)) + + (if kwd-sym + (progn + ;; Handle known specifier keywords and + ;; `c-decl-hangon-kwds' which can occur after known + ;; types. + + (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds) + ;; It's a hang-on keyword that can occur anywhere. + (progn + (setq at-decl-or-cast t) + (if at-type + ;; Move the identifier start position if + ;; we've passed a type. + (setq id-start kwd-clause-end) + ;; Otherwise treat this as a specifier and + ;; move the fallback position. + (setq start-pos kwd-clause-end)) + (goto-char kwd-clause-end)) + + ;; It's an ordinary specifier so we know that + ;; anything before this can't be the type. + (setq backup-at-type nil + start-pos kwd-clause-end) + + (if found-type + ;; It's ambiguous whether this keyword is a + ;; specifier or a type prefix, so set the backup + ;; flags. (It's assumed that `c-forward-type' + ;; moved further than `c-forward-keyword-clause'.) + (progn + (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds) + (setq backup-at-type-decl t)) + (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds) + (setq backup-maybe-typeless t))) + + (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds) + ;; This test only happens after we've scanned a type. + ;; So, with valid syntax, kwd-sym can't be 'typedef. + (setq at-type-decl t)) + (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds) + (setq maybe-typeless t)) + + ;; Haven't matched a type so it's an umambiguous + ;; specifier keyword and we know we're in a + ;; declaration. + (setq at-decl-or-cast t) + + (goto-char kwd-clause-end)))) + + ;; If the type isn't known we continue so that we'll jump + ;; over all specifiers and type identifiers. The reason + ;; to do this for a known type prefix is to make things + ;; like "unsigned INT16" work. + (and found-type (not (eq found-type t)))))) + + (cond + ((eq at-type t) + ;; If a known type was found, we still need to skip over any + ;; hangon keyword clauses after it. Otherwise it has already + ;; been done in the loop above. + (while (looking-at c-decl-hangon-key) + (c-forward-keyword-clause 1)) + (setq id-start (point))) + + ((eq at-type 'prefix) + ;; A prefix type is itself a primitive type when it's not + ;; followed by another type. + (setq at-type t)) + + ((not at-type) + ;; Got no type but set things up to continue anyway to handle + ;; the various cases when a declaration doesn't start with a + ;; type. + (setq id-start start-pos)) + + ((and (eq at-type 'maybe) + (c-major-mode-is 'c++-mode)) + ;; If it's C++ then check if the last "type" ends on the form + ;; "foo::foo" or "foo::~foo", i.e. if it's the name of a + ;; (con|de)structor. + (save-excursion + (let (name end-2 end-1) + (goto-char id-start) + (c-backward-syntactic-ws) + (setq end-2 (point)) + (when (and + (c-simple-skip-symbol-backward) + (progn + (setq name + (buffer-substring-no-properties (point) end-2)) + ;; Cheating in the handling of syntactic ws below. + (< (skip-chars-backward ":~ \t\n\r\v\f") 0)) + (progn + (setq end-1 (point)) + (c-simple-skip-symbol-backward)) + (>= (point) type-start) + (equal (buffer-substring-no-properties (point) end-1) + name)) + ;; It is a (con|de)structor name. In that case the + ;; declaration is typeless so zap out any preceding + ;; identifier(s) that we might have taken as types. + (goto-char type-start) + (setq at-type nil + backup-at-type nil + id-start type-start)))))) + + ;; Check for and step over a type decl expression after the thing + ;; that is or might be a type. This can't be skipped since we + ;; need the correct end position of the declarator for + ;; `max-type-decl-end-*'. + (let ((start (point)) (paren-depth 0) pos + ;; True if there's a non-open-paren match of + ;; `c-type-decl-prefix-key'. + got-prefix + ;; True if the declarator is surrounded by a parenthesis pair. + got-parens + ;; True if there is an identifier in the declarator. + got-identifier + ;; True if there's a non-close-paren match of + ;; `c-type-decl-suffix-key'. + got-suffix + ;; True if there's a prefix match outside the outermost + ;; paren pair that surrounds the declarator. + got-prefix-before-parens + ;; True if there's a suffix match outside the outermost + ;; paren pair that surrounds the declarator. The value is + ;; the position of the first suffix match. + got-suffix-after-parens + ;; True if we've parsed the type decl to a token that is + ;; known to end declarations in this context. + at-decl-end + ;; The earlier values of `at-type' and `type-start' if we've + ;; shifted the type backwards. + identifier-type identifier-start + ;; If `c-parse-and-markup-<>-arglists' is set we need to + ;; turn it off during the name skipping below to avoid + ;; getting `c-type' properties that might be bogus. That + ;; can happen since we don't know if + ;; `c-restricted-<>-arglists' will be correct inside the + ;; arglist paren that gets entered. + c-parse-and-markup-<>-arglists) + + (goto-char id-start) + + ;; Skip over type decl prefix operators. (Note similar code in + ;; `c-font-lock-declarators'.) + (while (and (looking-at c-type-decl-prefix-key) + (if (and (c-major-mode-is 'c++-mode) + (match-beginning 3)) + ;; If the third submatch matches in C++ then + ;; we're looking at an identifier that's a + ;; prefix only if it specifies a member pointer. + (when (setq got-identifier (c-forward-name)) + (if (looking-at "\\(::\\)") + ;; We only check for a trailing "::" and + ;; let the "*" that should follow be + ;; matched in the next round. + (progn (setq got-identifier nil) t) + ;; It turned out to be the real identifier, + ;; so stop. + nil)) + t)) + + (if (eq (char-after) ?\() + (progn + (setq paren-depth (1+ paren-depth)) + (forward-char)) + (unless got-prefix-before-parens + (setq got-prefix-before-parens (= paren-depth 0))) + (setq got-prefix t) + (goto-char (match-end 1))) + (c-forward-syntactic-ws)) + + (setq got-parens (> paren-depth 0)) + + ;; Skip over an identifier. + (or got-identifier + (and (looking-at c-identifier-start) + (setq got-identifier (c-forward-name)))) + + ;; Skip over type decl suffix operators. + (while (if (looking-at c-type-decl-suffix-key) + + (if (eq (char-after) ?\)) + (when (> paren-depth 0) + (setq paren-depth (1- paren-depth)) + (forward-char) + t) + (when (if (save-match-data (looking-at "\\s\(")) + (c-safe (c-forward-sexp 1) t) + (goto-char (match-end 1)) + t) + (when (and (not got-suffix-after-parens) + (= paren-depth 0)) + (setq got-suffix-after-parens (match-beginning 0))) + (setq got-suffix t))) + + ;; No suffix matched. We might have matched the + ;; identifier as a type and the open paren of a + ;; function arglist as a type decl prefix. In that + ;; case we should "backtrack": Reinterpret the last + ;; type as the identifier, move out of the arglist and + ;; continue searching for suffix operators. + ;; + ;; Do this even if there's no preceding type, to cope + ;; with old style function declarations in K&R C, + ;; (con|de)structors in C++ and `c-typeless-decl-kwds' + ;; style declarations. That isn't applicable in an + ;; arglist context, though. + (when (and (= paren-depth 1) + (not got-prefix-before-parens) + (not (eq at-type t)) + (or backup-at-type + maybe-typeless + backup-maybe-typeless + (when c-recognize-typeless-decls + (not context))) + (setq pos (c-up-list-forward (point))) + (eq (char-before pos) ?\))) + (c-fdoc-shift-type-backward) + (goto-char pos) + t)) + + (c-forward-syntactic-ws)) + + (when (and (or maybe-typeless backup-maybe-typeless) + (not got-identifier) + (not got-prefix) + at-type) + ;; Have found no identifier but `c-typeless-decl-kwds' has + ;; matched so we know we're inside a declaration. The + ;; preceding type must be the identifier instead. + (c-fdoc-shift-type-backward)) + + (setq + at-decl-or-cast + (catch 'at-decl-or-cast + + ;; CASE 1 + (when (> paren-depth 0) + ;; Encountered something inside parens that isn't matched by + ;; the `c-type-decl-*' regexps, so it's not a type decl + ;; expression. Try to skip out to the same paren depth to + ;; not confuse the cast check below. + (c-safe (goto-char (scan-lists (point) 1 paren-depth))) + ;; If we've found a specifier keyword then it's a + ;; declaration regardless. + (throw 'at-decl-or-cast (eq at-decl-or-cast t))) + + (setq at-decl-end + (looking-at (cond ((eq context '<>) "[,>]") + (context "[,\)]") + (t "[,;]")))) + + ;; Now we've collected info about various characteristics of + ;; the construct we're looking at. Below follows a decision + ;; tree based on that. It's ordered to check more certain + ;; signs before less certain ones. + + (if got-identifier + (progn + + ;; CASE 2 + (when (and (or at-type maybe-typeless) + (not (or got-prefix got-parens))) + ;; Got another identifier directly after the type, so it's a + ;; declaration. + (throw 'at-decl-or-cast t)) + + (when (and got-parens + (not got-prefix) + (not got-suffix-after-parens) + (or backup-at-type + maybe-typeless + backup-maybe-typeless)) + ;; Got a declaration of the form "foo bar (gnu);" where we've + ;; recognized "bar" as the type and "gnu" as the declarator. + ;; In this case it's however more likely that "bar" is the + ;; declarator and "gnu" a function argument or initializer (if + ;; `c-recognize-paren-inits' is set), since the parens around + ;; "gnu" would be superfluous if it's a declarator. Shift the + ;; type one step backward. + (c-fdoc-shift-type-backward))) + + ;; Found no identifier. + + (if backup-at-type + (progn + + ;; CASE 3 + (when (= (point) start) + ;; Got a plain list of identifiers. If a colon follows it's + ;; a valid label, or maybe a bitfield. Otherwise the last + ;; one probably is the declared identifier and we should + ;; back up to the previous type, providing it isn't a cast. + (if (and (eq (char-after) ?:) + (not (c-major-mode-is 'java-mode))) + (cond + ;; If we've found a specifier keyword then it's a + ;; declaration regardless. + ((eq at-decl-or-cast t) + (throw 'at-decl-or-cast t)) + ((and c-has-bitfields + (eq at-decl-or-cast 'ids)) ; bitfield. + (setq backup-if-not-cast t) + (throw 'at-decl-or-cast t))) + + (setq backup-if-not-cast t) + (throw 'at-decl-or-cast t))) + + ;; CASE 4 + (when (and got-suffix + (not got-prefix) + (not got-parens)) + ;; Got a plain list of identifiers followed by some suffix. + ;; If this isn't a cast then the last identifier probably is + ;; the declared one and we should back up to the previous + ;; type. + (setq backup-if-not-cast t) + (throw 'at-decl-or-cast t))) + + ;; CASE 5 + (when (eq at-type t) + ;; If the type is known we know that there can't be any + ;; identifier somewhere else, and it's only in declarations in + ;; e.g. function prototypes and in casts that the identifier may + ;; be left out. + (throw 'at-decl-or-cast t)) + + (when (= (point) start) + ;; Only got a single identifier (parsed as a type so far). + ;; CASE 6 + (if (and + ;; Check that the identifier isn't at the start of an + ;; expression. + at-decl-end + (cond + ((eq context 'decl) + ;; Inside an arglist that contains declarations. If K&R + ;; style declarations and parenthesis style initializers + ;; aren't allowed then the single identifier must be a + ;; type, else we require that it's known or found + ;; (primitive types are handled above). + (or (and (not c-recognize-knr-p) + (not c-recognize-paren-inits)) + (memq at-type '(known found)))) + ((eq context '<>) + ;; Inside a template arglist. Accept known and found + ;; types; other identifiers could just as well be + ;; constants in C++. + (memq at-type '(known found))))) + (throw 'at-decl-or-cast t) + ;; CASE 7 + ;; Can't be a valid declaration or cast, but if we've found a + ;; specifier it can't be anything else either, so treat it as + ;; an invalid/unfinished declaration or cast. + (throw 'at-decl-or-cast at-decl-or-cast)))) + + (if (and got-parens + (not got-prefix) + (not context) + (not (eq at-type t)) + (or backup-at-type + maybe-typeless + backup-maybe-typeless + (when c-recognize-typeless-decls + (or (not got-suffix) + (not (looking-at + c-after-suffixed-type-maybe-decl-key)))))) + ;; Got an empty paren pair and a preceding type that probably + ;; really is the identifier. Shift the type backwards to make + ;; the last one the identifier. This is analogous to the + ;; "backtracking" done inside the `c-type-decl-suffix-key' loop + ;; above. + ;; + ;; Exception: In addition to the conditions in that + ;; "backtracking" code, do not shift backward if we're not + ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]". + ;; Since there's no preceding type, the shift would mean that + ;; the declaration is typeless. But if the regexp doesn't match + ;; then we will simply fall through in the tests below and not + ;; recognize it at all, so it's better to try it as an abstract + ;; declarator instead. + (c-fdoc-shift-type-backward) + + ;; Still no identifier. + ;; CASE 8 + (when (and got-prefix (or got-parens got-suffix)) + ;; Require `got-prefix' together with either `got-parens' or + ;; `got-suffix' to recognize it as an abstract declarator: + ;; `got-parens' only is probably an empty function call. + ;; `got-suffix' only can build an ordinary expression together + ;; with the preceding identifier which we've taken as a type. + ;; We could actually accept on `got-prefix' only, but that can + ;; easily occur temporarily while writing an expression so we + ;; avoid that case anyway. We could do a better job if we knew + ;; the point when the fontification was invoked. + (throw 'at-decl-or-cast t)) + + ;; CASE 9 + (when (and at-type + (not got-prefix) + (not got-parens) + got-suffix-after-parens + (eq (char-after got-suffix-after-parens) ?\()) + ;; Got a type, no declarator but a paren suffix. I.e. it's a + ;; normal function call afterall (or perhaps a C++ style object + ;; instantiation expression). + (throw 'at-decl-or-cast nil)))) + + ;; CASE 10 + (when at-decl-or-cast + ;; By now we've located the type in the declaration that we know + ;; we're in. + (throw 'at-decl-or-cast t)) + + ;; CASE 11 + (when (and got-identifier + (not context) + (looking-at c-after-suffixed-type-decl-key) + (if (and got-parens + (not got-prefix) + (not got-suffix) + (not (eq at-type t))) + ;; Shift the type backward in the case that there's a + ;; single identifier inside parens. That can only + ;; occur in K&R style function declarations so it's + ;; more likely that it really is a function call. + ;; Therefore we only do this after + ;; `c-after-suffixed-type-decl-key' has matched. + (progn (c-fdoc-shift-type-backward) t) + got-suffix-after-parens)) + ;; A declaration according to `c-after-suffixed-type-decl-key'. + (throw 'at-decl-or-cast t)) + + ;; CASE 12 + (when (and (or got-prefix (not got-parens)) + (memq at-type '(t known))) + ;; It's a declaration if a known type precedes it and it can't be a + ;; function call. + (throw 'at-decl-or-cast t)) + + ;; If we get here we can't tell if this is a type decl or a normal + ;; expression by looking at it alone. (That's under the assumption + ;; that normal expressions always can look like type decl expressions, + ;; which isn't really true but the cases where it doesn't hold are so + ;; uncommon (e.g. some placements of "const" in C++) it's not worth + ;; the effort to look for them.) + +;;; 2008-04-16: commented out the next form, to allow the function to recognise +;;; "foo (int bar)" in CC (an implicit type (in class foo) without a semicolon) +;;; as a(n almost complete) declaration, enabling it to be fontified. + ;; CASE 13 + ;; (unless (or at-decl-end (looking-at "=[^=]")) + ;; If this is a declaration it should end here or its initializer(*) + ;; should start here, so check for allowed separation tokens. Note + ;; that this rule doesn't work e.g. with a K&R arglist after a + ;; function header. + ;; + ;; *) Don't check for C++ style initializers using parens + ;; since those already have been matched as suffixes. + ;; + ;; If `at-decl-or-cast' is then we've found some other sign that + ;; it's a declaration or cast, so then it's probably an + ;; invalid/unfinished one. + ;; (throw 'at-decl-or-cast at-decl-or-cast)) + + ;; Below are tests that only should be applied when we're certain to + ;; not have parsed halfway through an expression. + + ;; CASE 14 + (when (memq at-type '(t known)) + ;; The expression starts with a known type so treat it as a + ;; declaration. + (throw 'at-decl-or-cast t)) + + ;; CASE 15 + (when (and (c-major-mode-is 'c++-mode) + ;; In C++ we check if the identifier is a known type, since + ;; (con|de)structors use the class name as identifier. + ;; We've always shifted over the identifier as a type and + ;; then backed up again in this case. + identifier-type + (or (memq identifier-type '(found known)) + (and (eq (char-after identifier-start) ?~) + ;; `at-type' probably won't be 'found for + ;; destructors since the "~" is then part of the + ;; type name being checked against the list of + ;; known types, so do a check without that + ;; operator. + (or (save-excursion + (goto-char (1+ identifier-start)) + (c-forward-syntactic-ws) + (c-with-syntax-table + c-identifier-syntax-table + (looking-at c-known-type-key))) + (save-excursion + (goto-char (1+ identifier-start)) + ;; We have already parsed the type earlier, + ;; so it'd be possible to cache the end + ;; position instead of redoing it here, but + ;; then we'd need to keep track of another + ;; position everywhere. + (c-check-type (point) + (progn (c-forward-type) + (point)))))))) + (throw 'at-decl-or-cast t)) + + (if got-identifier + (progn + ;; CASE 16 + (when (and got-prefix-before-parens + at-type + (or at-decl-end (looking-at "=[^=]")) + (not context) + (not got-suffix)) + ;; Got something like "foo * bar;". Since we're not inside an + ;; arglist it would be a meaningless expression because the + ;; result isn't used. We therefore choose to recognize it as + ;; a declaration. Do not allow a suffix since it could then + ;; be a function call. + (throw 'at-decl-or-cast t)) + + ;; CASE 17 + (when (and (or got-suffix-after-parens + (looking-at "=[^=]")) + (eq at-type 'found) + (not (eq context 'arglist))) + ;; Got something like "a (*b) (c);" or "a (b) = c;". It could + ;; be an odd expression or it could be a declaration. Treat + ;; it as a declaration if "a" has been used as a type + ;; somewhere else (if it's a known type we won't get here). + (throw 'at-decl-or-cast t))) + + ;; CASE 18 + (when (and context + (or got-prefix + (and (eq context 'decl) + (not c-recognize-paren-inits) + (or got-parens got-suffix)))) + ;; Got a type followed by an abstract declarator. If `got-prefix' + ;; is set it's something like "a *" without anything after it. If + ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]", + ;; or similar, which we accept only if the context rules out + ;; expressions. + (throw 'at-decl-or-cast t))) + + ;; If we had a complete symbol table here (which rules out + ;; `c-found-types') we should return t due to the disambiguation rule + ;; (in at least C++) that anything that can be parsed as a declaration + ;; is a declaration. Now we're being more defensive and prefer to + ;; highlight things like "foo (bar);" as a declaration only if we're + ;; inside an arglist that contains declarations. + (eq context 'decl)))) + + ;; The point is now after the type decl expression. + + (cond + ;; Check for a cast. + ((save-excursion + (and + c-cast-parens + + ;; Should be the first type/identifier in a cast paren. + (> preceding-token-end (point-min)) + (memq (char-before preceding-token-end) c-cast-parens) + + ;; The closing paren should follow. + (progn + (c-forward-syntactic-ws) + (looking-at "\\s\)")) + + ;; There should be a primary expression after it. + (let (pos) + (forward-char) + (c-forward-syntactic-ws) + (setq cast-end (point)) + (and (looking-at c-primary-expr-regexp) + (progn + (setq pos (match-end 0)) + (or + ;; Check if the expression begins with a prefix keyword. + (match-beginning 2) + (if (match-beginning 1) + ;; Expression begins with an ambiguous operator. Treat + ;; it as a cast if it's a type decl or if we've + ;; recognized the type somewhere else. + (or at-decl-or-cast + (memq at-type '(t known found))) + ;; Unless it's a keyword, it's the beginning of a primary + ;; expression. + (not (looking-at c-keywords-regexp))))) + ;; If `c-primary-expr-regexp' matched a nonsymbol token, check + ;; that it matched a whole one so that we don't e.g. confuse + ;; the operator '-' with '->'. It's ok if it matches further, + ;; though, since it e.g. can match the float '.5' while the + ;; operator regexp only matches '.'. + (or (not (looking-at c-nonsymbol-token-regexp)) + (<= (match-end 0) pos)))) + + ;; There should either be a cast before it or something that isn't an + ;; identifier or close paren. + (> preceding-token-end (point-min)) + (progn + (goto-char (1- preceding-token-end)) + (or (eq (point) last-cast-end) + (progn + (c-backward-syntactic-ws) + (if (< (skip-syntax-backward "w_") 0) + ;; It's a symbol. Accept it only if it's one of the + ;; keywords that can precede an expression (without + ;; surrounding parens). + (looking-at c-simple-stmt-key) + (and + ;; Check that it isn't a close paren (block close is ok, + ;; though). + (not (memq (char-before) '(?\) ?\]))) + ;; Check that it isn't a nonsymbol identifier. + (not (c-on-identifier))))))))) + + ;; Handle the cast. + (when (and c-record-type-identifiers at-type (not (eq at-type t))) + (let ((c-promote-possible-types t)) + (goto-char type-start) + (c-forward-type))) + + (goto-char cast-end) + 'cast) + + (at-decl-or-cast + ;; We're at a declaration. Highlight the type and the following + ;; declarators. + + (when backup-if-not-cast + (c-fdoc-shift-type-backward t)) + + (when (and (eq context 'decl) (looking-at ",")) + ;; Make sure to propagate the `c-decl-arg-start' property to + ;; the next argument if it's set in this one, to cope with + ;; interactive refontification. + (c-put-c-type-property (point) 'c-decl-arg-start)) + + (when (and c-record-type-identifiers at-type (not (eq at-type t))) + (let ((c-promote-possible-types t)) + (save-excursion + (goto-char type-start) + (c-forward-type)))) + + (cons id-start + (and (or at-type-decl at-typedef) + (cons at-type-decl at-typedef)))) + + (t + ;; False alarm. Restore the recorded ranges. + (setq c-record-type-identifiers save-rec-type-ids + c-record-ref-identifiers save-rec-ref-ids) + nil)))) + +(defun c-forward-label (&optional assume-markup preceding-token-end limit) + ;; Assuming that point is at the beginning of a token, check if it starts a + ;; label and if so move over it and return non-nil (t in default situations, + ;; specific symbols (see below) for interesting situations), otherwise don't + ;; move and return nil. "Label" here means "most things with a colon". + ;; + ;; More precisely, a "label" is regarded as one of: + ;; (i) a goto target like "foo:" - returns the symbol `goto-target'; + ;; (ii) A case label - either the entire construct "case FOO:", or just the + ;; bare "case", should the colon be missing. We return t; + ;; (iii) a keyword which needs a colon, like "default:" or "private:"; We + ;; return t; + ;; (iv) One of QT's "extended" C++ variants of + ;; "private:"/"protected:"/"public:"/"more:" looking like "public slots:". + ;; Returns the symbol `qt-2kwds-colon'. + ;; (v) QT's construct "signals:". Returns the symbol `qt-1kwd-colon'. + ;; (vi) One of the keywords matched by `c-opt-extra-label-key' (without any + ;; colon). Currently (2006-03), this applies only to Objective C's + ;; keywords "@private", "@protected", and "@public". Returns t. + ;; + ;; One of the things which will NOT be recognised as a label is a bit-field + ;; element of a struct, something like "int foo:5". + ;; + ;; The end of the label is taken to be just after the colon, or the end of + ;; the first submatch in `c-opt-extra-label-key'. The point is directly + ;; after the end on return. The terminating char gets marked with + ;; `c-decl-end' to improve recognition of the following declaration or + ;; statement. + ;; + ;; If ASSUME-MARKUP is non-nil, it's assumed that the preceding + ;; label, if any, has already been marked up like that. + ;; + ;; If PRECEDING-TOKEN-END is given, it should be the first position + ;; after the preceding token, i.e. on the other side of the + ;; syntactic ws from the point. Use a value less than or equal to + ;; (point-min) if the point is at the first token in (the visible + ;; part of) the buffer. + ;; + ;; The optional LIMIT limits the forward scan for the colon. + ;; + ;; This function records the ranges of the label symbols on + ;; `c-record-ref-identifiers' if `c-record-type-identifiers' (!) is + ;; non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let ((start (point)) + label-end + qt-symbol-idx + macro-start ; if we're in one. + label-type + kwd) + (cond + ;; "case" or "default" (Doesn't apply to AWK). + ((looking-at c-label-kwds-regexp) + (let ((kwd-end (match-end 1))) + ;; Record only the keyword itself for fontification, since in + ;; case labels the following is a constant expression and not + ;; a label. + (when c-record-type-identifiers + (c-record-ref-id (cons (match-beginning 1) kwd-end))) + + ;; Find the label end. + (goto-char kwd-end) + (setq label-type + (if (and (c-syntactic-re-search-forward + ;; Stop on chars that aren't allowed in expressions, + ;; and on operator chars that would be meaningless + ;; there. FIXME: This doesn't cope with ?: operators. + "[;{=,@]\\|\\(\\=\\|[^:]\\):\\([^:]\\|\\'\\)" + limit t t nil 1) + (match-beginning 2)) + + (progn ; there's a proper : + (goto-char (match-beginning 2)) ; just after the : + (c-put-c-type-property (1- (point)) 'c-decl-end) + t) + + ;; It's an unfinished label. We consider the keyword enough + ;; to recognize it as a label, so that it gets fontified. + ;; Leave the point at the end of it, but don't put any + ;; `c-decl-end' marker. + (goto-char kwd-end) + t)))) + + ;; @private, @protected, @public, in Objective C, or similar. + ((and c-opt-extra-label-key + (looking-at c-opt-extra-label-key)) + ;; For a `c-opt-extra-label-key' match, we record the whole + ;; thing for fontification. That's to get the leading '@' in + ;; Objective-C protection labels fontified. + (goto-char (match-end 1)) + (when c-record-type-identifiers + (c-record-ref-id (cons (match-beginning 1) (point)))) + (c-put-c-type-property (1- (point)) 'c-decl-end) + (setq label-type t)) + + ;; All other cases of labels. + ((and c-recognize-colon-labels ; nil for AWK and IDL, otherwise t. + + ;; A colon label must have something before the colon. + (not (eq (char-after) ?:)) + + ;; Check that we're not after a token that can't precede a label. + (or + ;; Trivially succeeds when there's no preceding token. + ;; Succeeds when we're at a virtual semicolon. + (if preceding-token-end + (<= preceding-token-end (point-min)) + (save-excursion + (c-backward-syntactic-ws) + (setq preceding-token-end (point)) + (or (bobp) + (c-at-vsemi-p)))) + + ;; Check if we're after a label, if we're after a closing + ;; paren that belong to statement, and with + ;; `c-label-prefix-re'. It's done in different order + ;; depending on `assume-markup' since the checks have + ;; different expensiveness. + (if assume-markup + (or + (eq (c-get-char-property (1- preceding-token-end) 'c-type) + 'c-decl-end) + + (save-excursion + (goto-char (1- preceding-token-end)) + (c-beginning-of-current-token) + (or (looking-at c-label-prefix-re) + (looking-at c-block-stmt-1-key))) + + (and (eq (char-before preceding-token-end) ?\)) + (c-after-conditional))) + + (or + (save-excursion + (goto-char (1- preceding-token-end)) + (c-beginning-of-current-token) + (or (looking-at c-label-prefix-re) + (looking-at c-block-stmt-1-key))) + + (cond + ((eq (char-before preceding-token-end) ?\)) + (c-after-conditional)) + + ((eq (char-before preceding-token-end) ?:) + ;; Might be after another label, so check it recursively. + (save-restriction + (save-excursion + (goto-char (1- preceding-token-end)) + ;; Essentially the same as the + ;; `c-syntactic-re-search-forward' regexp below. + (setq macro-start + (save-excursion (and (c-beginning-of-macro) + (point)))) + (if macro-start (narrow-to-region macro-start (point-max))) + (c-syntactic-skip-backward "^-]:?;}=*/%&|,<>!@+" nil t) + ;; Note: the following should work instead of the + ;; narrow-to-region above. Investigate why not, + ;; sometime. ACM, 2006-03-31. + ;; (c-syntactic-skip-backward "^-]:?;}=*/%&|,<>!@+" + ;; macro-start t) + (let ((pte (point)) + ;; If the caller turned on recording for us, + ;; it shouldn't apply when we check the + ;; preceding label. + c-record-type-identifiers) + ;; A label can't start at a cpp directive. Check for + ;; this, since c-forward-syntactic-ws would foul up on it. + (unless (and c-opt-cpp-prefix (looking-at c-opt-cpp-prefix)) + (c-forward-syntactic-ws) + (c-forward-label nil pte start)))))))))) + + ;; Point is still at the beginning of the possible label construct. + ;; + ;; Check that the next nonsymbol token is ":", or that we're in one + ;; of QT's "slots" declarations. Allow '(' for the sake of macro + ;; arguments. FIXME: Should build this regexp from the language + ;; constants. + (cond + ;; public: protected: private: + ((and + (c-major-mode-is 'c++-mode) + (search-forward-regexp + "\\=p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\>[^_]" nil t) + (progn (backward-char) + (c-forward-syntactic-ws limit) + (looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon. + (forward-char) + (setq label-type t)) + ;; QT double keyword like "protected slots:" or goto target. + ((progn (goto-char start) nil)) + ((when (c-syntactic-re-search-forward + "[ \t\n[:?;{=*/%&|,<>!@+-]" limit t t) ; not at EOB + (backward-char) + (setq label-end (point)) + (setq qt-symbol-idx + (and (c-major-mode-is 'c++-mode) + (string-match + "\\(p\\(r\\(ivate\\|otected\\)\\|ublic\\)\\|more\\)\\>" + (buffer-substring start (point))))) + (c-forward-syntactic-ws limit) + (cond + ((looking-at ":\\([^:]\\|\\'\\)") ; A single colon. + (forward-char) + (setq label-type + (if (or (string= "signals" ; Special QT macro + (setq kwd (buffer-substring-no-properties start label-end))) + (string= "Q_SIGNALS" kwd)) + 'qt-1kwd-colon + 'goto-target))) + ((and qt-symbol-idx + (search-forward-regexp "\\=\\(slots\\|Q_SLOTS\\)\\>" limit t) + (progn (c-forward-syntactic-ws limit) + (looking-at ":\\([^:]\\|\\'\\)"))) ; A single colon + (forward-char) + (setq label-type 'qt-2kwds-colon))))))) + + (save-restriction + (narrow-to-region start (point)) + + ;; Check that `c-nonlabel-token-key' doesn't match anywhere. + (catch 'check-label + (goto-char start) + (while (progn + (when (looking-at c-nonlabel-token-key) + (goto-char start) + (setq label-type nil) + (throw 'check-label nil)) + (and (c-safe (c-forward-sexp) + (c-forward-syntactic-ws) + t) + (not (eobp))))) + + ;; Record the identifiers in the label for fontification, unless + ;; it begins with `c-label-kwds' in which case the following + ;; identifiers are part of a (constant) expression that + ;; shouldn't be fontified. + (when (and c-record-type-identifiers + (progn (goto-char start) + (not (looking-at c-label-kwds-regexp)))) + (while (c-syntactic-re-search-forward c-symbol-key nil t) + (c-record-ref-id (cons (match-beginning 0) + (match-end 0))))) + + (c-put-c-type-property (1- (point-max)) 'c-decl-end) + (goto-char (point-max))))) + + (t + ;; Not a label. + (goto-char start))) + label-type)) + +(defun c-forward-objc-directive () + ;; Assuming the point is at the beginning of a token, try to move + ;; forward to the end of the Objective-C directive that starts + ;; there. Return t if a directive was fully recognized, otherwise + ;; the point is moved as far as one could be successfully parsed and + ;; nil is returned. + ;; + ;; This function records identifier ranges on + ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if + ;; `c-record-type-identifiers' is non-nil. + ;; + ;; This function might do hidden buffer changes. + + (let ((start (point)) + start-char + (c-promote-possible-types t) + lim + ;; Turn off recognition of angle bracket arglists while parsing + ;; types here since the protocol reference list might then be + ;; considered part of the preceding name or superclass-name. + c-recognize-<>-arglists) + + (if (or + (when (looking-at + (eval-when-compile + (c-make-keywords-re t + (append (c-lang-const c-protection-kwds objc) + '("@end")) + 'objc-mode))) + (goto-char (match-end 1)) + t) + + (and + (looking-at + (eval-when-compile + (c-make-keywords-re t + '("@interface" "@implementation" "@protocol") + 'objc-mode))) + + ;; Handle the name of the class itself. + (progn + ; (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's + ; at EOB. + (goto-char (match-end 0)) + (setq lim (point)) + (c-skip-ws-forward) + (c-forward-type)) + + (catch 'break + ;; Look for ": superclass-name" or "( category-name )". + (when (looking-at "[:\(]") + (setq start-char (char-after)) + (forward-char) + (c-forward-syntactic-ws) + (unless (c-forward-type) (throw 'break nil)) + (when (eq start-char ?\() + (unless (eq (char-after) ?\)) (throw 'break nil)) + (forward-char) + (c-forward-syntactic-ws))) + + ;; Look for a protocol reference list. + (if (eq (char-after) ?<) + (let ((c-recognize-<>-arglists t) + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists) + (c-forward-<>-arglist t)) + t)))) + + (progn + (c-backward-syntactic-ws lim) + (c-clear-c-type-property start (1- (point)) 'c-decl-end) + (c-put-c-type-property (1- (point)) 'c-decl-end) + t) + + (c-clear-c-type-property start (point) 'c-decl-end) + nil))) + +(defun c-beginning-of-inheritance-list (&optional lim) + ;; Go to the first non-whitespace after the colon that starts a + ;; multiple inheritance introduction. Optional LIM is the farthest + ;; back we should search. + ;; + ;; This function might do hidden buffer changes. + (c-with-syntax-table c++-template-syntax-table + (c-backward-token-2 0 t lim) + (while (and (or (looking-at c-symbol-start) + (looking-at "[<,]\\|::")) + (zerop (c-backward-token-2 1 t lim)))))) + +(defun c-in-method-def-p () + ;; Return nil if we aren't in a method definition, otherwise the + ;; position of the initial [+-]. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (beginning-of-line) + (and c-opt-method-key + (looking-at c-opt-method-key) + (point)) + )) + +;; Contributed by Kevin Ryde . +(defun c-in-gcc-asm-p () + ;; Return non-nil if point is within a gcc \"asm\" block. + ;; + ;; This should be called with point inside an argument list. + ;; + ;; Only one level of enclosing parentheses is considered, so for + ;; instance `nil' is returned when in a function call within an asm + ;; operand. + ;; + ;; This function might do hidden buffer changes. + + (and c-opt-asm-stmt-key + (save-excursion + (beginning-of-line) + (backward-up-list 1) + (c-beginning-of-statement-1 (point-min) nil t) + (looking-at c-opt-asm-stmt-key)))) + +(defun c-at-toplevel-p () + "Return a determination as to whether point is \"at the top level\". +Informally, \"at the top level\" is anywhere where you can write +a function. + +More precisely, being at the top-level means that point is either +outside any enclosing block (such as a function definition), or +directly inside a class, namespace or other block that contains +another declaration level. + +If point is not at the top-level (e.g. it is inside a method +definition), then nil is returned. Otherwise, if point is at a +top-level not enclosed within a class definition, t is returned. +Otherwise, a 2-vector is returned where the zeroth element is the +buffer position of the start of the class declaration, and the first +element is the buffer position of the enclosing class's opening +brace. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + (let ((paren-state (c-parse-state))) + (or (not (c-most-enclosing-brace paren-state)) + (c-search-uplist-for-classkey paren-state)))) + +(defun c-just-after-func-arglist-p (&optional lim) + ;; Return non-nil if the point is in the region after the argument + ;; list of a function and its opening brace (or semicolon in case it + ;; got no body). If there are K&R style argument declarations in + ;; that region, the point has to be inside the first one for this + ;; function to recognize it. + ;; + ;; If successful, the point is moved to the first token after the + ;; function header (see `c-forward-decl-or-cast-1' for details) and + ;; the position of the opening paren of the function arglist is + ;; returned. + ;; + ;; The point is clobbered if not successful. + ;; + ;; LIM is used as bound for backward buffer searches. + ;; + ;; This function might do hidden buffer changes. + + (let ((beg (point)) id-start) + (and + (eq (c-beginning-of-statement-1 lim) 'same) + + (not (and (c-major-mode-is 'objc-mode) + (c-forward-objc-directive))) + + (setq id-start + (car-safe (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil))) + (< id-start beg) + + ;; There should not be a '=' or ',' between beg and the + ;; start of the declaration since that means we were in the + ;; "expression part" of the declaration. + (or (> (point) beg) + (not (looking-at "[=,]"))) + + (save-excursion + ;; Check that there's an arglist paren in the + ;; declaration. + (goto-char id-start) + (cond ((eq (char-after) ?\() + ;; The declarator is a paren expression, so skip past it + ;; so that we don't get stuck on that instead of the + ;; function arglist. + (c-forward-sexp)) + ((and c-opt-op-identifier-prefix + (looking-at c-opt-op-identifier-prefix)) + ;; Don't trip up on "operator ()". + (c-forward-token-2 2 t))) + (and (< (point) beg) + (c-syntactic-re-search-forward "(" beg t t) + (1- (point))))))) + +(defun c-in-knr-argdecl (&optional lim) + ;; Return the position of the first argument declaration if point is + ;; inside a K&R style argument declaration list, nil otherwise. + ;; `c-recognize-knr-p' is not checked. If LIM is non-nil, it's a + ;; position that bounds the backward search for the argument list. + ;; + ;; Point must be within a possible K&R region, e.g. just before a top-level + ;; "{". It must be outside of parens and brackets. The test can return + ;; false positives otherwise. + ;; + ;; This function might do hidden buffer changes. + + (save-excursion + (save-restriction + ;; If we're in a macro, our search range is restricted to it. Narrow to + ;; the searchable range. + (let* ((macro-start (save-excursion (and (c-beginning-of-macro) (point)))) + (macro-end (save-excursion (and macro-start (c-end-of-macro) (point)))) + (low-lim (max (or lim (point-min)) (or macro-start (point-min)))) + before-lparen after-rparen + (pp-count-out 20)) ; Max number of paren/brace constructs before + ; we give up + (narrow-to-region low-lim (or macro-end (point-max))) + + ;; Search backwards for the defun's argument list. We give up if we + ;; encounter a "}" (end of a previous defun) an "=" (which can't be in + ;; a knr region) or BOB. + ;; + ;; The criterion for a paren structure being the arg list is: + ;; o - there is non-WS stuff after it but before any "{"; AND + ;; o - the token after it isn't a ";" AND + ;; o - it is preceded by either an identifier (the function name) or + ;; a macro expansion like "DEFUN (...)"; AND + ;; o - its content is a non-empty comma-separated list of identifiers + ;; (an empty arg list won't have a knr region). + ;; + ;; The following snippet illustrates these rules: + ;; int foo (bar, baz, yuk) + ;; int bar [] ; + ;; int (*baz) (my_type) ; + ;; int (*) (void) (*yuk) (void) ; + ;; { + + (catch 'knr + (while (> pp-count-out 0) ; go back one paren/bracket pair each time. + (setq pp-count-out (1- pp-count-out)) + (c-syntactic-skip-backward "^)]}=") + (cond ((eq (char-before) ?\)) + (setq after-rparen (point))) + ((eq (char-before) ?\]) + (setq after-rparen nil)) + (t ; either } (hit previous defun) or = or no more + ; parens/brackets. + (throw 'knr nil))) + + (if after-rparen + ;; We're inside a paren. Could it be our argument list....? + (if + (and + (progn + (goto-char after-rparen) + (unless (c-go-list-backward) (throw 'knr nil)) ; + ;; FIXME!!! What about macros between the parens? 2007/01/20 + (setq before-lparen (point))) + + ;; It can't be the arg list if next token is ; or { + (progn (goto-char after-rparen) + (c-forward-syntactic-ws) + (not (memq (char-after) '(?\; ?\{ ?\=)))) + + ;; Is the thing preceding the list an identifier (the + ;; function name), or a macro expansion? + (progn + (goto-char before-lparen) + (eq (c-backward-token-2) 0) + (or (eq (c-on-identifier) (point)) + (and (eq (char-after) ?\)) + (c-go-up-list-backward) + (eq (c-backward-token-2) 0) + (eq (c-on-identifier) (point))))) + + ;; Have we got a non-empty list of comma-separated + ;; identifiers? + (progn + (goto-char before-lparen) + (c-forward-token-2) ; to first token inside parens + (and + (c-on-identifier) + (c-forward-token-2) + (catch 'id-list + (while (eq (char-after) ?\,) + (c-forward-token-2) + (unless (c-on-identifier) (throw 'id-list nil)) + (c-forward-token-2)) + (eq (char-after) ?\)))))) + + ;; ...Yes. We've identified the function's argument list. + (throw 'knr + (progn (goto-char after-rparen) + (c-forward-syntactic-ws) + (point))) + + ;; ...No. The current parens aren't the function's arg list. + (goto-char before-lparen)) + + (or (c-go-list-backward) ; backwards over [ .... ] + (throw 'knr nil))))))))) + +(defun c-skip-conditional () + ;; skip forward over conditional at point, including any predicate + ;; statements in parentheses. No error checking is performed. + ;; + ;; This function might do hidden buffer changes. + (c-forward-sexp (cond + ;; else if() + ((looking-at (concat "\\\\([^_]\\|$\\)")) + 3) + ;; do, else, try, finally + ((looking-at (concat "\\<\\(" + "do\\|else\\|try\\|finally" + "\\)\\>\\([^_]\\|$\\)")) + 1) + ;; for, if, while, switch, catch, synchronized, foreach + (t 2)))) + +(defun c-after-conditional (&optional lim) + ;; If looking at the token after a conditional then return the + ;; position of its start, otherwise return nil. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (and (zerop (c-backward-token-2 1 t lim)) + (or (looking-at c-block-stmt-1-key) + (and (eq (char-after) ?\() + (zerop (c-backward-token-2 1 t lim)) + (looking-at c-block-stmt-2-key))) + (point)))) + +(defun c-after-special-operator-id (&optional lim) + ;; If the point is after an operator identifier that isn't handled + ;; like an ordinary symbol (i.e. like "operator =" in C++) then the + ;; position of the start of that identifier is returned. nil is + ;; returned otherwise. The point may be anywhere in the syntactic + ;; whitespace after the last token of the operator identifier. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + (and c-overloadable-operators-regexp + (zerop (c-backward-token-2 1 nil lim)) + (looking-at c-overloadable-operators-regexp) + (or (not c-opt-op-identifier-prefix) + (and + (zerop (c-backward-token-2 1 nil lim)) + (looking-at c-opt-op-identifier-prefix))) + (point)))) + +(defsubst c-backward-to-block-anchor (&optional lim) + ;; Assuming point is at a brace that opens a statement block of some + ;; kind, move to the proper anchor point for that block. It might + ;; need to be adjusted further by c-add-stmt-syntax, but the + ;; position at return is suitable as start position for that + ;; function. + ;; + ;; This function might do hidden buffer changes. + (unless (= (point) (c-point 'boi)) + (let ((start (c-after-conditional lim))) + (if start + (goto-char start))))) + +(defsubst c-backward-to-decl-anchor (&optional lim) + ;; Assuming point is at a brace that opens the block of a top level + ;; declaration of some kind, move to the proper anchor point for + ;; that block. + ;; + ;; This function might do hidden buffer changes. + (unless (= (point) (c-point 'boi)) + (c-beginning-of-statement-1 lim))) + +(defun c-search-decl-header-end () + ;; Search forward for the end of the "header" of the current + ;; declaration. That's the position where the definition body + ;; starts, or the first variable initializer, or the ending + ;; semicolon. I.e. search forward for the closest following + ;; (syntactically relevant) '{', '=' or ';' token. Point is left + ;; _after_ the first found token, or at point-max if none is found. + ;; + ;; This function might do hidden buffer changes. + + (let ((base (point))) + (if (c-major-mode-is 'c++-mode) + + ;; In C++ we need to take special care to handle operator + ;; tokens and those pesky template brackets. + (while (and + (c-syntactic-re-search-forward "[;{<=]" nil 'move t t) + (or + (c-end-of-current-token base) + ;; Handle operator identifiers, i.e. ignore any + ;; operator token preceded by "operator". + (save-excursion + (and (c-safe (c-backward-sexp) t) + (looking-at c-opt-op-identifier-prefix))) + (and (eq (char-before) ?<) + (c-with-syntax-table c++-template-syntax-table + (if (c-safe (goto-char (c-up-list-forward (point)))) + t + (goto-char (point-max)) + nil))))) + (setq base (point))) + + (while (and + (c-syntactic-re-search-forward "[;{=]" nil 'move t t) + (c-end-of-current-token base)) + (setq base (point)))))) + +(defun c-beginning-of-decl-1 (&optional lim) + ;; Go to the beginning of the current declaration, or the beginning + ;; of the previous one if already at the start of it. Point won't + ;; be moved out of any surrounding paren. Return a cons cell of the + ;; form (MOVE . KNR-POS). MOVE is like the return value from + ;; `c-beginning-of-statement-1'. If point skipped over some K&R + ;; style argument declarations (and they are to be recognized) then + ;; KNR-POS is set to the start of the first such argument + ;; declaration, otherwise KNR-POS is nil. If LIM is non-nil, it's a + ;; position that bounds the backward search. + ;; + ;; NB: Cases where the declaration continues after the block, as in + ;; "struct foo { ... } bar;", are currently recognized as two + ;; declarations, e.g. "struct foo { ... }" and "bar;" in this case. + ;; + ;; This function might do hidden buffer changes. + (catch 'return + (let* ((start (point)) + (last-stmt-start (point)) + (move (c-beginning-of-statement-1 lim nil t))) + + ;; `c-beginning-of-statement-1' stops at a block start, but we + ;; want to continue if the block doesn't begin a top level + ;; construct, i.e. if it isn't preceded by ';', '}', ':', bob, + ;; or an open paren. + (let ((beg (point)) tentative-move) + ;; Go back one "statement" each time round the loop until we're just + ;; after a ;, }, or :, or at BOB or the start of a macro or start of + ;; an ObjC method. This will move over a multiple declaration whose + ;; components are comma separated. + (while (and + ;; Must check with c-opt-method-key in ObjC mode. + (not (and c-opt-method-key + (looking-at c-opt-method-key))) + (/= last-stmt-start (point)) + (progn + (c-backward-syntactic-ws lim) + (not (memq (char-before) '(?\; ?} ?: nil)))) + (save-excursion + (backward-char) + (not (looking-at "\\s("))) + ;; Check that we don't move from the first thing in a + ;; macro to its header. + (not (eq (setq tentative-move + (c-beginning-of-statement-1 lim nil t)) + 'macro))) + (setq last-stmt-start beg + beg (point) + move tentative-move)) + (goto-char beg)) + + (when c-recognize-knr-p + (let ((fallback-pos (point)) knr-argdecl-start) + ;; Handle K&R argdecls. Back up after the "statement" jumped + ;; over by `c-beginning-of-statement-1', unless it was the + ;; function body, in which case we're sitting on the opening + ;; brace now. Then test if we're in a K&R argdecl region and + ;; that we started at the other side of the first argdecl in + ;; it. + (unless (eq (char-after) ?{) + (goto-char last-stmt-start)) + (if (and (setq knr-argdecl-start (c-in-knr-argdecl lim)) + (< knr-argdecl-start start) + (progn + (goto-char knr-argdecl-start) + (not (eq (c-beginning-of-statement-1 lim nil t) 'macro)))) + (throw 'return + (cons (if (eq (char-after fallback-pos) ?{) + 'previous + 'same) + knr-argdecl-start)) + (goto-char fallback-pos)))) + + ;; `c-beginning-of-statement-1' counts each brace block as a separate + ;; statement, so the result will be 'previous if we've moved over any. + ;; So change our result back to 'same if necessary. + ;; + ;; If they were brace list initializers we might not have moved over a + ;; declaration boundary though, so change it to 'same if we've moved + ;; past a '=' before '{', but not ';'. (This ought to be integrated + ;; into `c-beginning-of-statement-1', so we avoid this extra pass which + ;; potentially can search over a large amount of text.). Take special + ;; pains not to get mislead by C++'s "operator=", and the like. + (if (and (eq move 'previous) + (c-with-syntax-table (if (c-major-mode-is 'c++-mode) + c++-template-syntax-table + (syntax-table)) + (save-excursion + (and + (progn + (while ; keep going back to "[;={"s until we either find + ; no more, or get to one which isn't an "operator =" + (and (c-syntactic-re-search-forward "[;={]" start t t t) + (eq (char-before) ?=) + c-overloadable-operators-regexp + c-opt-op-identifier-prefix + (save-excursion + (eq (c-backward-token-2) 0) + (looking-at c-overloadable-operators-regexp) + (eq (c-backward-token-2) 0) + (looking-at c-opt-op-identifier-prefix)))) + (eq (char-before) ?=)) + (c-syntactic-re-search-forward "[;{]" start t t) + (eq (char-before) ?{) + (c-safe (goto-char (c-up-list-forward (point))) t) + (not (c-syntactic-re-search-forward ";" start t t)))))) + (cons 'same nil) + (cons move nil))))) + +(defun c-end-of-decl-1 () + ;; Assuming point is at the start of a declaration (as detected by + ;; e.g. `c-beginning-of-decl-1'), go to the end of it. Unlike + ;; `c-beginning-of-decl-1', this function handles the case when a + ;; block is followed by identifiers in e.g. struct declarations in C + ;; or C++. If a proper end was found then t is returned, otherwise + ;; point is moved as far as possible within the current sexp and nil + ;; is returned. This function doesn't handle macros; use + ;; `c-end-of-macro' instead in those cases. + ;; + ;; This function might do hidden buffer changes. + (let ((start (point)) + (decl-syntax-table (if (c-major-mode-is 'c++-mode) + c++-template-syntax-table + (syntax-table)))) + (catch 'return + (c-search-decl-header-end) + + (when (and c-recognize-knr-p + (eq (char-before) ?\;) + (c-in-knr-argdecl start)) + ;; Stopped at the ';' in a K&R argdecl section which is + ;; detected using the same criteria as in + ;; `c-beginning-of-decl-1'. Move to the following block + ;; start. + (c-syntactic-re-search-forward "{" nil 'move t)) + + (when (eq (char-before) ?{) + ;; Encountered a block in the declaration. Jump over it. + (condition-case nil + (goto-char (c-up-list-forward (point))) + (error (goto-char (point-max)) + (throw 'return nil))) + (if (or (not c-opt-block-decls-with-vars-key) + (save-excursion + (c-with-syntax-table decl-syntax-table + (let ((lim (point))) + (goto-char start) + (not (and + ;; Check for `c-opt-block-decls-with-vars-key' + ;; before the first paren. + (c-syntactic-re-search-forward + (concat "[;=\(\[{]\\|\\(" + c-opt-block-decls-with-vars-key + "\\)") + lim t t t) + (match-beginning 1) + (not (eq (char-before) ?_)) + ;; Check that the first following paren is + ;; the block. + (c-syntactic-re-search-forward "[;=\(\[{]" + lim t t t) + (eq (char-before) ?{))))))) + ;; The declaration doesn't have any of the + ;; `c-opt-block-decls-with-vars' keywords in the + ;; beginning, so it ends here at the end of the block. + (throw 'return t))) + + (c-with-syntax-table decl-syntax-table + (while (progn + (if (eq (char-before) ?\;) + (throw 'return t)) + (c-syntactic-re-search-forward ";" nil 'move t)))) + nil))) + +(defun c-looking-at-decl-block (containing-sexp goto-start &optional limit) + ;; Assuming the point is at an open brace, check if it starts a + ;; block that contains another declaration level, i.e. that isn't a + ;; statement block or a brace list, and if so return non-nil. + ;; + ;; If the check is successful, the return value is the start of the + ;; keyword that tells what kind of construct it is, i.e. typically + ;; what `c-decl-block-key' matched. Also, if GOTO-START is set then + ;; the point will be at the start of the construct, before any + ;; leading specifiers, otherwise it's at the returned position. + ;; + ;; The point is clobbered if the check is unsuccessful. + ;; + ;; CONTAINING-SEXP is the position of the open of the surrounding + ;; paren, or nil if none. + ;; + ;; The optional LIMIT limits the backward search for the start of + ;; the construct. It's assumed to be at a syntactically relevant + ;; position. + ;; + ;; If any template arglists are found in the searched region before + ;; the open brace, they get marked with paren syntax. + ;; + ;; This function might do hidden buffer changes. + + (let ((open-brace (point)) kwd-start first-specifier-pos) + (c-syntactic-skip-backward c-block-prefix-charset limit t) + + (when (and c-recognize-<>-arglists + (eq (char-before) ?>)) + ;; Could be at the end of a template arglist. + (let ((c-parse-and-markup-<>-arglists t)) + (while (and + (c-backward-<>-arglist nil limit) + (progn + (c-syntactic-skip-backward c-block-prefix-charset limit t) + (eq (char-before) ?>)))))) + + ;; Note: Can't get bogus hits inside template arglists below since they + ;; have gotten paren syntax above. + (when (and + ;; If `goto-start' is set we begin by searching for the + ;; first possible position of a leading specifier list. + ;; The `c-decl-block-key' search continues from there since + ;; we know it can't match earlier. + (if goto-start + (when (c-syntactic-re-search-forward c-symbol-start + open-brace t t) + (goto-char (setq first-specifier-pos (match-beginning 0))) + t) + t) + + (cond + ((c-syntactic-re-search-forward c-decl-block-key open-brace t t t) + (goto-char (setq kwd-start (match-beginning 0))) + (or + + ;; Found a keyword that can't be a type? + (match-beginning 1) + + ;; Can be a type too, in which case it's the return type of a + ;; function (under the assumption that no declaration level + ;; block construct starts with a type). + (not (c-forward-type)) + + ;; Jumped over a type, but it could be a declaration keyword + ;; followed by the declared identifier that we've jumped over + ;; instead (e.g. in "class Foo {"). If it indeed is a type + ;; then we should be at the declarator now, so check for a + ;; valid declarator start. + ;; + ;; Note: This doesn't cope with the case when a declared + ;; identifier is followed by e.g. '(' in a language where '(' + ;; also might be part of a declarator expression. Currently + ;; there's no such language. + (not (or (looking-at c-symbol-start) + (looking-at c-type-decl-prefix-key))))) + + ;; In Pike a list of modifiers may be followed by a brace + ;; to make them apply to many identifiers. Note that the + ;; match data will be empty on return in this case. + ((and (c-major-mode-is 'pike-mode) + (progn + (goto-char open-brace) + (= (c-backward-token-2) 0)) + (looking-at c-specifier-key) + ;; Use this variant to avoid yet another special regexp. + (c-keyword-member (c-keyword-sym (match-string 1)) + 'c-modifier-kwds)) + (setq kwd-start (point)) + t))) + + ;; Got a match. + + (if goto-start + ;; Back up over any preceding specifiers and their clauses + ;; by going forward from `first-specifier-pos', which is the + ;; earliest possible position where the specifier list can + ;; start. + (progn + (goto-char first-specifier-pos) + + (while (< (point) kwd-start) + (if (looking-at c-symbol-key) + ;; Accept any plain symbol token on the ground that + ;; it's a specifier masked through a macro (just + ;; like `c-forward-decl-or-cast-1' skip forward over + ;; such tokens). + ;; + ;; Could be more restrictive wrt invalid keywords, + ;; but that'd only occur in invalid code so there's + ;; no use spending effort on it. + (let ((end (match-end 0))) + (unless (c-forward-keyword-clause 0) + (goto-char end) + (c-forward-syntactic-ws))) + + ;; Can't parse a declaration preamble and is still + ;; before `kwd-start'. That means `first-specifier-pos' + ;; was in some earlier construct. Search again. + (if (c-syntactic-re-search-forward c-symbol-start + kwd-start 'move t) + (goto-char (setq first-specifier-pos (match-beginning 0))) + ;; Got no preamble before the block declaration keyword. + (setq first-specifier-pos kwd-start)))) + + (goto-char first-specifier-pos)) + (goto-char kwd-start)) + + kwd-start))) + +(defun c-search-uplist-for-classkey (paren-state) + ;; Check if the closest containing paren sexp is a declaration + ;; block, returning a 2 element vector in that case. Aref 0 + ;; contains the bufpos at boi of the class key line, and aref 1 + ;; contains the bufpos of the open brace. This function is an + ;; obsolete wrapper for `c-looking-at-decl-block'. + ;; + ;; This function might do hidden buffer changes. + (let ((open-paren-pos (c-most-enclosing-brace paren-state))) + (when open-paren-pos + (save-excursion + (goto-char open-paren-pos) + (when (and (eq (char-after) ?{) + (c-looking-at-decl-block + (c-safe-position open-paren-pos paren-state) + nil)) + (back-to-indentation) + (vector (point) open-paren-pos)))))) + +;;;; 2007-03-29: Inserted the following two defs from cc-engine.C-M-ae.el. +;;;; Test these! FIXME!!! +(defmacro c-pull-open-brace (ps) + ;; Pull the next open brace from PS (which has the form of paren-state), + ;; skipping over any brace pairs. Returns NIL when PS is exhausted. + `(progn + (while (consp (car ,ps)) + (setq ,ps (cdr ,ps))) + (prog1 (car ,ps) + (setq ,ps (cdr ,ps))))) + +(defun c-most-enclosing-decl-block (paren-state) + ;; Return the buffer position of the most enclosing decl-block brace (in the + ;; sense of c-looking-at-decl-block) in the PAREN-STATE structure, or nil if + ;; none was found. + (let* ((open-brace (c-pull-open-brace paren-state)) + (next-open-brace (c-pull-open-brace paren-state))) + (while (and open-brace + (save-excursion + (goto-char open-brace) + (not (c-looking-at-decl-block next-open-brace nil)))) + (setq open-brace next-open-brace + next-open-brace (c-pull-open-brace paren-state))) + open-brace)) + +(defun c-cheap-inside-bracelist-p (paren-state) + ;; Return the position of the L-brace if point is inside a brace list + ;; initialization of an array, etc. This is an approximate function, + ;; designed for speed over accuracy. It will not find every bracelist, but + ;; a non-nil result is reliable. We simply search for "= {" (naturally with + ;; syntactic whitespace allowed). PAREN-STATE is the normal thing that it + ;; is everywhere else. + (let (b-pos) + (save-excursion + (while + (and (setq b-pos (c-pull-open-brace paren-state)) + (progn (goto-char b-pos) + (c-backward-sws) + (c-backward-token-2) + (not (looking-at "="))))) + b-pos))) + +(defun c-inside-bracelist-p (containing-sexp paren-state) + ;; return the buffer position of the beginning of the brace list + ;; statement if we're inside a brace list, otherwise return nil. + ;; CONTAINING-SEXP is the buffer pos of the innermost containing + ;; paren. PAREN-STATE is the remainder of the state of enclosing + ;; braces + ;; + ;; N.B.: This algorithm can potentially get confused by cpp macros + ;; placed in inconvenient locations. It's a trade-off we make for + ;; speed. + ;; + ;; This function might do hidden buffer changes. + (or + ;; This will pick up brace list declarations. + (c-safe + (save-excursion + (goto-char containing-sexp) + (c-forward-sexp -1) + (let (bracepos) + (if (and (or (looking-at c-brace-list-key) + (progn (c-forward-sexp -1) + (looking-at c-brace-list-key))) + (setq bracepos (c-down-list-forward (point))) + (not (c-crosses-statement-barrier-p (point) + (- bracepos 2)))) + (point))))) + ;; this will pick up array/aggregate init lists, even if they are nested. + (save-excursion + (let ((class-key + ;; Pike can have class definitions anywhere, so we must + ;; check for the class key here. + (and (c-major-mode-is 'pike-mode) + c-decl-block-key)) + bufpos braceassignp lim next-containing) + (while (and (not bufpos) + containing-sexp) + (when paren-state + (if (consp (car paren-state)) + (setq lim (cdr (car paren-state)) + paren-state (cdr paren-state)) + (setq lim (car paren-state))) + (when paren-state + (setq next-containing (car paren-state) + paren-state (cdr paren-state)))) + (goto-char containing-sexp) + (if (c-looking-at-inexpr-block next-containing next-containing) + ;; We're in an in-expression block of some kind. Do not + ;; check nesting. We deliberately set the limit to the + ;; containing sexp, so that c-looking-at-inexpr-block + ;; doesn't check for an identifier before it. + (setq containing-sexp nil) + ;; see if the open brace is preceded by = or [...] in + ;; this statement, but watch out for operator= + (setq braceassignp 'dontknow) + (c-backward-token-2 1 t lim) + ;; Checks to do only on the first sexp before the brace. + (when (and c-opt-inexpr-brace-list-key + (eq (char-after) ?\[)) + ;; In Java, an initialization brace list may follow + ;; directly after "new Foo[]", so check for a "new" + ;; earlier. + (while (eq braceassignp 'dontknow) + (setq braceassignp + (cond ((/= (c-backward-token-2 1 t lim) 0) nil) + ((looking-at c-opt-inexpr-brace-list-key) t) + ((looking-at "\\sw\\|\\s_\\|[.[]") + ;; Carry on looking if this is an + ;; identifier (may contain "." in Java) + ;; or another "[]" sexp. + 'dontknow) + (t nil))))) + ;; Checks to do on all sexps before the brace, up to the + ;; beginning of the statement. + (while (eq braceassignp 'dontknow) + (cond ((eq (char-after) ?\;) + (setq braceassignp nil)) + ((and class-key + (looking-at class-key)) + (setq braceassignp nil)) + ((eq (char-after) ?=) + ;; We've seen a =, but must check earlier tokens so + ;; that it isn't something that should be ignored. + (setq braceassignp 'maybe) + (while (and (eq braceassignp 'maybe) + (zerop (c-backward-token-2 1 t lim))) + (setq braceassignp + (cond + ;; Check for operator = + ((and c-opt-op-identifier-prefix + (looking-at c-opt-op-identifier-prefix)) + nil) + ;; Check for `= in Pike. + ((and (c-major-mode-is 'pike-mode) + (or (eq (char-after) ?`) + ;; Special case for Pikes + ;; `[]=, since '[' is not in + ;; the punctuation class. + (and (eq (char-after) ?\[) + (eq (char-before) ?`)))) + nil) + ((looking-at "\\s.") 'maybe) + ;; make sure we're not in a C++ template + ;; argument assignment + ((and + (c-major-mode-is 'c++-mode) + (save-excursion + (let ((here (point)) + (pos< (progn + (skip-chars-backward "^<>") + (point)))) + (and (eq (char-before) ?<) + (not (c-crosses-statement-barrier-p + pos< here)) + (not (c-in-literal)) + )))) + nil) + (t t)))))) + (if (and (eq braceassignp 'dontknow) + (/= (c-backward-token-2 1 t lim) 0)) + (setq braceassignp nil))) + (if (not braceassignp) + (if (eq (char-after) ?\;) + ;; Brace lists can't contain a semicolon, so we're done. + (setq containing-sexp nil) + ;; Go up one level. + (setq containing-sexp next-containing + lim nil + next-containing nil)) + ;; we've hit the beginning of the aggregate list + (c-beginning-of-statement-1 + (c-most-enclosing-brace paren-state)) + (setq bufpos (point)))) + ) + bufpos)) + )) + +(defun c-looking-at-special-brace-list (&optional lim) + ;; If we're looking at the start of a pike-style list, ie `({ })', + ;; `([ ])', `(< >)' etc, a cons of a cons of its starting and ending + ;; positions and its entry in c-special-brace-lists is returned, nil + ;; otherwise. The ending position is nil if the list is still open. + ;; LIM is the limit for forward search. The point may either be at + ;; the `(' or at the following paren character. Tries to check the + ;; matching closer, but assumes it's correct if no balanced paren is + ;; found (i.e. the case `({ ... } ... )' is detected as _not_ being + ;; a special brace list). + ;; + ;; This function might do hidden buffer changes. + (if c-special-brace-lists + (condition-case () + (save-excursion + (let ((beg (point)) + inner-beg end type) + (c-forward-syntactic-ws) + (if (eq (char-after) ?\() + (progn + (forward-char 1) + (c-forward-syntactic-ws) + (setq inner-beg (point)) + (setq type (assq (char-after) c-special-brace-lists))) + (if (setq type (assq (char-after) c-special-brace-lists)) + (progn + (setq inner-beg (point)) + (c-backward-syntactic-ws) + (forward-char -1) + (setq beg (if (eq (char-after) ?\() + (point) + nil))))) + (if (and beg type) + (if (and (c-safe + (goto-char beg) + (c-forward-sexp 1) + (setq end (point)) + (= (char-before) ?\))) + (c-safe + (goto-char inner-beg) + (if (looking-at "\\s(") + ;; Check balancing of the inner paren + ;; below. + (progn + (c-forward-sexp 1) + t) + ;; If the inner char isn't a paren then + ;; we can't check balancing, so just + ;; check the char before the outer + ;; closing paren. + (goto-char end) + (backward-char) + (c-backward-syntactic-ws) + (= (char-before) (cdr type))))) + (if (or (/= (char-syntax (char-before)) ?\)) + (= (progn + (c-forward-syntactic-ws) + (point)) + (1- end))) + (cons (cons beg end) type)) + (cons (list beg) type))))) + (error nil)))) + +(defun c-looking-at-bos (&optional lim) + ;; Return non-nil if between two statements or declarations, assuming + ;; point is not inside a literal or comment. + ;; + ;; Obsolete - `c-at-statement-start-p' or `c-at-expression-start-p' + ;; are recommended instead. + ;; + ;; This function might do hidden buffer changes. + (c-at-statement-start-p)) +(make-obsolete 'c-looking-at-bos 'c-at-statement-start-p nil) + +(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end) + ;; Return non-nil if we're looking at the beginning of a block + ;; inside an expression. The value returned is actually a cons of + ;; either 'inlambda, 'inexpr-statement or 'inexpr-class and the + ;; position of the beginning of the construct. + ;; + ;; LIM limits the backward search. CONTAINING-SEXP is the start + ;; position of the closest containing list. If it's nil, the + ;; containing paren isn't used to decide whether we're inside an + ;; expression or not. If both LIM and CONTAINING-SEXP are used, LIM + ;; needs to be farther back. + ;; + ;; If CHECK-AT-END is non-nil then extra checks at the end of the + ;; brace block might be done. It should only be used when the + ;; construct can be assumed to be complete, i.e. when the original + ;; starting position was further down than that. + ;; + ;; This function might do hidden buffer changes. + + (save-excursion + (let ((res 'maybe) passed-paren + (closest-lim (or containing-sexp lim (point-min))) + ;; Look at the character after point only as a last resort + ;; when we can't disambiguate. + (block-follows (and (eq (char-after) ?{) (point)))) + + (while (and (eq res 'maybe) + (progn (c-backward-syntactic-ws) + (> (point) closest-lim)) + (not (bobp)) + (progn (backward-char) + (looking-at "[\]\).]\\|\\w\\|\\s_")) + (c-safe (forward-char) + (goto-char (scan-sexps (point) -1)))) + + (setq res + (if (looking-at c-keywords-regexp) + (let ((kw-sym (c-keyword-sym (match-string 1)))) + (cond + ((and block-follows + (c-keyword-member kw-sym 'c-inexpr-class-kwds)) + (and (not (eq passed-paren ?\[)) + (or (not (looking-at c-class-key)) + ;; If the class definition is at the start of + ;; a statement, we don't consider it an + ;; in-expression class. + (let ((prev (point))) + (while (and + (= (c-backward-token-2 1 nil closest-lim) 0) + (eq (char-syntax (char-after)) ?w)) + (setq prev (point))) + (goto-char prev) + (not (c-at-statement-start-p))) + ;; Also, in Pike we treat it as an + ;; in-expression class if it's used in an + ;; object clone expression. + (save-excursion + (and check-at-end + (c-major-mode-is 'pike-mode) + (progn (goto-char block-follows) + (zerop (c-forward-token-2 1 t))) + (eq (char-after) ?\()))) + (cons 'inexpr-class (point)))) + ((c-keyword-member kw-sym 'c-inexpr-block-kwds) + (when (not passed-paren) + (cons 'inexpr-statement (point)))) + ((c-keyword-member kw-sym 'c-lambda-kwds) + (when (or (not passed-paren) + (eq passed-paren ?\()) + (cons 'inlambda (point)))) + ((c-keyword-member kw-sym 'c-block-stmt-kwds) + nil) + (t + 'maybe))) + + (if (looking-at "\\s(") + (if passed-paren + (if (and (eq passed-paren ?\[) + (eq (char-after) ?\[)) + ;; Accept several square bracket sexps for + ;; Java array initializations. + 'maybe) + (setq passed-paren (char-after)) + 'maybe) + 'maybe)))) + + (if (eq res 'maybe) + (when (and c-recognize-paren-inexpr-blocks + block-follows + containing-sexp + (eq (char-after containing-sexp) ?\()) + (goto-char containing-sexp) + (if (or (save-excursion + (c-backward-syntactic-ws lim) + (and (> (point) (or lim (point-min))) + (c-on-identifier))) + (and c-special-brace-lists + (c-looking-at-special-brace-list))) + nil + (cons 'inexpr-statement (point)))) + + res)))) + +(defun c-looking-at-inexpr-block-backward (paren-state) + ;; Returns non-nil if we're looking at the end of an in-expression + ;; block, otherwise the same as `c-looking-at-inexpr-block'. + ;; PAREN-STATE is the paren state relevant at the current position. + ;; + ;; This function might do hidden buffer changes. + (save-excursion + ;; We currently only recognize a block. + (let ((here (point)) + (elem (car-safe paren-state)) + containing-sexp) + (when (and (consp elem) + (progn (goto-char (cdr elem)) + (c-forward-syntactic-ws here) + (= (point) here))) + (goto-char (car elem)) + (if (setq paren-state (cdr paren-state)) + (setq containing-sexp (car-safe paren-state))) + (c-looking-at-inexpr-block (c-safe-position containing-sexp + paren-state) + containing-sexp))))) + +(defun c-at-macro-vsemi-p (&optional pos) + ;; Is there a "virtual semicolon" at POS or point? + ;; (See cc-defs.el for full details of "virtual semicolons".) + ;; + ;; This is true when point is at the last non syntactic WS position on the + ;; line, there is a macro call last on the line, and this particular macro's + ;; name is defined by the regexp `c-vs-macro-regexp' as not needing a + ;; semicolon. + (save-excursion + (save-restriction + (widen) + (if pos + (goto-char pos) + (setq pos (point))) + (and + c-macro-with-semi-re + (eq (skip-chars-backward " \t") 0) + + ;; Check we've got nothing after this except comments and empty lines + ;; joined by escaped EOLs. + (skip-chars-forward " \t") ; always returns non-nil. + (progn + (while ; go over 1 block comment per iteration. + (and + (looking-at "\\(\\\\[\n\r][ \t]*\\)*") + (goto-char (match-end 0)) + (cond + ((looking-at c-block-comment-start-regexp) + (and (forward-comment 1) + (skip-chars-forward " \t"))) ; always returns non-nil + ((looking-at c-line-comment-start-regexp) + (end-of-line) + nil) + (t nil)))) + (eolp)) + + (goto-char pos) + (progn (c-backward-syntactic-ws) + (eq (point) pos)) + + ;; Check for one of the listed macros being before point. + (or (not (eq (char-before) ?\))) + (when (c-go-list-backward) + (c-backward-syntactic-ws) + t)) + (c-simple-skip-symbol-backward) + (looking-at c-macro-with-semi-re) + (goto-char pos) + (not (c-in-literal)))))) ; The most expensive check last. + +(defun c-macro-vsemi-status-unknown-p () t) ; See cc-defs.el. + + +;; `c-guess-basic-syntax' and the functions that precedes it below +;; implements the main decision tree for determining the syntactic +;; analysis of the current line of code. + +;; Dynamically bound to t when `c-guess-basic-syntax' is called during +;; auto newline analysis. +(defvar c-auto-newline-analysis nil) + +(defun c-brace-anchor-point (bracepos) + ;; BRACEPOS is the position of a brace in a construct like "namespace + ;; Bar {". Return the anchor point in this construct; this is the + ;; earliest symbol on the brace's line which isn't earlier than + ;; "namespace". + ;; + ;; Currently (2007-08-17), "like namespace" means "matches + ;; c-other-block-decl-kwds". It doesn't work with "class" or "struct" + ;; or anything like that. + (save-excursion + (let ((boi (c-point 'boi bracepos))) + (goto-char bracepos) + (while (and (> (point) boi) + (not (looking-at c-other-decl-block-key))) + (c-backward-token-2)) + (if (> (point) boi) (point) boi)))) + +(defsubst c-add-syntax (symbol &rest args) + ;; A simple function to prepend a new syntax element to + ;; `c-syntactic-context'. Using `setq' on it is unsafe since it + ;; should always be dynamically bound but since we read it first + ;; we'll fail properly anyway if this function is misused. + (setq c-syntactic-context (cons (cons symbol args) + c-syntactic-context))) + +(defsubst c-append-syntax (symbol &rest args) + ;; Like `c-add-syntax' but appends to the end of the syntax list. + ;; (Normally not necessary.) + (setq c-syntactic-context (nconc c-syntactic-context + (list (cons symbol args))))) + +(defun c-add-stmt-syntax (syntax-symbol + syntax-extra-args + stop-at-boi-only + containing-sexp + paren-state) + ;; Add the indicated SYNTAX-SYMBOL to `c-syntactic-context', extending it as + ;; needed with further syntax elements of the types `substatement', + ;; `inexpr-statement', `arglist-cont-nonempty', `statement-block-intro', and + ;; `defun-block-intro'. + ;; + ;; Do the generic processing to anchor the given syntax symbol on + ;; the preceding statement: Skip over any labels and containing + ;; statements on the same line, and then search backward until we + ;; find a statement or block start that begins at boi without a + ;; label or comment. + ;; + ;; Point is assumed to be at the prospective anchor point for the + ;; given SYNTAX-SYMBOL. More syntax entries are added if we need to + ;; skip past open parens and containing statements. Most of the added + ;; syntax elements will get the same anchor point - the exception is + ;; for an anchor in a construct like "namespace"[*] - this is as early + ;; as possible in the construct but on the same line as the {. + ;; + ;; [*] i.e. with a keyword matching c-other-block-decl-kwds. + ;; + ;; SYNTAX-EXTRA-ARGS are a list of the extra arguments for the + ;; syntax symbol. They are appended after the anchor point. + ;; + ;; If STOP-AT-BOI-ONLY is nil, we can stop in the middle of the line + ;; if the current statement starts there. + ;; + ;; Note: It's not a problem if PAREN-STATE "overshoots" + ;; CONTAINING-SEXP, i.e. contains info about parens further down. + ;; + ;; This function might do hidden buffer changes. + + (if (= (point) (c-point 'boi)) + ;; This is by far the most common case, so let's give it special + ;; treatment. + (apply 'c-add-syntax syntax-symbol (point) syntax-extra-args) + + (let ((syntax-last c-syntactic-context) + (boi (c-point 'boi)) + ;; Set when we're on a label, so that we don't stop there. + ;; FIXME: To be complete we should check if we're on a label + ;; now at the start. + on-label) + + ;; Use point as the anchor point for "namespace", "extern", etc. + (apply 'c-add-syntax syntax-symbol + (if (rassq syntax-symbol c-other-decl-block-key-in-symbols-alist) + (point) nil) + syntax-extra-args) + + ;; Loop while we have to back out of containing blocks. + (while + (and + (catch 'back-up-block + + ;; Loop while we have to back up statements. + (while (or (/= (point) boi) + on-label + (looking-at c-comment-start-regexp)) + + ;; Skip past any comments that stands between the + ;; statement start and boi. + (let ((savepos (point))) + (while (and (/= savepos boi) + (c-backward-single-comment)) + (setq savepos (point) + boi (c-point 'boi))) + (goto-char savepos)) + + ;; Skip to the beginning of this statement or backward + ;; another one. + (let ((old-pos (point)) + (old-boi boi) + (step-type (c-beginning-of-statement-1 containing-sexp))) + (setq boi (c-point 'boi) + on-label (eq step-type 'label)) + + (cond ((= (point) old-pos) + ;; If we didn't move we're at the start of a block and + ;; have to continue outside it. + (throw 'back-up-block t)) + + ((and (eq step-type 'up) + (>= (point) old-boi) + (looking-at "else\\>[^_]") + (save-excursion + (goto-char old-pos) + (looking-at "if\\>[^_]"))) + ;; Special case to avoid deeper and deeper indentation + ;; of "else if" clauses. + ) + + ((and (not stop-at-boi-only) + (/= old-pos old-boi) + (memq step-type '(up previous))) + ;; If stop-at-boi-only is nil, we shouldn't back up + ;; over previous or containing statements to try to + ;; reach boi, so go back to the last position and + ;; exit. + (goto-char old-pos) + (throw 'back-up-block nil)) + + (t + (if (and (not stop-at-boi-only) + (memq step-type '(up previous beginning))) + ;; If we've moved into another statement then we + ;; should no longer try to stop in the middle of a + ;; line. + (setq stop-at-boi-only t)) + + ;; Record this as a substatement if we skipped up one + ;; level. + (when (eq step-type 'up) + (c-add-syntax 'substatement nil)))) + ))) + + containing-sexp) + + ;; Now we have to go out of this block. + (goto-char containing-sexp) + + ;; Don't stop in the middle of a special brace list opener + ;; like "({". + (when c-special-brace-lists + (let ((special-list (c-looking-at-special-brace-list))) + (when (and special-list + (< (car (car special-list)) (point))) + (setq containing-sexp (car (car special-list))) + (goto-char containing-sexp)))) + + (setq paren-state (c-whack-state-after containing-sexp paren-state) + containing-sexp (c-most-enclosing-brace paren-state) + boi (c-point 'boi)) + + ;; Analyze the construct in front of the block we've stepped out + ;; from and add the right syntactic element for it. + (let ((paren-pos (point)) + (paren-char (char-after)) + step-type) + + (if (eq paren-char ?\() + ;; Stepped out of a parenthesis block, so we're in an + ;; expression now. + (progn + (when (/= paren-pos boi) + (if (and c-recognize-paren-inexpr-blocks + (progn + (c-backward-syntactic-ws containing-sexp) + (or (not (looking-at "\\>")) + (not (c-on-identifier)))) + (save-excursion + (goto-char (1+ paren-pos)) + (c-forward-syntactic-ws) + (eq (char-after) ?{))) + ;; Stepped out of an in-expression statement. This + ;; syntactic element won't get an anchor pos. + (c-add-syntax 'inexpr-statement) + + ;; A parenthesis normally belongs to an arglist. + (c-add-syntax 'arglist-cont-nonempty nil paren-pos))) + + (goto-char (max boi + (if containing-sexp + (1+ containing-sexp) + (point-min)))) + (setq step-type 'same + on-label nil)) + + ;; Stepped out of a brace block. + (setq step-type (c-beginning-of-statement-1 containing-sexp) + on-label (eq step-type 'label)) + + (if (and (eq step-type 'same) + (/= paren-pos (point))) + (let (inexpr) + (cond + ((save-excursion + (goto-char paren-pos) + (setq inexpr (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + containing-sexp))) + (c-add-syntax (if (eq (car inexpr) 'inlambda) + 'defun-block-intro + 'statement-block-intro) + nil)) + ((looking-at c-other-decl-block-key) + (c-add-syntax + (cdr (assoc (match-string 1) + c-other-decl-block-key-in-symbols-alist)) + (max (c-point 'boi paren-pos) (point)))) + (t (c-add-syntax 'defun-block-intro nil)))) + + (c-add-syntax 'statement-block-intro nil))) + + (if (= paren-pos boi) + ;; Always done if the open brace was at boi. The + ;; c-beginning-of-statement-1 call above is necessary + ;; anyway, to decide the type of block-intro to add. + (goto-char paren-pos) + (setq boi (c-point 'boi))) + )) + + ;; Fill in the current point as the anchor for all the symbols + ;; added above. + (let ((p c-syntactic-context) q) + (while (not (eq p syntax-last)) + (setq q (cdr (car p))) ; e.g. (nil 28) [from (arglist-cont-nonempty nil 28)] + (while q + (unless (car q) + (setcar q (point))) + (setq q (cdr q))) + (setq p (cdr p)))) + ))) + +(defun c-add-class-syntax (symbol + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state) + ;; The inclass and class-close syntactic symbols are added in + ;; several places and some work is needed to fix everything. + ;; Therefore it's collected here. + ;; + ;; This function might do hidden buffer changes. + (goto-char containing-decl-open) + (if (and (eq symbol 'inclass) (= (point) (c-point 'boi))) + (progn + (c-add-syntax symbol containing-decl-open) + containing-decl-open) + (goto-char containing-decl-start) + ;; Ought to use `c-add-stmt-syntax' instead of backing up to boi + ;; here, but we have to do like this for compatibility. + (back-to-indentation) + (c-add-syntax symbol (point)) + (if (and (c-keyword-member containing-decl-kwd + 'c-inexpr-class-kwds) + (/= containing-decl-start (c-point 'boi containing-decl-start))) + (c-add-syntax 'inexpr-class)) + (point))) + +(defun c-guess-continued-construct (indent-point + char-after-ip + beg-of-same-or-containing-stmt + containing-sexp + paren-state) + ;; This function contains the decision tree reached through both + ;; cases 18 and 10. It's a continued statement or top level + ;; construct of some kind. + ;; + ;; This function might do hidden buffer changes. + + (let (special-brace-list placeholder) + (goto-char indent-point) + (skip-chars-forward " \t") + + (cond + ;; (CASE A removed.) + ;; CASE B: open braces for class or brace-lists + ((setq special-brace-list + (or (and c-special-brace-lists + (c-looking-at-special-brace-list)) + (eq char-after-ip ?{))) + + (cond + ;; CASE B.1: class-open + ((save-excursion + (and (eq (char-after) ?{) + (c-looking-at-decl-block containing-sexp t) + (setq beg-of-same-or-containing-stmt (point)))) + (c-add-syntax 'class-open beg-of-same-or-containing-stmt)) + + ;; CASE B.2: brace-list-open + ((or (consp special-brace-list) + (save-excursion + (goto-char beg-of-same-or-containing-stmt) + (c-syntactic-re-search-forward "=\\([^=]\\|$\\)" + indent-point t t t))) + ;; The most semantically accurate symbol here is + ;; brace-list-open, but we normally report it simply as a + ;; statement-cont. The reason is that one normally adjusts + ;; brace-list-open for brace lists as top-level constructs, + ;; and brace lists inside statements is a completely different + ;; context. C.f. case 5A.3. + (c-beginning-of-statement-1 containing-sexp) + (c-add-stmt-syntax (if c-auto-newline-analysis + ;; Turn off the dwim above when we're + ;; analyzing the nature of the brace + ;; for the auto newline feature. + 'brace-list-open + 'statement-cont) + nil nil + containing-sexp paren-state)) + + ;; CASE B.3: The body of a function declared inside a normal + ;; block. Can occur e.g. in Pike and when using gcc + ;; extensions, but watch out for macros followed by blocks. + ;; C.f. cases E, 16F and 17G. + ((and (not (c-at-statement-start-p)) + (eq (c-beginning-of-statement-1 containing-sexp nil nil t) + 'same) + (save-excursion + (let ((c-recognize-typeless-decls nil)) + ;; Turn off recognition of constructs that lacks a + ;; type in this case, since that's more likely to be + ;; a macro followed by a block. + (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))) + (c-add-stmt-syntax 'defun-open nil t + containing-sexp paren-state)) + + ;; CASE B.4: Continued statement with block open. The most + ;; accurate analysis is perhaps `statement-cont' together with + ;; `block-open' but we play DWIM and use `substatement-open' + ;; instead. The rationaly is that this typically is a macro + ;; followed by a block which makes it very similar to a + ;; statement with a substatement block. + (t + (c-add-stmt-syntax 'substatement-open nil nil + containing-sexp paren-state)) + )) + + ;; CASE C: iostream insertion or extraction operator + ((and (looking-at "\\(<<\\|>>\\)\\([^=]\\|$\\)") + (save-excursion + (goto-char beg-of-same-or-containing-stmt) + ;; If there is no preceding streamop in the statement + ;; then indent this line as a normal statement-cont. + (when (c-syntactic-re-search-forward + "\\(<<\\|>>\\)\\([^=]\\|$\\)" indent-point 'move t t) + (c-add-syntax 'stream-op (c-point 'boi)) + t)))) + + ;; CASE E: In the "K&R region" of a function declared inside a + ;; normal block. C.f. case B.3. + ((and (save-excursion + ;; Check that the next token is a '{'. This works as + ;; long as no language that allows nested function + ;; definitions allows stuff like member init lists, K&R + ;; declarations or throws clauses there. + ;; + ;; Note that we do a forward search for something ahead + ;; of the indentation line here. That's not good since + ;; the user might not have typed it yet. Unfortunately + ;; it's exceedingly tricky to recognize a function + ;; prototype in a code block without resorting to this. + (c-forward-syntactic-ws) + (eq (char-after) ?{)) + (not (c-at-statement-start-p)) + (eq (c-beginning-of-statement-1 containing-sexp nil nil t) + 'same) + (save-excursion + (let ((c-recognize-typeless-decls nil)) + ;; Turn off recognition of constructs that lacks a + ;; type in this case, since that's more likely to be + ;; a macro followed by a block. + (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))) + (c-add-stmt-syntax 'func-decl-cont nil t + containing-sexp paren-state)) + + ;;CASE F: continued statement and the only preceding items are + ;;annotations. + ((and (c-major-mode-is 'java-mode) + (setq placeholder (point)) + (c-beginning-of-statement-1) + (progn + (while (and (c-forward-annotation) + (< (point) placeholder)) + (c-forward-syntactic-ws)) + t) + (prog1 + (>= (point) placeholder) + (goto-char placeholder))) + (c-beginning-of-statement-1 containing-sexp) + (c-add-syntax 'annotation-var-cont (point))) + + ;; CASE G: a template list continuation? + ;; Mostly a duplication of case 5D.3 to fix templates-19: + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (goto-char indent-point) + (c-with-syntax-table c++-template-syntax-table + (setq placeholder (c-up-list-backward))) + (and placeholder + (eq (char-after placeholder) ?<) + (/= (char-before placeholder) ?<) + (progn + (goto-char (1+ placeholder)) + (not (looking-at c-<-op-cont-regexp)))))) + (c-with-syntax-table c++-template-syntax-table + (goto-char placeholder) + (c-beginning-of-statement-1 containing-sexp t) + (if (save-excursion + (c-backward-syntactic-ws containing-sexp) + (eq (char-before) ?<)) + ;; In a nested template arglist. + (progn + (goto-char placeholder) + (c-syntactic-skip-backward "^,;" containing-sexp t) + (c-forward-syntactic-ws)) + (back-to-indentation))) + ;; FIXME: Should use c-add-stmt-syntax, but it's not yet + ;; template aware. + (c-add-syntax 'template-args-cont (point) placeholder)) + + ;; CASE D: continued statement. + (t + (c-beginning-of-statement-1 containing-sexp) + (c-add-stmt-syntax 'statement-cont nil nil + containing-sexp paren-state)) + ))) + +;; The next autoload was added by RMS on 2005/8/9 - don't know why (ACM, +;; 2005/11/29). +;;;###autoload +(defun c-guess-basic-syntax () + "Return the syntactic context of the current line." + (save-excursion + (beginning-of-line) + (c-save-buffer-state + ((indent-point (point)) + (case-fold-search nil) + ;; A whole ugly bunch of various temporary variables. Have + ;; to declare them here since it's not possible to declare + ;; a variable with only the scope of a cond test and the + ;; following result clauses, and most of this function is a + ;; single gigantic cond. :P + literal char-before-ip before-ws-ip char-after-ip macro-start + in-macro-expr c-syntactic-context placeholder c-in-literal-cache + step-type tmpsymbol keyword injava-inher special-brace-list tmp-pos + containing-< + ;; The following record some positions for the containing + ;; declaration block if we're directly within one: + ;; `containing-decl-open' is the position of the open + ;; brace. `containing-decl-start' is the start of the + ;; declaration. `containing-decl-kwd' is the keyword + ;; symbol of the keyword that tells what kind of block it + ;; is. + containing-decl-open + containing-decl-start + containing-decl-kwd + ;; The open paren of the closest surrounding sexp or nil if + ;; there is none. + containing-sexp + ;; The position after the closest preceding brace sexp + ;; (nested sexps are ignored), or the position after + ;; `containing-sexp' if there is none, or (point-min) if + ;; `containing-sexp' is nil. + lim + ;; The paren state outside `containing-sexp', or at + ;; `indent-point' if `containing-sexp' is nil. + (paren-state (c-parse-state)) + ;; There's always at most one syntactic element which got + ;; an anchor pos. It's stored in syntactic-relpos. + syntactic-relpos + (c-stmt-delim-chars c-stmt-delim-chars)) + + ;; Check if we're directly inside an enclosing declaration + ;; level block. + (when (and (setq containing-sexp + (c-most-enclosing-brace paren-state)) + (progn + (goto-char containing-sexp) + (eq (char-after) ?{)) + (setq placeholder + (c-looking-at-decl-block + (c-most-enclosing-brace paren-state + containing-sexp) + t))) + (setq containing-decl-open containing-sexp + containing-decl-start (point) + containing-sexp nil) + (goto-char placeholder) + (setq containing-decl-kwd (and (looking-at c-keywords-regexp) + (c-keyword-sym (match-string 1))))) + + ;; Init some position variables. + (if c-state-cache + (progn + (setq containing-sexp (car paren-state) + paren-state (cdr paren-state)) + (if (consp containing-sexp) + (progn + (setq lim (cdr containing-sexp)) + (if (cdr c-state-cache) + ;; Ignore balanced paren. The next entry + ;; can't be another one. + (setq containing-sexp (car (cdr c-state-cache)) + paren-state (cdr paren-state)) + ;; If there is no surrounding open paren then + ;; put the last balanced pair back on paren-state. + (setq paren-state (cons containing-sexp paren-state) + containing-sexp nil))) + (setq lim (1+ containing-sexp)))) + (setq lim (point-min))) + (when (c-beginning-of-macro) + (goto-char indent-point) + (let ((lim1 (c-determine-limit 2000))) + (setq lim (max lim lim1)))) + + ;; If we're in a parenthesis list then ',' delimits the + ;; "statements" rather than being an operator (with the + ;; exception of the "for" clause). This difference is + ;; typically only noticeable when statements are used in macro + ;; arglists. + (when (and containing-sexp + (eq (char-after containing-sexp) ?\()) + (setq c-stmt-delim-chars c-stmt-delim-chars-with-comma)) + ;; cache char before and after indent point, and move point to + ;; the most likely position to perform the majority of tests + (goto-char indent-point) + (c-backward-syntactic-ws lim) + (setq before-ws-ip (point) + char-before-ip (char-before)) + (goto-char indent-point) + (skip-chars-forward " \t") + (setq char-after-ip (char-after)) + + ;; are we in a literal? + (setq literal (c-in-literal lim)) + + ;; now figure out syntactic qualities of the current line + (cond + + ;; CASE 1: in a string. + ((eq literal 'string) + (c-add-syntax 'string (c-point 'bopl))) + + ;; CASE 2: in a C or C++ style comment. + ((and (memq literal '(c c++)) + ;; This is a kludge for XEmacs where we use + ;; `buffer-syntactic-context', which doesn't correctly + ;; recognize "\*/" to end a block comment. + ;; `parse-partial-sexp' which is used by + ;; `c-literal-limits' will however do that in most + ;; versions, which results in that we get nil from + ;; `c-literal-limits' even when `c-in-literal' claims + ;; we're inside a comment. + (setq placeholder (c-literal-limits lim))) + (c-add-syntax literal (car placeholder))) + + ;; CASE 3: in a cpp preprocessor macro continuation. + ((and (save-excursion + (when (c-beginning-of-macro) + (setq macro-start (point)))) + (/= macro-start (c-point 'boi)) + (progn + (setq tmpsymbol 'cpp-macro-cont) + (or (not c-syntactic-indentation-in-macros) + (save-excursion + (goto-char macro-start) + ;; If at the beginning of the body of a #define + ;; directive then analyze as cpp-define-intro + ;; only. Go on with the syntactic analysis + ;; otherwise. in-macro-expr is set if we're in a + ;; cpp expression, i.e. before the #define body + ;; or anywhere in a non-#define directive. + (if (c-forward-to-cpp-define-body) + (let ((indent-boi (c-point 'boi indent-point))) + (setq in-macro-expr (> (point) indent-boi) + tmpsymbol 'cpp-define-intro) + (= (point) indent-boi)) + (setq in-macro-expr t) + nil))))) + (c-add-syntax tmpsymbol macro-start) + (setq macro-start nil)) + + ;; CASE 11: an else clause? + ((looking-at "else\\>[^_]") + (c-beginning-of-statement-1 containing-sexp) + (c-add-stmt-syntax 'else-clause nil t + containing-sexp paren-state)) + + ;; CASE 12: while closure of a do/while construct? + ((and (looking-at "while\\>[^_]") + (save-excursion + (prog1 (eq (c-beginning-of-statement-1 containing-sexp) + 'beginning) + (setq placeholder (point))))) + (goto-char placeholder) + (c-add-stmt-syntax 'do-while-closure nil t + containing-sexp paren-state)) + + ;; CASE 13: A catch or finally clause? This case is simpler + ;; than if-else and do-while, because a block is required + ;; after every try, catch and finally. + ((save-excursion + (and (cond ((c-major-mode-is 'c++-mode) + (looking-at "catch\\>[^_]")) + ((c-major-mode-is 'java-mode) + (looking-at "\\(catch\\|finally\\)\\>[^_]"))) + (and (c-safe (c-backward-syntactic-ws) + (c-backward-sexp) + t) + (eq (char-after) ?{) + (c-safe (c-backward-syntactic-ws) + (c-backward-sexp) + t) + (if (eq (char-after) ?\() + (c-safe (c-backward-sexp) t) + t)) + (looking-at "\\(try\\|catch\\)\\>[^_]") + (setq placeholder (point)))) + (goto-char placeholder) + (c-add-stmt-syntax 'catch-clause nil t + containing-sexp paren-state)) + + ;; CASE 18: A substatement we can recognize by keyword. + ((save-excursion + (and c-opt-block-stmt-key + (not (eq char-before-ip ?\;)) + (not (c-at-vsemi-p before-ws-ip)) + (not (memq char-after-ip '(?\) ?\] ?,))) + (or (not (eq char-before-ip ?})) + (c-looking-at-inexpr-block-backward c-state-cache)) + (> (point) + (progn + ;; Ought to cache the result from the + ;; c-beginning-of-statement-1 calls here. + (setq placeholder (point)) + (while (eq (setq step-type + (c-beginning-of-statement-1 lim)) + 'label)) + (if (eq step-type 'previous) + (goto-char placeholder) + (setq placeholder (point)) + (if (and (eq step-type 'same) + (not (looking-at c-opt-block-stmt-key))) + ;; Step up to the containing statement if we + ;; stayed in the same one. + (let (step) + (while (eq + (setq step + (c-beginning-of-statement-1 lim)) + 'label)) + (if (eq step 'up) + (setq placeholder (point)) + ;; There was no containing statement afterall. + (goto-char placeholder))))) + placeholder)) + (if (looking-at c-block-stmt-2-key) + ;; Require a parenthesis after these keywords. + ;; Necessary to catch e.g. synchronized in Java, + ;; which can be used both as statement and + ;; modifier. + (and (zerop (c-forward-token-2 1 nil)) + (eq (char-after) ?\()) + (looking-at c-opt-block-stmt-key)))) + + (if (eq step-type 'up) + ;; CASE 18A: Simple substatement. + (progn + (goto-char placeholder) + (cond + ((eq char-after-ip ?{) + (c-add-stmt-syntax 'substatement-open nil nil + containing-sexp paren-state)) + ((save-excursion + (goto-char indent-point) + (back-to-indentation) + (c-forward-label)) + (c-add-stmt-syntax 'substatement-label nil nil + containing-sexp paren-state)) + (t + (c-add-stmt-syntax 'substatement nil nil + containing-sexp paren-state)))) + + ;; CASE 18B: Some other substatement. This is shared + ;; with case 10. + (c-guess-continued-construct indent-point + char-after-ip + placeholder + lim + paren-state))) + + ;; CASE 14: A case or default label + ((looking-at c-label-kwds-regexp) + (if containing-sexp + (progn + (goto-char containing-sexp) + (setq lim (c-most-enclosing-brace c-state-cache + containing-sexp)) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'case-label nil t lim paren-state)) + ;; Got a bogus label at the top level. In lack of better + ;; alternatives, anchor it on (point-min). + (c-add-syntax 'case-label (point-min)))) + + ;; CASE 15: any other label + ((save-excursion + (back-to-indentation) + (and (not (looking-at c-syntactic-ws-start)) + (c-forward-label))) + (cond (containing-decl-open + (setq placeholder (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state)) + ;; Append access-label with the same anchor point as + ;; inclass gets. + (c-append-syntax 'access-label placeholder)) + + (containing-sexp + (goto-char containing-sexp) + (setq lim (c-most-enclosing-brace c-state-cache + containing-sexp)) + (save-excursion + (setq tmpsymbol + (if (and (eq (c-beginning-of-statement-1 lim) 'up) + (looking-at "switch\\>[^_]")) + ;; If the surrounding statement is a switch then + ;; let's analyze all labels as switch labels, so + ;; that they get lined up consistently. + 'case-label + 'label))) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax tmpsymbol nil t lim paren-state)) + + (t + ;; A label on the top level. Treat it as a class + ;; context. (point-min) is the closest we get to the + ;; class open brace. + (c-add-syntax 'access-label (point-min))))) + + ;; CASE 4: In-expression statement. C.f. cases 7B, 16A and + ;; 17E. + ((setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + containing-sexp + ;; Have to turn on the heuristics after + ;; the point even though it doesn't work + ;; very well. C.f. test case class-16.pike. + t)) + (setq tmpsymbol (assq (car placeholder) + '((inexpr-class . class-open) + (inexpr-statement . block-open)))) + (if tmpsymbol + ;; It's a statement block or an anonymous class. + (setq tmpsymbol (cdr tmpsymbol)) + ;; It's a Pike lambda. Check whether we are between the + ;; lambda keyword and the argument list or at the defun + ;; opener. + (setq tmpsymbol (if (eq char-after-ip ?{) + 'inline-open + 'lambda-intro-cont))) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol nil t + (c-most-enclosing-brace c-state-cache (point)) + paren-state) + (unless (eq (point) (cdr placeholder)) + (c-add-syntax (car placeholder)))) + + ;; CASE 5: Line is inside a declaration level block or at top level. + ((or containing-decl-open (null containing-sexp)) + (cond + + ;; CASE 5A: we are looking at a defun, brace list, class, + ;; or inline-inclass method opening brace + ((setq special-brace-list + (or (and c-special-brace-lists + (c-looking-at-special-brace-list)) + (eq char-after-ip ?{))) + (cond + + ;; CASE 5A.1: Non-class declaration block open. + ((save-excursion + (let (tmp) + (and (eq char-after-ip ?{) + (setq tmp (c-looking-at-decl-block containing-sexp t)) + (progn + (setq placeholder (point)) + (goto-char tmp) + (looking-at c-symbol-key)) + (c-keyword-member + (c-keyword-sym (setq keyword (match-string 0))) + 'c-other-block-decl-kwds)))) + (goto-char placeholder) + (c-add-stmt-syntax + (if (string-equal keyword "extern") + ;; Special case for extern-lang-open. + 'extern-lang-open + (intern (concat keyword "-open"))) + nil t containing-sexp paren-state)) + + ;; CASE 5A.2: we are looking at a class opening brace + ((save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + (and (eq (char-after) ?{) + (c-looking-at-decl-block containing-sexp t) + (setq placeholder (point)))) + (c-add-syntax 'class-open placeholder)) + + ;; CASE 5A.3: brace list open + ((save-excursion + (c-beginning-of-decl-1 lim) + (while (looking-at c-specifier-key) + (goto-char (match-end 1)) + (c-forward-syntactic-ws indent-point)) + (setq placeholder (c-point 'boi)) + (or (consp special-brace-list) + (and (or (save-excursion + (goto-char indent-point) + (setq tmpsymbol nil) + (while (and (> (point) placeholder) + (zerop (c-backward-token-2 1 t)) + (/= (char-after) ?=)) + (and c-opt-inexpr-brace-list-key + (not tmpsymbol) + (looking-at c-opt-inexpr-brace-list-key) + (setq tmpsymbol 'topmost-intro-cont))) + (eq (char-after) ?=)) + (looking-at c-brace-list-key)) + (save-excursion + (while (and (< (point) indent-point) + (zerop (c-forward-token-2 1 t)) + (not (memq (char-after) '(?\; ?\())))) + (not (memq (char-after) '(?\; ?\())) + )))) + (if (and (not c-auto-newline-analysis) + (c-major-mode-is 'java-mode) + (eq tmpsymbol 'topmost-intro-cont)) + ;; We're in Java and have found that the open brace + ;; belongs to a "new Foo[]" initialization list, + ;; which means the brace list is part of an + ;; expression and not a top level definition. We + ;; therefore treat it as any topmost continuation + ;; even though the semantically correct symbol still + ;; is brace-list-open, on the same grounds as in + ;; case B.2. + (progn + (c-beginning-of-statement-1 lim) + (c-add-syntax 'topmost-intro-cont (c-point 'boi))) + (c-add-syntax 'brace-list-open placeholder))) + + ;; CASE 5A.4: inline defun open + ((and containing-decl-open + (not (c-keyword-member containing-decl-kwd + 'c-other-block-decl-kwds))) + (c-add-syntax 'inline-open) + (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state)) + + ;; CASE 5A.5: ordinary defun open + (t + (save-excursion + (c-beginning-of-decl-1 lim) + (while (looking-at c-specifier-key) + (goto-char (match-end 1)) + (c-forward-syntactic-ws indent-point)) + (c-add-syntax 'defun-open (c-point 'boi)) + ;; Bogus to use bol here, but it's the legacy. (Resolved, + ;; 2007-11-09) + )))) + + ;; CASE 5B: After a function header but before the body (or + ;; the ending semicolon if there's no body). + ((save-excursion + (when (setq placeholder (c-just-after-func-arglist-p + (max lim (c-determine-limit 500)))) + (setq tmp-pos (point)))) + (cond + + ;; CASE 5B.1: Member init list. + ((eq (char-after tmp-pos) ?:) + (if (or (>= tmp-pos indent-point) + (= (c-point 'bosws) (1+ tmp-pos))) + (progn + ;; There is no preceding member init clause. + ;; Indent relative to the beginning of indentation + ;; for the topmost-intro line that contains the + ;; prototype's open paren. + (goto-char placeholder) + (c-add-syntax 'member-init-intro (c-point 'boi))) + ;; Indent relative to the first member init clause. + (goto-char (1+ tmp-pos)) + (c-forward-syntactic-ws) + (c-add-syntax 'member-init-cont (point)))) + + ;; CASE 5B.2: K&R arg decl intro + ((and c-recognize-knr-p + (c-in-knr-argdecl lim)) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'knr-argdecl-intro (c-point 'boi)) + (if containing-decl-open + (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state))) + + ;; CASE 5B.4: Nether region after a C++ or Java func + ;; decl, which could include a `throws' declaration. + (t + (c-beginning-of-statement-1 lim) + (c-add-syntax 'func-decl-cont (c-point 'boi)) + ))) + + ;; CASE 5C: inheritance line. could be first inheritance + ;; line, or continuation of a multiple inheritance + ((or (and (c-major-mode-is 'c++-mode) + (progn + (when (eq char-after-ip ?,) + (skip-chars-forward " \t") + (forward-char)) + (looking-at c-opt-postfix-decl-spec-key))) + (and (or (eq char-before-ip ?:) + ;; watch out for scope operator + (save-excursion + (and (eq char-after-ip ?:) + (c-safe (forward-char 1) t) + (not (eq (char-after) ?:)) + ))) + (save-excursion + (c-backward-syntactic-ws lim) + (if (eq char-before-ip ?:) + (progn + (forward-char -1) + (c-backward-syntactic-ws lim))) + (back-to-indentation) + (looking-at c-class-key))) + ;; for Java + (and (c-major-mode-is 'java-mode) + (let ((fence (save-excursion + (c-beginning-of-statement-1 lim) + (point))) + cont done) + (save-excursion + (while (not done) + (cond ((looking-at c-opt-postfix-decl-spec-key) + (setq injava-inher (cons cont (point)) + done t)) + ((or (not (c-safe (c-forward-sexp -1) t)) + (<= (point) fence)) + (setq done t)) + ) + (setq cont t))) + injava-inher) + (not (c-crosses-statement-barrier-p (cdr injava-inher) + (point))) + )) + (cond + + ;; CASE 5C.1: non-hanging colon on an inher intro + ((eq char-after-ip ?:) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'inher-intro (c-point 'boi)) + ;; don't add inclass symbol since relative point already + ;; contains any class offset + ) + + ;; CASE 5C.2: hanging colon on an inher intro + ((eq char-before-ip ?:) + (c-beginning-of-statement-1 lim) + (c-add-syntax 'inher-intro (c-point 'boi)) + (if containing-decl-open + (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state))) + + ;; CASE 5C.3: in a Java implements/extends + (injava-inher + (let ((where (cdr injava-inher)) + (cont (car injava-inher))) + (goto-char where) + (cond ((looking-at "throws\\>[^_]") + (c-add-syntax 'func-decl-cont + (progn (c-beginning-of-statement-1 lim) + (c-point 'boi)))) + (cont (c-add-syntax 'inher-cont where)) + (t (c-add-syntax 'inher-intro + (progn (goto-char (cdr injava-inher)) + (c-beginning-of-statement-1 lim) + (point)))) + ))) + + ;; CASE 5C.4: a continued inheritance line + (t + (c-beginning-of-inheritance-list lim) + (c-add-syntax 'inher-cont (point)) + ;; don't add inclass symbol since relative point already + ;; contains any class offset + ))) + + ;; CASE 5D: this could be a top-level initialization, a + ;; member init list continuation, or a template argument + ;; list continuation. + ((save-excursion + ;; Note: We use the fact that lim is always after any + ;; preceding brace sexp. + (if c-recognize-<>-arglists + (while (and + (progn + (c-syntactic-skip-backward "^;,=<>" lim t) + (> (point) lim)) + (or + (when c-overloadable-operators-regexp + (when (setq placeholder (c-after-special-operator-id lim)) + (goto-char placeholder) + t)) + (cond + ((eq (char-before) ?>) + (or (c-backward-<>-arglist nil lim) + (backward-char)) + t) + ((eq (char-before) ?<) + (backward-char) + (if (save-excursion + (c-forward-<>-arglist nil)) + (progn (forward-char) + nil) + t)) + (t nil))))) + ;; NB: No c-after-special-operator-id stuff in this + ;; clause - we assume only C++ needs it. + (c-syntactic-skip-backward "^;,=" lim t)) + (memq (char-before) '(?, ?= ?<))) + (cond + + ;; CASE 5D.3: perhaps a template list continuation? + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (save-restriction + (c-with-syntax-table c++-template-syntax-table + (goto-char indent-point) + (setq placeholder (c-up-list-backward)) + (and placeholder + (eq (char-after placeholder) ?<)))))) + (c-with-syntax-table c++-template-syntax-table + (goto-char placeholder) + (c-beginning-of-statement-1 lim t) + (if (save-excursion + (c-backward-syntactic-ws lim) + (eq (char-before) ?<)) + ;; In a nested template arglist. + (progn + (goto-char placeholder) + (c-syntactic-skip-backward "^,;" lim t) + (c-forward-syntactic-ws)) + (back-to-indentation))) + ;; FIXME: Should use c-add-stmt-syntax, but it's not yet + ;; template aware. + (c-add-syntax 'template-args-cont (point) placeholder)) + + ;; CASE 5D.4: perhaps a multiple inheritance line? + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (c-beginning-of-statement-1 lim) + (setq placeholder (point)) + (if (looking-at "static\\>[^_]") + (c-forward-token-2 1 nil indent-point)) + (and (looking-at c-class-key) + (zerop (c-forward-token-2 2 nil indent-point)) + (if (eq (char-after) ?<) + (c-with-syntax-table c++-template-syntax-table + (zerop (c-forward-token-2 1 t indent-point))) + t) + (eq (char-after) ?:)))) + (goto-char placeholder) + (c-add-syntax 'inher-cont (c-point 'boi))) + + ;; CASE 5D.5: Continuation of the "expression part" of a + ;; top level construct. Or, perhaps, an unrecognised construct. + (t + (while (and (setq placeholder (point)) + (eq (car (c-beginning-of-decl-1 containing-sexp)) ; Can't use `lim' here. + 'same) + (save-excursion + (c-backward-syntactic-ws) + (eq (char-before) ?})) + (< (point) placeholder))) + (c-add-stmt-syntax + (cond + ((eq (point) placeholder) 'statement) ; unrecognised construct + ;; A preceding comma at the top level means that a + ;; new variable declaration starts here. Use + ;; topmost-intro-cont for it, for consistency with + ;; the first variable declaration. C.f. case 5N. + ((eq char-before-ip ?,) 'topmost-intro-cont) + (t 'statement-cont)) + nil nil containing-sexp paren-state)) + )) + + ;; CASE 5F: Close of a non-class declaration level block. + ((and (eq char-after-ip ?}) + (c-keyword-member containing-decl-kwd + 'c-other-block-decl-kwds)) + ;; This is inconsistent: Should use `containing-decl-open' + ;; here if it's at boi, like in case 5J. + (goto-char containing-decl-start) + (c-add-stmt-syntax + (if (string-equal (symbol-name containing-decl-kwd) "extern") + ;; Special case for compatibility with the + ;; extern-lang syntactic symbols. + 'extern-lang-close + (intern (concat (symbol-name containing-decl-kwd) + "-close"))) + nil t + (c-most-enclosing-brace paren-state (point)) + paren-state)) + + ;; CASE 5G: we are looking at the brace which closes the + ;; enclosing nested class decl + ((and containing-sexp + (eq char-after-ip ?}) + (eq containing-decl-open containing-sexp)) + (c-add-class-syntax 'class-close + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state)) + + ;; CASE 5H: we could be looking at subsequent knr-argdecls + ((and c-recognize-knr-p + (not containing-sexp) ; can't be knr inside braces. + (not (eq char-before-ip ?})) + (save-excursion + (setq placeholder (cdr (c-beginning-of-decl-1 lim))) + (and placeholder + ;; Do an extra check to avoid tripping up on + ;; statements that occur in invalid contexts + ;; (e.g. in macro bodies where we don't really + ;; know the context of what we're looking at). + (not (and c-opt-block-stmt-key + (looking-at c-opt-block-stmt-key))))) + (< placeholder indent-point)) + (goto-char placeholder) + (c-add-syntax 'knr-argdecl (point))) + + ;; CASE 5I: ObjC method definition. + ((and c-opt-method-key + (looking-at c-opt-method-key)) + (c-beginning-of-statement-1 nil t) + (if (= (point) indent-point) + ;; Handle the case when it's the first (non-comment) + ;; thing in the buffer. Can't look for a 'same return + ;; value from cbos1 since ObjC directives currently + ;; aren't recognized fully, so that we get 'same + ;; instead of 'previous if it moved over a preceding + ;; directive. + (goto-char (point-min))) + (c-add-syntax 'objc-method-intro (c-point 'boi))) + + ;; CASE 5P: AWK pattern or function or continuation + ;; thereof. + ((c-major-mode-is 'awk-mode) + (setq placeholder (point)) + (c-add-stmt-syntax + (if (and (eq (c-beginning-of-statement-1) 'same) + (/= (point) placeholder)) + 'topmost-intro-cont + 'topmost-intro) + nil nil + containing-sexp paren-state)) + + ;; CASE 5N: At a variable declaration that follows a class + ;; definition or some other block declaration that doesn't + ;; end at the closing '}'. C.f. case 5D.5. + ((progn + (c-backward-syntactic-ws lim) + (and (eq (char-before) ?}) + (save-excursion + (let ((start (point))) + (if (and c-state-cache + (consp (car c-state-cache)) + (eq (cdar c-state-cache) (point))) + ;; Speed up the backward search a bit. + (goto-char (caar c-state-cache))) + (c-beginning-of-decl-1 containing-sexp) ; Can't use `lim' here. + (setq placeholder (point)) + (if (= start (point)) + ;; The '}' is unbalanced. + nil + (c-end-of-decl-1) + (>= (point) indent-point)))))) + (goto-char placeholder) + (c-add-stmt-syntax 'topmost-intro-cont nil nil + containing-sexp paren-state)) + + ;; NOTE: The point is at the end of the previous token here. + + ;; CASE 5J: we are at the topmost level, make + ;; sure we skip back past any access specifiers + ((and + ;; A macro continuation line is never at top level. + (not (and macro-start + (> indent-point macro-start))) + (save-excursion + (setq placeholder (point)) + (or (memq char-before-ip '(?\; ?{ ?} nil)) + (c-at-vsemi-p before-ws-ip) + (when (and (eq char-before-ip ?:) + (eq (c-beginning-of-statement-1 lim) + 'label)) + (c-backward-syntactic-ws lim) + (setq placeholder (point))) + (and (c-major-mode-is 'objc-mode) + (catch 'not-in-directive + (c-beginning-of-statement-1 lim) + (setq placeholder (point)) + (while (and (c-forward-objc-directive) + (< (point) indent-point)) + (c-forward-syntactic-ws) + (if (>= (point) indent-point) + (throw 'not-in-directive t)) + (setq placeholder (point))) + nil))))) + ;; For historic reasons we anchor at bol of the last + ;; line of the previous declaration. That's clearly + ;; highly bogus and useless, and it makes our lives hard + ;; to remain compatible. :P + (goto-char placeholder) + (c-add-syntax 'topmost-intro (c-point 'bol)) + (if containing-decl-open + (if (c-keyword-member containing-decl-kwd + 'c-other-block-decl-kwds) + (progn + (goto-char (c-brace-anchor-point containing-decl-open)) + (c-add-stmt-syntax + (if (string-equal (symbol-name containing-decl-kwd) + "extern") + ;; Special case for compatibility with the + ;; extern-lang syntactic symbols. + 'inextern-lang + (intern (concat "in" + (symbol-name containing-decl-kwd)))) + nil t + (c-most-enclosing-brace paren-state (point)) + paren-state)) + (c-add-class-syntax 'inclass + containing-decl-open + containing-decl-start + containing-decl-kwd + paren-state))) + (when (and c-syntactic-indentation-in-macros + macro-start + (/= macro-start (c-point 'boi indent-point))) + (c-add-syntax 'cpp-define-intro) + (setq macro-start nil))) + + ;; CASE 5K: we are at an ObjC method definition + ;; continuation line. + ((and c-opt-method-key + (save-excursion + (c-beginning-of-statement-1 lim) + (beginning-of-line) + (when (looking-at c-opt-method-key) + (setq placeholder (point))))) + (c-add-syntax 'objc-method-args-cont placeholder)) + + ;; CASE 5L: we are at the first argument of a template + ;; arglist that begins on the previous line. + ((and c-recognize-<>-arglists + (eq (char-before) ?<) + (not (and c-overloadable-operators-regexp + (c-after-special-operator-id lim)))) + (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (c-add-syntax 'template-args-cont (c-point 'boi))) + + ;; CASE 5Q: we are at a statement within a macro. + (macro-start + (c-beginning-of-statement-1 containing-sexp) + (c-add-stmt-syntax 'statement nil t containing-sexp paren-state)) + + ;;CASE 5N: We are at a tompmost continuation line and the only + ;;preceding items are annotations. + ((and (c-major-mode-is 'java-mode) + (setq placeholder (point)) + (c-beginning-of-statement-1) + (progn + (while (and (c-forward-annotation)) + (c-forward-syntactic-ws)) + t) + (prog1 + (>= (point) placeholder) + (goto-char placeholder))) + (c-add-syntax 'annotation-top-cont (c-point 'boi))) + + ;; CASE 5M: we are at a topmost continuation line + (t + (c-beginning-of-statement-1 (c-safe-position (point) paren-state)) + (when (c-major-mode-is 'objc-mode) + (setq placeholder (point)) + (while (and (c-forward-objc-directive) + (< (point) indent-point)) + (c-forward-syntactic-ws) + (setq placeholder (point))) + (goto-char placeholder)) + (c-add-syntax 'topmost-intro-cont (c-point 'boi))) + )) + + ;; (CASE 6 has been removed.) + + ;; CASE 7: line is an expression, not a statement. Most + ;; likely we are either in a function prototype or a function + ;; call argument list + ((not (or (and c-special-brace-lists + (save-excursion + (goto-char containing-sexp) + (c-looking-at-special-brace-list))) + (eq (char-after containing-sexp) ?{))) + (cond + + ;; CASE 7A: we are looking at the arglist closing paren. + ;; C.f. case 7F. + ((memq char-after-ip '(?\) ?\])) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (if (and (c-safe (backward-up-list 1) t) + (>= (point) placeholder)) + (progn + (forward-char) + (skip-chars-forward " \t")) + (goto-char placeholder)) + (c-add-stmt-syntax 'arglist-close (list containing-sexp) t + (c-most-enclosing-brace paren-state (point)) + paren-state)) + + ;; CASE 7B: Looking at the opening brace of an + ;; in-expression block or brace list. C.f. cases 4, 16A + ;; and 17E. + ((and (eq char-after-ip ?{) + (progn + (setq placeholder (c-inside-bracelist-p (point) + paren-state)) + (if placeholder + (setq tmpsymbol '(brace-list-open . inexpr-class)) + (setq tmpsymbol '(block-open . inexpr-statement) + placeholder + (cdr-safe (c-looking-at-inexpr-block + (c-safe-position containing-sexp + paren-state) + containing-sexp))) + ;; placeholder is nil if it's a block directly in + ;; a function arglist. That makes us skip out of + ;; this case. + ))) + (goto-char placeholder) + (back-to-indentation) + (c-add-stmt-syntax (car tmpsymbol) nil t + (c-most-enclosing-brace paren-state (point)) + paren-state) + (if (/= (point) placeholder) + (c-add-syntax (cdr tmpsymbol)))) + + ;; CASE 7C: we are looking at the first argument in an empty + ;; argument list. Use arglist-close if we're actually + ;; looking at a close paren or bracket. + ((memq char-before-ip '(?\( ?\[)) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (if (and (c-safe (backward-up-list 1) t) + (>= (point) placeholder)) + (progn + (forward-char) + (skip-chars-forward " \t")) + (goto-char placeholder)) + (c-add-stmt-syntax 'arglist-intro (list containing-sexp) t + (c-most-enclosing-brace paren-state (point)) + paren-state)) + + ;; CASE 7D: we are inside a conditional test clause. treat + ;; these things as statements + ((progn + (goto-char containing-sexp) + (and (c-safe (c-forward-sexp -1) t) + (looking-at "\\[^_]"))) + (goto-char (1+ containing-sexp)) + (c-forward-syntactic-ws indent-point) + (if (eq char-before-ip ?\;) + (c-add-syntax 'statement (point)) + (c-add-syntax 'statement-cont (point)) + )) + + ;; CASE 7E: maybe a continued ObjC method call. This is the + ;; case when we are inside a [] bracketed exp, and what + ;; precede the opening bracket is not an identifier. + ((and c-opt-method-key + (eq (char-after containing-sexp) ?\[) + (progn + (goto-char (1- containing-sexp)) + (c-backward-syntactic-ws (c-point 'bod)) + (if (not (looking-at c-symbol-key)) + (c-add-syntax 'objc-method-call-cont containing-sexp)) + ))) + + ;; CASE 7F: we are looking at an arglist continuation line, + ;; but the preceding argument is on the same line as the + ;; opening paren. This case includes multi-line + ;; mathematical paren groupings, but we could be on a + ;; for-list continuation line. C.f. case 7A. + ((progn + (goto-char (1+ containing-sexp)) + (< (save-excursion + (c-forward-syntactic-ws) + (point)) + (c-point 'bonl))) + (goto-char containing-sexp) + (setq placeholder (c-point 'boi)) + (if (and (c-safe (backward-up-list 1) t) + (>= (point) placeholder)) + (progn + (forward-char) + (skip-chars-forward " \t")) + (goto-char placeholder)) + (c-add-stmt-syntax 'arglist-cont-nonempty (list containing-sexp) t + (c-most-enclosing-brace c-state-cache (point)) + paren-state)) + + ;; CASE 7G: we are looking at just a normal arglist + ;; continuation line + (t (c-forward-syntactic-ws indent-point) + (c-add-syntax 'arglist-cont (c-point 'boi))) + )) + + ;; CASE 8: func-local multi-inheritance line + ((and (c-major-mode-is 'c++-mode) + (save-excursion + (goto-char indent-point) + (skip-chars-forward " \t") + (looking-at c-opt-postfix-decl-spec-key))) + (goto-char indent-point) + (skip-chars-forward " \t") + (cond + + ;; CASE 8A: non-hanging colon on an inher intro + ((eq char-after-ip ?:) + (c-backward-syntactic-ws lim) + (c-add-syntax 'inher-intro (c-point 'boi))) + + ;; CASE 8B: hanging colon on an inher intro + ((eq char-before-ip ?:) + (c-add-syntax 'inher-intro (c-point 'boi))) + + ;; CASE 8C: a continued inheritance line + (t + (c-beginning-of-inheritance-list lim) + (c-add-syntax 'inher-cont (point)) + ))) + + ;; CASE 9: we are inside a brace-list + ((and (not (c-major-mode-is 'awk-mode)) ; Maybe this isn't needed (ACM, 2002/3/29) + (setq special-brace-list + (or (and c-special-brace-lists ;;;; ALWAYS NIL FOR AWK!! + (save-excursion + (goto-char containing-sexp) + (c-looking-at-special-brace-list))) + (c-inside-bracelist-p containing-sexp paren-state)))) + (cond + + ;; CASE 9A: In the middle of a special brace list opener. + ((and (consp special-brace-list) + (save-excursion + (goto-char containing-sexp) + (eq (char-after) ?\()) + (eq char-after-ip (car (cdr special-brace-list)))) + (goto-char (car (car special-brace-list))) + (skip-chars-backward " \t") + (if (and (bolp) + (assoc 'statement-cont + (setq placeholder (c-guess-basic-syntax)))) + (setq c-syntactic-context placeholder) + (c-beginning-of-statement-1 + (c-safe-position (1- containing-sexp) paren-state)) + (c-forward-token-2 0) + (while (looking-at c-specifier-key) + (goto-char (match-end 1)) + (c-forward-syntactic-ws)) + (c-add-syntax 'brace-list-open (c-point 'boi)))) + + ;; CASE 9B: brace-list-close brace + ((if (consp special-brace-list) + ;; Check special brace list closer. + (progn + (goto-char (car (car special-brace-list))) + (save-excursion + (goto-char indent-point) + (back-to-indentation) + (or + ;; We were between the special close char and the `)'. + (and (eq (char-after) ?\)) + (eq (1+ (point)) (cdr (car special-brace-list)))) + ;; We were before the special close char. + (and (eq (char-after) (cdr (cdr special-brace-list))) + (zerop (c-forward-token-2)) + (eq (1+ (point)) (cdr (car special-brace-list))))))) + ;; Normal brace list check. + (and (eq char-after-ip ?}) + (c-safe (goto-char (c-up-list-backward (point))) t) + (= (point) containing-sexp))) + (if (eq (point) (c-point 'boi)) + (c-add-syntax 'brace-list-close (point)) + (setq lim (c-most-enclosing-brace c-state-cache (point))) + (c-beginning-of-statement-1 lim) + (c-add-stmt-syntax 'brace-list-close nil t lim paren-state))) + + (t + ;; Prepare for the rest of the cases below by going to the + ;; token following the opening brace + (if (consp special-brace-list) + (progn + (goto-char (car (car special-brace-list))) + (c-forward-token-2 1 nil indent-point)) + (goto-char containing-sexp)) + (forward-char) + (let ((start (point))) + (c-forward-syntactic-ws indent-point) + (goto-char (max start (c-point 'bol)))) + (c-skip-ws-forward indent-point) + (cond + + ;; CASE 9C: we're looking at the first line in a brace-list + ((= (point) indent-point) + (if (consp special-brace-list) + (goto-char (car (car special-brace-list))) + (goto-char containing-sexp)) + (if (eq (point) (c-point 'boi)) + (c-add-syntax 'brace-list-intro (point)) + (setq lim (c-most-enclosing-brace c-state-cache (point))) + (c-beginning-of-statement-1 lim) + (c-add-stmt-syntax 'brace-list-intro nil t lim paren-state))) + + ;; CASE 9D: this is just a later brace-list-entry or + ;; brace-entry-open + (t (if (or (eq char-after-ip ?{) + (and c-special-brace-lists + (save-excursion + (goto-char indent-point) + (c-forward-syntactic-ws (c-point 'eol)) + (c-looking-at-special-brace-list (point))))) + (c-add-syntax 'brace-entry-open (point)) + (c-add-syntax 'brace-list-entry (point)) + )) + )))) + + ;; CASE 10: A continued statement or top level construct. + ((and (not (memq char-before-ip '(?\; ?:))) + (not (c-at-vsemi-p before-ws-ip)) + (or (not (eq char-before-ip ?})) + (c-looking-at-inexpr-block-backward c-state-cache)) + (> (point) + (save-excursion + (c-beginning-of-statement-1 containing-sexp) + (setq placeholder (point)))) + (/= placeholder containing-sexp)) + ;; This is shared with case 18. + (c-guess-continued-construct indent-point + char-after-ip + placeholder + containing-sexp + paren-state)) + + ;; CASE 16: block close brace, possibly closing the defun or + ;; the class + ((eq char-after-ip ?}) + ;; From here on we have the next containing sexp in lim. + (setq lim (c-most-enclosing-brace paren-state)) + (goto-char containing-sexp) + (cond + + ;; CASE 16E: Closing a statement block? This catches + ;; cases where it's preceded by a statement keyword, + ;; which works even when used in an "invalid" context, + ;; e.g. a macro argument. + ((c-after-conditional) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'block-close nil t lim paren-state)) + + ;; CASE 16A: closing a lambda defun or an in-expression + ;; block? C.f. cases 4, 7B and 17E. + ((setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + nil)) + (setq tmpsymbol (if (eq (car placeholder) 'inlambda) + 'inline-close + 'block-close)) + (goto-char containing-sexp) + (back-to-indentation) + (if (= containing-sexp (point)) + (c-add-syntax tmpsymbol (point)) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol nil t + (c-most-enclosing-brace paren-state (point)) + paren-state) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder))))) + + ;; CASE 16B: does this close an inline or a function in + ;; a non-class declaration level block? + ((save-excursion + (and lim + (progn + (goto-char lim) + (c-looking-at-decl-block + (c-most-enclosing-brace paren-state lim) + nil)) + (setq placeholder (point)))) + (c-backward-to-decl-anchor lim) + (back-to-indentation) + (if (save-excursion + (goto-char placeholder) + (looking-at c-other-decl-block-key)) + (c-add-syntax 'defun-close (point)) + (c-add-syntax 'inline-close (point)))) + + ;; CASE 16F: Can be a defun-close of a function declared + ;; in a statement block, e.g. in Pike or when using gcc + ;; extensions, but watch out for macros followed by + ;; blocks. Let it through to be handled below. + ;; C.f. cases B.3 and 17G. + ((save-excursion + (and (not (c-at-statement-start-p)) + (eq (c-beginning-of-statement-1 lim nil nil t) 'same) + (setq placeholder (point)) + (let ((c-recognize-typeless-decls nil)) + ;; Turn off recognition of constructs that + ;; lacks a type in this case, since that's more + ;; likely to be a macro followed by a block. + (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))) + (back-to-indentation) + (if (/= (point) containing-sexp) + (goto-char placeholder)) + (c-add-stmt-syntax 'defun-close nil t lim paren-state)) + + ;; CASE 16C: If there is an enclosing brace then this is + ;; a block close since defun closes inside declaration + ;; level blocks have been handled above. + (lim + ;; If the block is preceded by a case/switch label on + ;; the same line, we anchor at the first preceding label + ;; at boi. The default handling in c-add-stmt-syntax + ;; really fixes it better, but we do like this to keep + ;; the indentation compatible with version 5.28 and + ;; earlier. C.f. case 17H. + (while (and (/= (setq placeholder (point)) (c-point 'boi)) + (eq (c-beginning-of-statement-1 lim) 'label))) + (goto-char placeholder) + (if (looking-at c-label-kwds-regexp) + (c-add-syntax 'block-close (point)) + (goto-char containing-sexp) + ;; c-backward-to-block-anchor not necessary here; those + ;; situations are handled in case 16E above. + (c-add-stmt-syntax 'block-close nil t lim paren-state))) + + ;; CASE 16D: Only top level defun close left. + (t + (goto-char containing-sexp) + (c-backward-to-decl-anchor lim) + (c-add-stmt-syntax 'defun-close nil nil + (c-most-enclosing-brace paren-state) + paren-state)) + )) + + ;; CASE 19: line is an expression, not a statement, and is directly + ;; contained by a template delimiter. Most likely, we are in a + ;; template arglist within a statement. This case is based on CASE + ;; 7. At some point in the future, we may wish to create more + ;; syntactic symbols such as `template-intro', + ;; `template-cont-nonempty', etc., and distinguish between them as we + ;; do for `arglist-intro' etc. (2009-12-07). + ((and c-recognize-<>-arglists + (setq containing-< (c-up-list-backward indent-point containing-sexp)) + (eq (char-after containing-<) ?\<)) + (setq placeholder (c-point 'boi containing-<)) + (goto-char containing-sexp) ; Most nested Lbrace/Lparen (but not + ; '<') before indent-point. + (if (>= (point) placeholder) + (progn + (forward-char) + (skip-chars-forward " \t")) + (goto-char placeholder)) + (c-add-stmt-syntax 'template-args-cont (list containing-<) t + (c-most-enclosing-brace c-state-cache (point)) + paren-state)) + + ;; CASE 17: Statement or defun catchall. + (t + (goto-char indent-point) + ;; Back up statements until we find one that starts at boi. + (while (let* ((prev-point (point)) + (last-step-type (c-beginning-of-statement-1 + containing-sexp))) + (if (= (point) prev-point) + (progn + (setq step-type (or step-type last-step-type)) + nil) + (setq step-type last-step-type) + (/= (point) (c-point 'boi))))) + (cond + + ;; CASE 17B: continued statement + ((and (eq step-type 'same) + (/= (point) indent-point)) + (c-add-stmt-syntax 'statement-cont nil nil + containing-sexp paren-state)) + + ;; CASE 17A: After a case/default label? + ((progn + (while (and (eq step-type 'label) + (not (looking-at c-label-kwds-regexp))) + (setq step-type + (c-beginning-of-statement-1 containing-sexp))) + (eq step-type 'label)) + (c-add-stmt-syntax (if (eq char-after-ip ?{) + 'statement-case-open + 'statement-case-intro) + nil t containing-sexp paren-state)) + + ;; CASE 17D: any old statement + ((progn + (while (eq step-type 'label) + (setq step-type + (c-beginning-of-statement-1 containing-sexp))) + (eq step-type 'previous)) + (c-add-stmt-syntax 'statement nil t + containing-sexp paren-state) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + + ;; CASE 17I: Inside a substatement block. + ((progn + ;; The following tests are all based on containing-sexp. + (goto-char containing-sexp) + ;; From here on we have the next containing sexp in lim. + (setq lim (c-most-enclosing-brace paren-state containing-sexp)) + (c-after-conditional)) + (c-backward-to-block-anchor lim) + (c-add-stmt-syntax 'statement-block-intro nil t + lim paren-state) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + + ;; CASE 17E: first statement in an in-expression block. + ;; C.f. cases 4, 7B and 16A. + ((setq placeholder (c-looking-at-inexpr-block + (c-safe-position containing-sexp paren-state) + nil)) + (setq tmpsymbol (if (eq (car placeholder) 'inlambda) + 'defun-block-intro + 'statement-block-intro)) + (back-to-indentation) + (if (= containing-sexp (point)) + (c-add-syntax tmpsymbol (point)) + (goto-char (cdr placeholder)) + (back-to-indentation) + (c-add-stmt-syntax tmpsymbol nil t + (c-most-enclosing-brace c-state-cache (point)) + paren-state) + (if (/= (point) (cdr placeholder)) + (c-add-syntax (car placeholder)))) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + + ;; CASE 17F: first statement in an inline, or first + ;; statement in a top-level defun. we can tell this is it + ;; if there are no enclosing braces that haven't been + ;; narrowed out by a class (i.e. don't use bod here). + ((save-excursion + (or (not (setq placeholder (c-most-enclosing-brace + paren-state))) + (and (progn + (goto-char placeholder) + (eq (char-after) ?{)) + (c-looking-at-decl-block (c-most-enclosing-brace + paren-state (point)) + nil)))) + (c-backward-to-decl-anchor lim) + (back-to-indentation) + (c-add-syntax 'defun-block-intro (point))) + + ;; CASE 17G: First statement in a function declared inside + ;; a normal block. This can occur in Pike and with + ;; e.g. the gcc extensions, but watch out for macros + ;; followed by blocks. C.f. cases B.3 and 16F. + ((save-excursion + (and (not (c-at-statement-start-p)) + (eq (c-beginning-of-statement-1 lim nil nil t) 'same) + (setq placeholder (point)) + (let ((c-recognize-typeless-decls nil)) + ;; Turn off recognition of constructs that lacks + ;; a type in this case, since that's more likely + ;; to be a macro followed by a block. + (c-forward-decl-or-cast-1 (c-point 'bosws) nil nil)))) + (back-to-indentation) + (if (/= (point) containing-sexp) + (goto-char placeholder)) + (c-add-stmt-syntax 'defun-block-intro nil t + lim paren-state)) + + ;; CASE 17H: First statement in a block. + (t + ;; If the block is preceded by a case/switch label on the + ;; same line, we anchor at the first preceding label at + ;; boi. The default handling in c-add-stmt-syntax is + ;; really fixes it better, but we do like this to keep the + ;; indentation compatible with version 5.28 and earlier. + ;; C.f. case 16C. + (while (and (/= (setq placeholder (point)) (c-point 'boi)) + (eq (c-beginning-of-statement-1 lim) 'label))) + (goto-char placeholder) + (if (looking-at c-label-kwds-regexp) + (c-add-syntax 'statement-block-intro (point)) + (goto-char containing-sexp) + ;; c-backward-to-block-anchor not necessary here; those + ;; situations are handled in case 17I above. + (c-add-stmt-syntax 'statement-block-intro nil t + lim paren-state)) + (if (eq char-after-ip ?{) + (c-add-syntax 'block-open))) + )) + ) + + ;; now we need to look at any modifiers + (goto-char indent-point) + (skip-chars-forward " \t") + + ;; are we looking at a comment only line? + (when (and (looking-at c-comment-start-regexp) + (/= (c-forward-token-2 0 nil (c-point 'eol)) 0)) + (c-append-syntax 'comment-intro)) + + ;; we might want to give additional offset to friends (in C++). + (when (and c-opt-friend-key + (looking-at c-opt-friend-key)) + (c-append-syntax 'friend)) + + ;; Set syntactic-relpos. + (let ((p c-syntactic-context)) + (while (and p + (if (integerp (c-langelem-pos (car p))) + (progn + (setq syntactic-relpos (c-langelem-pos (car p))) + nil) + t)) + (setq p (cdr p)))) + + ;; Start of or a continuation of a preprocessor directive? + (if (and macro-start + (eq macro-start (c-point 'boi)) + (not (and (c-major-mode-is 'pike-mode) + (eq (char-after (1+ macro-start)) ?\")))) + (c-append-syntax 'cpp-macro) + (when (and c-syntactic-indentation-in-macros macro-start) + (if in-macro-expr + (when (or + (< syntactic-relpos macro-start) + (not (or + (assq 'arglist-intro c-syntactic-context) + (assq 'arglist-cont c-syntactic-context) + (assq 'arglist-cont-nonempty c-syntactic-context) + (assq 'arglist-close c-syntactic-context)))) + ;; If inside a cpp expression, i.e. anywhere in a + ;; cpp directive except a #define body, we only let + ;; through the syntactic analysis that is internal + ;; in the expression. That means the arglist + ;; elements, if they are anchored inside the cpp + ;; expression. + (setq c-syntactic-context nil) + (c-add-syntax 'cpp-macro-cont macro-start)) + (when (and (eq macro-start syntactic-relpos) + (not (assq 'cpp-define-intro c-syntactic-context)) + (save-excursion + (goto-char macro-start) + (or (not (c-forward-to-cpp-define-body)) + (<= (point) (c-point 'boi indent-point))))) + ;; Inside a #define body and the syntactic analysis is + ;; anchored on the start of the #define. In this case + ;; we add cpp-define-intro to get the extra + ;; indentation of the #define body. + (c-add-syntax 'cpp-define-intro))))) + + ;; return the syntax + c-syntactic-context))) + + +;; Indentation calculation. + +(defun c-evaluate-offset (offset langelem symbol) + ;; offset can be a number, a function, a variable, a list, or one of + ;; the symbols + or - + ;; + ;; This function might do hidden buffer changes. + (let ((res + (cond + ((numberp offset) offset) + ((vectorp offset) offset) + ((null offset) nil) + + ((eq offset '+) c-basic-offset) + ((eq offset '-) (- c-basic-offset)) + ((eq offset '++) (* 2 c-basic-offset)) + ((eq offset '--) (* 2 (- c-basic-offset))) + ((eq offset '*) (/ c-basic-offset 2)) + ((eq offset '/) (/ (- c-basic-offset) 2)) + + ((functionp offset) + (c-evaluate-offset + (funcall offset + (cons (c-langelem-sym langelem) + (c-langelem-pos langelem))) + langelem symbol)) + + ((listp offset) + (cond + ((eq (car offset) 'quote) + (c-benign-error "The offset %S for %s was mistakenly quoted" + offset symbol) + nil) + + ((memq (car offset) '(min max)) + (let (res val (method (car offset))) + (setq offset (cdr offset)) + (while offset + (setq val (c-evaluate-offset (car offset) langelem symbol)) + (cond + ((not val)) + ((not res) + (setq res val)) + ((integerp val) + (if (vectorp res) + (c-benign-error "\ +Error evaluating offset %S for %s: \ +Cannot combine absolute offset %S with relative %S in `%s' method" + (car offset) symbol res val method) + (setq res (funcall method res val)))) + (t + (if (integerp res) + (c-benign-error "\ +Error evaluating offset %S for %s: \ +Cannot combine relative offset %S with absolute %S in `%s' method" + (car offset) symbol res val method) + (setq res (vector (funcall method (aref res 0) + (aref val 0))))))) + (setq offset (cdr offset))) + res)) + + ((eq (car offset) 'add) + (let (res val) + (setq offset (cdr offset)) + (while offset + (setq val (c-evaluate-offset (car offset) langelem symbol)) + (cond + ((not val)) + ((not res) + (setq res val)) + ((integerp val) + (if (vectorp res) + (setq res (vector (+ (aref res 0) val))) + (setq res (+ res val)))) + (t + (if (vectorp res) + (c-benign-error "\ +Error evaluating offset %S for %s: \ +Cannot combine absolute offsets %S and %S in `add' method" + (car offset) symbol res val) + (setq res val)))) ; Override. + (setq offset (cdr offset))) + res)) + + (t + (let (res) + (when (eq (car offset) 'first) + (setq offset (cdr offset))) + (while (and (not res) offset) + (setq res (c-evaluate-offset (car offset) langelem symbol) + offset (cdr offset))) + res)))) + + ((and (symbolp offset) (boundp offset)) + (symbol-value offset)) + + (t + (c-benign-error "Unknown offset format %S for %s" offset symbol) + nil)))) + + (if (or (null res) (integerp res) + (and (vectorp res) (= (length res) 1) (integerp (aref res 0)))) + res + (c-benign-error "Error evaluating offset %S for %s: Got invalid value %S" + offset symbol res) + nil))) + +(defun c-calc-offset (langelem) + ;; Get offset from LANGELEM which is a list beginning with the + ;; syntactic symbol and followed by any analysis data it provides. + ;; That data may be zero or more elements, but if at least one is + ;; given then the first is the anchor position (or nil). The symbol + ;; is matched against `c-offsets-alist' and the offset calculated + ;; from that is returned. + ;; + ;; This function might do hidden buffer changes. + (let* ((symbol (c-langelem-sym langelem)) + (match (assq symbol c-offsets-alist)) + (offset (cdr-safe match))) + (if match + (setq offset (c-evaluate-offset offset langelem symbol)) + (if c-strict-syntax-p + (c-benign-error "No offset found for syntactic symbol %s" symbol)) + (setq offset 0)) + (if (vectorp offset) + offset + (or (and (numberp offset) offset) + (and (symbolp offset) (symbol-value offset)) + 0)) + )) + +(defun c-get-offset (langelem) + ;; This is a compatibility wrapper for `c-calc-offset' in case + ;; someone is calling it directly. It takes an old style syntactic + ;; element on the form (SYMBOL . ANCHOR-POS) and converts it to the + ;; new list form. + ;; + ;; This function might do hidden buffer changes. + (if (c-langelem-pos langelem) + (c-calc-offset (list (c-langelem-sym langelem) + (c-langelem-pos langelem))) + (c-calc-offset langelem))) + +(defun c-get-syntactic-indentation (langelems) + ;; Calculate the syntactic indentation from a syntactic description + ;; as returned by `c-guess-syntax'. + ;; + ;; Note that topmost-intro always has an anchor position at bol, for + ;; historical reasons. It's often used together with other symbols + ;; that has more sane positions. Since we always use the first + ;; found anchor position, we rely on that these other symbols always + ;; precede topmost-intro in the LANGELEMS list. + ;; + ;; This function might do hidden buffer changes. + (let ((indent 0) anchor) + + (while langelems + (let* ((c-syntactic-element (car langelems)) + (res (c-calc-offset c-syntactic-element))) + + (if (vectorp res) + ;; Got an absolute column that overrides any indentation + ;; we've collected so far, but not the relative + ;; indentation we might get for the nested structures + ;; further down the langelems list. + (setq indent (elt res 0) + anchor (point-min)) ; A position at column 0. + + ;; Got a relative change of the current calculated + ;; indentation. + (setq indent (+ indent res)) + + ;; Use the anchor position from the first syntactic + ;; element with one. + (unless anchor + (setq anchor (c-langelem-pos (car langelems))))) + + (setq langelems (cdr langelems)))) + + (if anchor + (+ indent (save-excursion + (goto-char anchor) + (current-column))) + indent))) + + +(cc-provide 'cc-engine) + +;;; arch-tag: 149add18-4673-4da5-ac47-6805e4eae089 +;;; cc-engine.el ends here + diff --git a/site-lisp/cc-mode/5.32.3/cc-fix.el b/site-lisp/cc-mode/5.32.3/cc-fix.el new file mode 100644 index 0000000..589a7d5 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-fix.el @@ -0,0 +1,155 @@ +;;; cc-fix.el --- compatibility library for old (X)Emacs versions + +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005, 2006, 2007, 2008, +;; 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2003- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1997-1999 Barry A. Warsaw +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 03-Jul-1997 (as cc-mode-19.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is not part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; This file is necessary in order to run CC Mode in older (X)Emacs +;; versions. It's not needed at all for the latest versions of Emacs +;; and XEmacs. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +;; Silence the compiler (in case this file is compiled by other +;; Emacsen even though it isn't used by them). +(cc-bytecomp-obsolete-fun byte-code-function-p) +(cc-bytecomp-defun regexp-opt-depth) + +(cc-external-require 'advice) + +;; Emacs 20.n doesn't have the macros push and pop. Here're the Emacs 21 +;; definitions. +(or (fboundp 'push) + (defmacro push (newelt listname) + "Add NEWELT to the list stored in the symbol LISTNAME. +This is equivalent to (setq LISTNAME (cons NEWELT LISTNAME)). +LISTNAME must be a symbol." + (list 'setq listname + (list 'cons newelt listname)))) + +(or (fboundp 'pop) + (defmacro pop (listname) + "Return the first element of LISTNAME's value, and remove it from the list. +LISTNAME must be a symbol whose value is a list. +If the value is nil, `pop' returns nil but does not actually +change the list." + (list 'prog1 (list 'car listname) + (list 'setq listname (list 'cdr listname))))) + + +(if (/= (regexp-opt-depth "\\(\\(\\)\\)") 2) + (progn + ;; Emacs 21.1 has a buggy regexp-opt-depth which prevents CC + ;; Mode building. Those in Emacs 21.[23] are not entirely + ;; accurate. The following definition comes from Emacs's + ;; regexp-opt.el CVS version 1.25 and is believed to be a + ;; rigorously correct implementation. + (defconst regexp-opt-not-groupie*-re + (let* ((harmless-ch "[^\\\\[]") + (esc-pair-not-lp "\\\\[^(]") + (class-harmless-ch "[^][]") + (class-lb-harmless "[^]:]") + (class-lb-colon-maybe-charclass ":\\([a-z]+:]\\)?") + (class-lb (concat "\\[\\(" class-lb-harmless + "\\|" class-lb-colon-maybe-charclass "\\)")) + (class + (concat "\\[^?]?" + "\\(" class-harmless-ch + "\\|" class-lb "\\)*" + "\\[?]")) ; special handling for bare [ at end of re + (shy-lp "\\\\(\\?:")) + (concat "\\(" harmless-ch "\\|" esc-pair-not-lp + "\\|" class "\\|" shy-lp "\\)*")) + "Matches any part of a regular expression EXCEPT for non-shy \"\\\\(\"s") + + (defun regexp-opt-depth (regexp) + "Return the depth of REGEXP. +This means the number of regexp grouping constructs (parenthesised expressions) +in REGEXP." + (save-match-data + ;; Hack to signal an error if REGEXP does not have balanced + ;; parentheses. + (string-match regexp "") + ;; Count the number of open parentheses in REGEXP. + (let ((count 0) start) + (while + (progn + (string-match regexp-opt-not-groupie*-re regexp start) + (setq start ( + (match-end 0) 2)) ; +2 for "\\(" after match-end. + (<= start (length regexp))) + (setq count (1+ count))) + count))) + )) + +;; Some XEmacs versions have a bug in which font-lock-compile-keywords +;; overwrites the variable font-lock-keywords with its result. This causes +;; havoc when what the function is compiling is font-lock-SYNTACTIC-keywords, +;; hence.... +(eval-after-load "font-lock" + '(when (and (featurep 'xemacs) ; There is now (2005/12) code in GNU Emacs CVS + ; to make the call to f-l-c-k throw an error. + (let (font-lock-keywords) + (font-lock-compile-keywords '("\\<\\>")) + font-lock-keywords)) ; did the previous call foul this up? + (defun font-lock-compile-keywords (keywords) + "Compile KEYWORDS (a list) and return the list of compiled keywords. +Each keyword has the form (MATCHER HIGHLIGHT ...). See `font-lock-keywords'." + (if (eq (car-safe keywords) t) + keywords + (cons t (mapcar 'font-lock-compile-keyword keywords)))) + (defadvice font-lock-fontify-keywords-region (before c-compile-font-lock-keywords + activate preactivate) + (unless (eq (car-safe font-lock-keywords) t) + (setq font-lock-keywords + (font-lock-compile-keywords font-lock-keywords)))) + )) + +;; XEmacs 21.4 doesn't have `delete-dups'. +(if (not (fboundp 'delete-dups)) + (defun delete-dups (list) + "Destructively remove `equal' duplicates from LIST. +Store the result in LIST and return it. LIST must be a proper list. +Of several `equal' occurrences of an element in LIST, the first +one is kept." + (let ((tail list)) + (while tail + (setcdr tail (delete (car tail) (cdr tail))) + (setq tail (cdr tail)))) + list)) + + +(cc-provide 'cc-fix) +;;; cc-fix.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-fonts.el b/site-lisp/cc-mode/5.32.3/cc-fonts.el new file mode 100644 index 0000000..8f3421c --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-fonts.el @@ -0,0 +1,2694 @@ +;;; cc-fonts.el --- font lock support for CC Mode + +;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2003- Alan Mackenzie +;; 2002- Martin Stjernholm +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 07-Jan-2002 +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; Some comments on the use of faces: +;; +;; o `c-label-face-name' is either `font-lock-constant-face' (in +;; Emacs), or `font-lock-reference-face'. +;; +;; o `c-constant-face-name', `c-reference-face-name' and +;; `c-doc-markup-face-name' are essentially set up like +;; `c-label-face-name'. +;; +;; o `c-preprocessor-face-name' is `font-lock-preprocessor-face' in +;; XEmacs and - in lack of a closer equivalent - +;; `font-lock-builtin-face' or `font-lock-reference-face' in Emacs. +;; +;; o `c-doc-face-name' is `font-lock-doc-string-face' in XEmacs, +;; `font-lock-doc-face' in Emacs 21 and later, or +;; `font-lock-comment-face' in older Emacs (that since source +;; documentation are actually comments in these languages, as opposed +;; to elisp). +;; +;; TBD: We should probably provide real faces for the above uses and +;; instead initialize them from the standard faces. + +;;; Code: + +;; The faces that already have been put onto the text is tested in +;; various places to direct further fontifications. For this to work, +;; the following assumptions regarding the faces must hold (apart from +;; the dependencies on the font locking order): +;; +;; o `font-lock-comment-face' and the face in `c-doc-face-name' is +;; not used in anything but comments. +;; o If any face (e.g. `c-doc-markup-face-name') but those above is +;; used in comments, it doesn't replace them. +;; o `font-lock-string-face' is not used in anything but string +;; literals (single or double quoted). +;; o `font-lock-keyword-face' and the face in `c-label-face-name' are +;; never overlaid with other faces. + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require-when-compile 'cc-langs) +(cc-require 'cc-vars) +(cc-require 'cc-engine) +(cc-require-when-compile 'cc-awk) ; Change from cc-require, 2003/6/18 to +;; prevent cc-awk being loaded when it's not needed. There is now a (require +;; 'cc-awk) in (defun awk-mode ..). + +;; Avoid repeated loading through the eval-after-load directive in +;; cc-mode.el. +(provide 'cc-fonts) + +(cc-external-require 'font-lock) + +(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs only. + +;; Need to declare these local symbols during compilation since +;; they're referenced from lambdas in `byte-compile' calls that are +;; executed at compile time. They don't need to have the proper +;; definitions, though, since the generated functions aren't called +;; during compilation. +(cc-bytecomp-defvar c-preprocessor-face-name) +(cc-bytecomp-defvar c-reference-face-name) +(cc-bytecomp-defun c-fontify-recorded-types-and-refs) +(cc-bytecomp-defun c-font-lock-declarators) +(cc-bytecomp-defun c-font-lock-objc-method) +(cc-bytecomp-defun c-font-lock-invalid-string) + + +;; Note that font-lock in XEmacs doesn't expand face names as +;; variables, so we have to use the (eval . FORM) in the font lock +;; matchers wherever we use these alias variables. + +(defconst c-preprocessor-face-name + (cond ((c-face-name-p 'font-lock-preprocessor-face) + ;; XEmacs has a font-lock-preprocessor-face. + 'font-lock-preprocessor-face) + ((c-face-name-p 'font-lock-builtin-face) + ;; In Emacs font-lock-builtin-face has traditionally been + ;; used for preprocessor directives. + 'font-lock-builtin-face) + (t + 'font-lock-reference-face))) + +(cc-bytecomp-defvar font-lock-constant-face) + +(defconst c-label-face-name + (cond ((c-face-name-p 'font-lock-label-face) + ;; If it happens to occur in the future. (Well, the more + ;; pragmatic reason is to get unique faces for the test + ;; suite.) + 'font-lock-label-face) + ((and (c-face-name-p 'font-lock-constant-face) + (eq font-lock-constant-face 'font-lock-constant-face)) + ;; Test both if font-lock-constant-face exists and that it's + ;; not an alias for something else. This is important since + ;; we compare already set faces in various places. + 'font-lock-constant-face) + (t + 'font-lock-reference-face))) + +(defconst c-constant-face-name + (if (and (c-face-name-p 'font-lock-constant-face) + (eq font-lock-constant-face 'font-lock-constant-face)) + ;; This doesn't exist in some earlier versions of XEmacs 21. + 'font-lock-constant-face + c-label-face-name)) + +(defconst c-reference-face-name + (if (and (c-face-name-p 'font-lock-reference-face) + (eq font-lock-reference-face 'font-lock-reference-face)) + ;; This is considered obsolete in Emacs, but it still maps well + ;; to this use. (Another reason to do this is to get unique + ;; faces for the test suite.) + 'font-lock-reference-face + c-label-face-name)) + +;; This should not mapped to a face that also is used to fontify things +;; that aren't comments or string literals. +(defconst c-doc-face-name + (cond ((c-face-name-p 'font-lock-doc-string-face) + ;; XEmacs. + 'font-lock-doc-string-face) + ((c-face-name-p 'font-lock-doc-face) + ;; Emacs 21 and later. + 'font-lock-doc-face) + (t + 'font-lock-comment-face))) + +(defconst c-doc-markup-face-name + (if (c-face-name-p 'font-lock-doc-markup-face) + ;; If it happens to occur in the future. (Well, the more + ;; pragmatic reason is to get unique faces for the test + ;; suite.) + 'font-lock-doc-markup-face + c-label-face-name)) + +(defconst c-negation-char-face-name + (if (c-face-name-p 'font-lock-negation-char-face) + ;; Emacs 22 has a special face for negation chars. + 'font-lock-negation-char-face)) + +(cc-bytecomp-defun face-inverse-video-p) ; Only in Emacs. +(cc-bytecomp-defun face-property-instance) ; Only in XEmacs. + +(defun c-make-inverse-face (oldface newface) + ;; Emacs and XEmacs have completely different face manipulation + ;; routines. :P + (copy-face oldface newface) + (cond ((fboundp 'face-inverse-video-p) + ;; Emacs. This only looks at the inverse flag in the current + ;; frame. Other display configurations might be different, + ;; but it can only show if the same Emacs has frames on + ;; e.g. a color and a monochrome display simultaneously. + (unless (face-inverse-video-p oldface) + (invert-face newface))) + ((fboundp 'face-property-instance) + ;; XEmacs. Same pitfall here. + (unless (face-property-instance oldface 'reverse) + (invert-face newface))))) + +(eval-and-compile + ;; We need the following definitions during compilation since they're + ;; used when the `c-lang-defconst' initializers are evaluated. Define + ;; them at runtime too for the sake of derived modes. + + ;; This indicates the "font locking context", and is set just before + ;; fontification is done. If non-nil, it says, e.g., point starts + ;; from within a #if preprocessor construct. + (defvar c-font-lock-context nil) + (make-variable-buffer-local 'c-font-lock-context) + + (defmacro c-put-font-lock-face (from to face) + ;; Put a face on a region (overriding any existing face) in the way + ;; font-lock would do it. In XEmacs that means putting an + ;; additional font-lock property, or else the font-lock package + ;; won't recognize it as fontified and might override it + ;; incorrectly. + ;; + ;; This function does a hidden buffer change. + (if (fboundp 'font-lock-set-face) + ;; Note: This function has no docstring in XEmacs so it might be + ;; considered internal. + `(font-lock-set-face ,from ,to ,face) + `(put-text-property ,from ,to 'face ,face))) + + (defmacro c-remove-font-lock-face (from to) + ;; This is the inverse of `c-put-font-lock-face'. + ;; + ;; This function does a hidden buffer change. + (if (fboundp 'font-lock-remove-face) + `(font-lock-remove-face ,from ,to) + `(remove-text-properties ,from ,to '(face nil)))) + + (defmacro c-put-font-lock-string-face (from to) + ;; Put `font-lock-string-face' on a string. The surrounding + ;; quotes are included in Emacs but not in XEmacs. The passed + ;; region should include them. + ;; + ;; This function does a hidden buffer change. + (if (featurep 'xemacs) + `(c-put-font-lock-face (1+ ,from) (1- ,to) 'font-lock-string-face) + `(c-put-font-lock-face ,from ,to 'font-lock-string-face))) + + (defmacro c-fontify-types-and-refs (varlist &rest body) + ;; Like `let', but additionally activates `c-record-type-identifiers' + ;; and `c-record-ref-identifiers', and fontifies the recorded ranges + ;; accordingly on exit. + ;; + ;; This function does hidden buffer changes. + `(let ((c-record-type-identifiers t) + c-record-ref-identifiers + ,@varlist) + (prog1 (progn ,@body) + (c-fontify-recorded-types-and-refs)))) + (put 'c-fontify-types-and-refs 'lisp-indent-function 1) + + (defun c-skip-comments-and-strings (limit) + ;; If the point is within a region fontified as a comment or + ;; string literal skip to the end of it or to LIMIT, whichever + ;; comes first, and return t. Otherwise return nil. The match + ;; data is not clobbered. + ;; + ;; This function might do hidden buffer changes. + (when (c-got-face-at (point) c-literal-faces) + (while (progn + (goto-char (c-next-single-property-change + (point) 'face nil limit)) + (and (< (point) limit) + (c-got-face-at (point) c-literal-faces)))) + t)) + + (defun c-make-syntactic-matcher (regexp) + ;; Returns a byte compiled function suitable for use in place of a + ;; regexp string in a `font-lock-keywords' matcher, except that + ;; only matches outside comments and string literals count. + ;; + ;; This function does not do any hidden buffer changes, but the + ;; generated functions will. (They are however used in places + ;; covered by the font-lock context.) + (byte-compile + `(lambda (limit) + (let (res) + (while (and (setq res (re-search-forward ,regexp limit t)) + (progn + (goto-char (match-beginning 0)) + (or (c-skip-comments-and-strings limit) + (progn + (goto-char (match-end 0)) + nil))))) + res)))) + + (defun c-make-font-lock-search-form (regexp highlights) + ;; Return a lisp form which will fontify every occurence of REGEXP + ;; (a regular expression, NOT a function) between POINT and `limit' + ;; with HIGHLIGHTS, a list of highlighters as specified on page + ;; "Search-based Fontification" in the elisp manual. + `(while (re-search-forward ,regexp limit t) + (unless (progn + (goto-char (match-beginning 0)) + (c-skip-comments-and-strings limit)) + (goto-char (match-end 0)) + ,@(mapcar + (lambda (highlight) + (if (integerp (car highlight)) + ;; e.g. highlight is (1 font-lock-type-face t) + (progn + (unless (eq (nth 2 highlight) t) + (error + "The override flag must currently be t in %s" + highlight)) + (when (nth 3 highlight) + (error + "The laxmatch flag may currently not be set in %s" + highlight)) + `(save-match-data + (c-put-font-lock-face + (match-beginning ,(car highlight)) + (match-end ,(car highlight)) + ,(elt highlight 1)))) + ;; highlight is an "ANCHORED HIGHLIGHER" of the form + ;; (ANCHORED-MATCHER PRE-FORM POST-FORM SUBEXP-HIGHLIGHTERS...) + (when (nth 3 highlight) + (error "Match highlights currently not supported in %s" + highlight)) + `(progn + ,(nth 1 highlight) + (save-match-data ,(car highlight)) + ,(nth 2 highlight)))) + highlights)))) + + (defun c-make-font-lock-search-function (regexp &rest highlights) + ;; This function makes a byte compiled function that works much like + ;; a matcher element in `font-lock-keywords'. It cuts out a little + ;; bit of the overhead compared to a real matcher. The main reason + ;; is however to pass the real search limit to the anchored + ;; matcher(s), since most (if not all) font-lock implementations + ;; arbitrarily limit anchored matchers to the same line, and also + ;; to insulate against various other irritating differences between + ;; the different (X)Emacs font-lock packages. + ;; + ;; REGEXP is the matcher, which must be a regexp. Only matches + ;; where the beginning is outside any comment or string literal are + ;; significant. + ;; + ;; HIGHLIGHTS is a list of highlight specs, just like in + ;; `font-lock-keywords', with these limitations: The face is always + ;; overridden (no big disadvantage, since hits in comments etc are + ;; filtered anyway), there is no "laxmatch", and an anchored matcher + ;; is always a form which must do all the fontification directly. + ;; `limit' is a variable bound to the real limit in the context of + ;; the anchored matcher forms. + ;; + ;; This function does not do any hidden buffer changes, but the + ;; generated functions will. (They are however used in places + ;; covered by the font-lock context.) + + ;; Note: Replace `byte-compile' with `eval' to debug the generated + ;; lambda more easily. + (byte-compile + `(lambda (limit) + (let ( ;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + ,(c-make-font-lock-search-form regexp highlights)) + nil))) + + (defun c-make-font-lock-BO-decl-search-function (regexp &rest highlights) + ;; This function makes a byte compiled function that first moves back + ;; to the beginning of the current declaration (if any), then searches + ;; forward for matcher elements (as in `font-lock-keywords') and + ;; fontifies them. + ;; + ;; The motivation for moving back to the declaration start is to + ;; establish a context for the current text when, e.g., a character + ;; is typed on a C++ inheritance continuation line, or a jit-lock + ;; chunk starts there. + ;; + ;; The new function works much like a matcher element in + ;; `font-lock-keywords'. It cuts out a little bit of the overhead + ;; compared to a real matcher. The main reason is however to pass the + ;; real search limit to the anchored matcher(s), since most (if not + ;; all) font-lock implementations arbitrarily limit anchored matchers + ;; to the same line, and also to insulate against various other + ;; irritating differences between the different (X)Emacs font-lock + ;; packages. + ;; + ;; REGEXP is the matcher, which must be a regexp. Only matches + ;; where the beginning is outside any comment or string literal are + ;; significant. + ;; + ;; HIGHLIGHTS is a list of highlight specs, just like in + ;; `font-lock-keywords', with these limitations: The face is always + ;; overridden (no big disadvantage, since hits in comments etc are + ;; filtered anyway), there is no "laxmatch", and an anchored matcher + ;; is always a form which must do all the fontification directly. + ;; `limit' is a variable bound to the real limit in the context of + ;; the anchored matcher forms. + ;; + ;; This function does not do any hidden buffer changes, but the + ;; generated functions will. (They are however used in places + ;; covered by the font-lock context.) + + ;; Note: Replace `byte-compile' with `eval' to debug the generated + ;; lambda more easily. + (byte-compile + `(lambda (limit) + (let ( ;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties))) + (BOD-limit + (c-determine-limit 1000))) + (goto-char + (let ((here (point))) + (if (eq (car (c-beginning-of-decl-1 BOD-limit)) 'same) + (point) + here))) + ,(c-make-font-lock-search-form regexp highlights)) + nil))) + + (defun c-make-font-lock-context-search-function (normal &rest state-stanzas) + ;; This function makes a byte compiled function that works much like + ;; a matcher element in `font-lock-keywords', with the following + ;; enhancement: the generated function will test for particular "font + ;; lock contexts" at the start of the region, i.e. is this point in + ;; the middle of some particular construct? if so the generated + ;; function will first fontify the tail of the construct, before + ;; going into the main loop and fontify full constructs up to limit. + ;; + ;; The generated function takes one parameter called `limit', and + ;; will fontify the region between POINT and LIMIT. + ;; + ;; NORMAL is a list of the form (REGEXP HIGHLIGHTS .....), and is + ;; used to fontify the "regular" bit of the region. + ;; STATE-STANZAS is list of elements of the form (STATE LIM REGEXP + ;; HIGHLIGHTS), each element coding one possible font lock context. + + ;; o - REGEXP is a font-lock regular expression (NOT a function), + ;; o - HIGHLIGHTS is a list of zero or more highlighters as defined + ;; on page "Search-based Fontification" in the elisp manual. As + ;; yet (2009-06), they must have OVERRIDE set, and may not have + ;; LAXMATCH set. + ;; + ;; o - STATE is the "font lock context" (e.g. in-cpp-expr) and is + ;; not quoted. + ;; o - LIM is a lisp form whose evaluation will yield the limit + ;; position in the buffer for fontification by this stanza. + ;; + ;; This function does not do any hidden buffer changes, but the + ;; generated functions will. (They are however used in places + ;; covered by the font-lock context.) + ;; + ;; Note: Replace `byte-compile' with `eval' to debug the generated + ;; lambda more easily. + (byte-compile + `(lambda (limit) + (let ( ;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + ,@(mapcar + (lambda (stanza) + (let ((state (car stanza)) + (lim (nth 1 stanza)) + (regexp (nth 2 stanza)) + (highlights (cdr (cddr stanza)))) + `(if (eq c-font-lock-context ',state) + (let ((limit ,lim)) + ,(c-make-font-lock-search-form + regexp highlights))))) + state-stanzas) + ,(c-make-font-lock-search-form (car normal) (cdr normal)) + nil)))) + + (eval-after-load "edebug" + '(progn + (def-edebug-spec c-fontify-types-and-refs let*) + (def-edebug-spec c-make-syntactic-matcher t) + ;; If there are literal quoted or backquoted highlight specs in + ;; the call to `c-make-font-lock-search-function' then let's + ;; instrument the forms in them. + (def-edebug-spec c-make-font-lock-search-function + (form &rest &or ("quote" (&rest form)) ("`" (&rest form)) form))))) + +(defun c-fontify-recorded-types-and-refs () + ;; Convert the ranges recorded on `c-record-type-identifiers' and + ;; `c-record-ref-identifiers' to fontification. + ;; + ;; This function does hidden buffer changes. + (let (elem) + (while (consp c-record-type-identifiers) + (setq elem (car c-record-type-identifiers) + c-record-type-identifiers (cdr c-record-type-identifiers)) + (c-put-font-lock-face (car elem) (cdr elem) + 'font-lock-type-face)) + (while c-record-ref-identifiers + (setq elem (car c-record-ref-identifiers) + c-record-ref-identifiers (cdr c-record-ref-identifiers)) + ;; Note that the reference face is a variable that is + ;; dereferenced, since it's an alias in Emacs. + (c-put-font-lock-face (car elem) (cdr elem) + c-reference-face-name)))) + +(c-lang-defconst c-cpp-matchers + "Font lock matchers for preprocessor directives and purely lexical +stuff. Used on level 1 and higher." + + ;; Note: `c-font-lock-declarations' assumes that no matcher here + ;; sets `font-lock-type-face' in languages where + ;; `c-recognize-<>-arglists' is set. + + t `(,@(when (c-lang-const c-opt-cpp-prefix) + (let* ((noncontinued-line-end "\\(\\=\\|\\(\\=\\|[^\\]\\)[\n\r]\\)") + (ncle-depth (regexp-opt-depth noncontinued-line-end)) + (sws-depth (c-lang-const c-syntactic-ws-depth)) + (nsws-depth (c-lang-const c-nonempty-syntactic-ws-depth))) + + `(;; The stuff after #error and #warning is a message, so + ;; fontify it as a string. + ,@(when (c-lang-const c-cpp-message-directives) + (let* ((re (c-make-keywords-re 'appendable ; nil + (c-lang-const c-cpp-message-directives))) + (re-depth (regexp-opt-depth re))) + `((,(concat noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + re + "\\s +\\(.*\\)$") + ,(+ ncle-depth re-depth 1) font-lock-string-face t)))) + + ;; Fontify filenames in #include <...> as strings. + ,@(when (c-lang-const c-cpp-include-directives) + (let* ((re (c-make-keywords-re nil + (c-lang-const c-cpp-include-directives))) + (re-depth (regexp-opt-depth re))) + `((,(concat noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + re + (c-lang-const c-syntactic-ws) + "\\(<[^>\n\r]*>?\\)") + (,(+ ncle-depth re-depth sws-depth 1) + font-lock-string-face) + + ;; Use an anchored matcher to put paren syntax + ;; on the brackets. + (,(byte-compile + `(lambda (limit) + (let ((beg (match-beginning + ,(+ ncle-depth re-depth sws-depth 1))) + (end (1- (match-end ,(+ ncle-depth re-depth + sws-depth 1))))) + (if (eq (char-after end) ?>) + (progn + (c-mark-<-as-paren beg) + (c-mark->-as-paren end)) + (c-unmark-<->-as-paren beg))) + nil))))))) + + ;; #define. + ,@(when (c-lang-const c-opt-cpp-macro-define) + `((,(c-make-font-lock-search-function + (concat + noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + (c-lang-const c-opt-cpp-macro-define) + (c-lang-const c-nonempty-syntactic-ws) + "\\(" (c-lang-const ; 1 + ncle + nsws + c-symbol-key) "\\)" + (concat "\\(" ; 2 + ncle + nsws + c-sym-key + ;; Macro with arguments - a "function". + "\\(\(\\)" ; 3 + ncle + nsws + c-sym-key + "\\|" + ;; Macro without arguments - a "variable". + "\\([^\(]\\|$\\)" + "\\)")) + `((if (match-beginning + ,(+ 3 ncle-depth nsws-depth + (c-lang-const c-symbol-key-depth))) + + ;; "Function". Fontify the name and the arguments. + (save-restriction + (c-put-font-lock-face + (match-beginning ,(+ 1 ncle-depth nsws-depth)) + (match-end ,(+ 1 ncle-depth nsws-depth)) + 'font-lock-function-name-face) + (goto-char + (match-end + ,(+ 3 ncle-depth nsws-depth + (c-lang-const c-symbol-key-depth)))) + + (narrow-to-region (point-min) limit) + (while (and + (progn + (c-forward-syntactic-ws) + (looking-at c-symbol-key)) + (progn + (c-put-font-lock-face + (match-beginning 0) (match-end 0) + 'font-lock-variable-name-face) + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + (eq (char-after) ?,))) + (forward-char))) + + ;; "Variable". + (c-put-font-lock-face + (match-beginning ,(+ 1 ncle-depth nsws-depth)) + (match-end ,(+ 1 ncle-depth nsws-depth)) + 'font-lock-variable-name-face))))))) + + ;; Fontify cpp function names in preprocessor + ;; expressions in #if and #elif. + ,@(when (and (c-lang-const c-cpp-expr-directives) + (c-lang-const c-cpp-expr-functions)) + (let ((ced-re (c-make-keywords-re t + (c-lang-const c-cpp-expr-directives))) + (cef-re (c-make-keywords-re t + (c-lang-const c-cpp-expr-functions)))) + + `((,(c-make-font-lock-context-search-function + `(,(concat noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + ced-re ; 1 + ncle-depth + ;; Match the whole logical line to look + ;; for the functions in. + "\\(\\\\\\(.\\|[\n\r]\\)\\|[^\n\r]\\)*") + ((let ((limit (match-end 0))) + (while (re-search-forward ,cef-re limit 'move) + (c-put-font-lock-face (match-beginning 1) + (match-end 1) + c-preprocessor-face-name))) + (goto-char (match-end ,(1+ ncle-depth))))) + `(in-cpp-expr + (save-excursion (c-end-of-macro) (point)) + ,cef-re + (1 c-preprocessor-face-name t))))))) + + ;; Fontify the directive names. + (,(c-make-font-lock-search-function + (concat noncontinued-line-end + "\\(" + (c-lang-const c-opt-cpp-prefix) + "[" (c-lang-const c-symbol-chars) "]+" + "\\)") + `(,(1+ ncle-depth) c-preprocessor-face-name t))) + + (eval . (list ,(c-make-syntactic-matcher + (concat noncontinued-line-end + (c-lang-const c-opt-cpp-prefix) + "if\\(n\\)def\\>")) + ,(+ ncle-depth 1) + c-negation-char-face-name + 'append)) + ))) + + ,@(when (c-major-mode-is 'pike-mode) + ;; Recognize hashbangs in Pike. + `((eval . (list "\\`#![^\n\r]*" + 0 c-preprocessor-face-name)))) + + ;; Make hard spaces visible through an inverted `font-lock-warning-face'. + (eval . (list + "\240" + 0 (progn + (unless (c-face-name-p 'c-nonbreakable-space-face) + (c-make-inverse-face 'font-lock-warning-face + 'c-nonbreakable-space-face)) + ''c-nonbreakable-space-face))) + )) + +(defun c-font-lock-invalid-string () + ;; Assuming the point is after the opening character of a string, + ;; fontify that char with `font-lock-warning-face' if the string + ;; decidedly isn't terminated properly. + ;; + ;; This function does hidden buffer changes. + (let ((start (1- (point)))) + (save-excursion + (and (eq (elt (parse-partial-sexp start (c-point 'eol)) 8) start) + (if (if (integerp ?c) + ;; Emacs + (integerp c-multiline-string-start-char) + ;; XEmacs + (characterp c-multiline-string-start-char)) + ;; There's no multiline string start char before the + ;; string, so newlines aren't allowed. + (not (eq (char-before start) c-multiline-string-start-char)) + ;; Multiline strings are allowed anywhere if + ;; c-multiline-string-start-char is t. + (not c-multiline-string-start-char)) + (if c-string-escaped-newlines + ;; There's no \ before the newline. + (not (eq (char-before (point)) ?\\)) + ;; Escaped newlines aren't supported. + t) + (c-put-font-lock-face start (1+ start) 'font-lock-warning-face))))) + +(c-lang-defconst c-basic-matchers-before + "Font lock matchers for basic keywords, labels, references and various +other easily recognizable things that should be fontified before generic +casts and declarations are fontified. Used on level 2 and higher." + + ;; Note: `c-font-lock-declarations' assumes that no matcher here + ;; sets `font-lock-type-face' in languages where + ;; `c-recognize-<>-arglists' is set. + + t `(;; Put a warning face on the opener of unclosed strings that + ;; can't span lines. Later font + ;; lock packages have a `font-lock-syntactic-face-function' for + ;; this, but it doesn't give the control we want since any + ;; fontification done inside the function will be + ;; unconditionally overridden. + ,(c-make-font-lock-search-function + ;; Match a char before the string starter to make + ;; `c-skip-comments-and-strings' work correctly. + (concat ".\\(" c-string-limit-regexp "\\)") + '((c-font-lock-invalid-string))) + + ;; Fontify keyword constants. + ,@(when (c-lang-const c-constant-kwds) + (let ((re (c-make-keywords-re nil (c-lang-const c-constant-kwds)))) + (if (c-major-mode-is 'pike-mode) + ;; No symbol is a keyword after "->" in Pike. + `((eval . (list ,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" + "\\<\\(" re "\\)\\>") + 2 c-constant-face-name))) + `((eval . (list ,(concat "\\<\\(" re "\\)\\>") + 1 c-constant-face-name)))))) + + ;; Fontify all keywords except the primitive types. + ,(if (c-major-mode-is 'pike-mode) + ;; No symbol is a keyword after "->" in Pike. + `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" + "\\<" (c-lang-const c-regular-keywords-regexp)) + 2 font-lock-keyword-face) + `(,(concat "\\<" (c-lang-const c-regular-keywords-regexp)) + 1 font-lock-keyword-face)) + + ;; The following must come before c-font-lock-enclosing-decls in + ;; c-complex-decl-matchers. It fontifies java @annotations. + ,@(when (c-major-mode-is 'java-mode) + `((eval . (list "\\<\\(@[a-zA-Z0-9]+\\)\\>" 1 + c-preprocessor-face-name + )))) + + ;; Fontify leading identifiers in fully qualified names like + ;; "foo::bar" in languages that supports such things. + ,@(when (c-lang-const c-opt-identifier-concat-key) + (if (c-major-mode-is 'java-mode) + ;; Java needs special treatment since "." is used both to + ;; qualify names and in normal indexing. Here we look for + ;; capital characters at the beginning of an identifier to + ;; recognize the class. "*" is also recognized to cover + ;; wildcard import declarations. All preceding dot separated + ;; identifiers are taken as package names and therefore + ;; fontified as references. + `(,(c-make-font-lock-search-function + ;; Search for class identifiers preceded by ".". The + ;; anchored matcher takes it from there. + (concat (c-lang-const c-opt-identifier-concat-key) + (c-lang-const c-simple-ws) "*" + (concat "\\(" + "[" c-upper "]" + "[" (c-lang-const c-symbol-chars) "]*" + "\\|" + "\\*" + "\\)")) + `((let (id-end) + (goto-char (1+ (match-beginning 0))) + (while (and (eq (char-before) ?.) + (progn + (backward-char) + (c-backward-syntactic-ws) + (setq id-end (point)) + (< (skip-chars-backward + ,(c-lang-const c-symbol-chars)) 0)) + (not (get-text-property (point) 'face))) + (c-put-font-lock-face (point) id-end + c-reference-face-name) + (c-backward-syntactic-ws))) + nil + (goto-char (match-end 0))))) + + `((,(byte-compile + ;; Must use a function here since we match longer than + ;; we want to move before doing a new search. This is + ;; not necessary for XEmacs since it restarts the + ;; search from the end of the first highlighted + ;; submatch (something that causes problems in other + ;; places). + `(lambda (limit) + (while (re-search-forward + ,(concat "\\(\\<" ; 1 + "\\(" (c-lang-const c-symbol-key) "\\)" ; 2 + (c-lang-const c-simple-ws) "*" + (c-lang-const c-opt-identifier-concat-key) + (c-lang-const c-simple-ws) "*" + "\\)" + "\\(" + (c-lang-const c-opt-after-id-concat-key) + "\\)") + limit t) + (unless (progn + (goto-char (match-beginning 0)) + (c-skip-comments-and-strings limit)) + (or (get-text-property (match-beginning 2) 'face) + (c-put-font-lock-face (match-beginning 2) + (match-end 2) + c-reference-face-name)) + (goto-char (match-end 1)))))))))) + + ;; Fontify the special declarations in Objective-C. + ,@(when (c-major-mode-is 'objc-mode) + `(;; Fontify class names in the beginning of message expressions. + ,(c-make-font-lock-search-function + "\\[" + '((c-fontify-types-and-refs () + (c-forward-syntactic-ws limit) + (let ((start (point))) + ;; In this case we accept both primitive and known types. + (when (eq (c-forward-type) 'known) + (goto-char start) + (let ((c-promote-possible-types t)) + (c-forward-type)))) + (if (> (point) limit) (goto-char limit))))) + + ;; The @interface/@implementation/@protocol directives. + ,(c-make-font-lock-search-function + (concat "\\<" + (regexp-opt + '("@interface" "@implementation" "@protocol") + t) + "\\>") + '((c-fontify-types-and-refs + (;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + (c-forward-objc-directive) + nil) + (goto-char (match-beginning 0)))))) + + (eval . (list "\\(!\\)[^=]" 1 c-negation-char-face-name)) + )) + +(defun c-font-lock-complex-decl-prepare (limit) + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + ;; + ;; Called before any of the matchers in `c-complex-decl-matchers'. + ;; + ;; This function does hidden buffer changes. + + ;;(message "c-font-lock-complex-decl-prepare %s %s" (point) limit) + + ;; Clear the list of found types if we start from the start of the + ;; buffer, to make it easier to get rid of misspelled types and + ;; variables that have gotten recognized as types in malformed code. + (when (bobp) + (c-clear-found-types)) + + ;; Clear the c-type char properties which mark the region, to recalculate + ;; them properly. The most interesting properties are those put on the + ;; closest token before the region. + (save-excursion + (let ((pos (point))) + (c-backward-syntactic-ws) + (c-clear-char-properties + (if (and (not (bobp)) + (memq (c-get-char-property (1- (point)) 'c-type) + '(c-decl-arg-start + c-decl-end + c-decl-id-start + c-decl-type-start))) + (1- (point)) + pos) + limit 'c-type))) + + ;; Update `c-state-cache' to the beginning of the region. This will + ;; make `c-beginning-of-syntax' go faster when it's used later on, + ;; and it's near the point most of the time. + (c-parse-state) + + ;; Check if the fontified region starts inside a declarator list so + ;; that `c-font-lock-declarators' should be called at the start. + ;; The declared identifiers are font-locked correctly as types, if + ;; that is what they are. + (let ((prop (save-excursion + (c-backward-syntactic-ws) + (unless (bobp) + (c-get-char-property (1- (point)) 'c-type))))) + (when (memq prop '(c-decl-id-start c-decl-type-start)) + (c-forward-syntactic-ws limit) + (c-font-lock-declarators limit t (eq prop 'c-decl-type-start)))) + + (setq c-font-lock-context ;; (c-guess-font-lock-context) + (save-excursion + (if (and c-cpp-expr-intro-re + (c-beginning-of-macro) + (looking-at c-cpp-expr-intro-re)) + 'in-cpp-expr))) + nil) + +(defun c-font-lock-<>-arglists (limit) + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + ;; + ;; Fontify types and references in names containing angle bracket + ;; arglists from the point to LIMIT. Note that + ;; `c-font-lock-declarations' already has handled many of them. + ;; + ;; This function might do hidden buffer changes. + + (let (;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties))) + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists + id-start id-end id-face pos kwd-sym) + + (while (and (< (point) limit) + (re-search-forward c-opt-<>-arglist-start limit t)) + + (setq id-start (match-beginning 1) + id-end (match-end 1) + pos (point)) + + (goto-char id-start) + (unless (c-skip-comments-and-strings limit) + (setq kwd-sym nil + c-restricted-<>-arglists nil + id-face (get-text-property id-start 'face)) + + (if (cond + ((eq id-face 'font-lock-type-face) + ;; The identifier got the type face so it has already been + ;; handled in `c-font-lock-declarations'. + nil) + + ((eq id-face 'font-lock-keyword-face) + (when (looking-at c-opt-<>-sexp-key) + ;; There's a special keyword before the "<" that tells + ;; that it's an angle bracket arglist. + (setq kwd-sym (c-keyword-sym (match-string 1))))) + + (t + ;; There's a normal identifier before the "<". If we're not in + ;; a declaration context then we set `c-restricted-<>-arglists' + ;; to avoid recognizing templates in function calls like "foo (a + ;; < b, c > d)". + (c-backward-syntactic-ws) + (when (and (memq (char-before) '(?\( ?,)) + (not (eq (get-text-property (1- (point)) 'c-type) + 'c-decl-arg-start))) + (setq c-restricted-<>-arglists t)) + t)) + + (progn + (goto-char (1- pos)) + ;; Check for comment/string both at the identifier and + ;; at the "<". + (unless (c-skip-comments-and-strings limit) + + (c-fontify-types-and-refs () + (when (c-forward-<>-arglist (c-keyword-member + kwd-sym 'c-<>-type-kwds)) + (when (and c-opt-identifier-concat-key + (not (get-text-property id-start 'face))) + (c-forward-syntactic-ws) + (if (looking-at c-opt-identifier-concat-key) + (c-put-font-lock-face id-start id-end + c-reference-face-name) + (c-put-font-lock-face id-start id-end + 'font-lock-type-face))))) + + (goto-char pos))) + (goto-char pos))))) + nil) + +(defun c-font-lock-declarators (limit list types) + ;; Assuming the point is at the start of a declarator in a declaration, + ;; fontify the identifier it declares. (If TYPES is set, it does this via + ;; the macro `c-fontify-types-and-refs'.) + ;; + ;; If LIST is non-nil, also fontify the ids in any following declarators in + ;; a comma separated list (e.g. "foo" and "*bar" in "int foo = 17, *bar;"); + ;; additionally, mark the commas with c-type property 'c-decl-id-start or + ;; 'c-decl-type-start (according to TYPES). Stop at LIMIT. + ;; + ;; If TYPES is non-nil, fontify all identifiers as types. + ;; + ;; Nil is always returned. The function leaves point at the delimiter after + ;; the last declarator it processes. + ;; + ;; This function might do hidden buffer changes. + + ;;(message "c-font-lock-declarators from %s to %s" (point) limit) + (c-fontify-types-and-refs + ((pos (point)) next-pos id-start id-end + paren-depth + id-face got-init + c-last-identifier-range + (separator-prop (if types 'c-decl-type-start 'c-decl-id-start))) + + ;; The following `while' fontifies a single declarator id each time round. + ;; It loops only when LIST is non-nil. + (while + ;; Inside the following "condition form", we move forward over the + ;; declarator's identifier up as far as any opening bracket (for array + ;; size) or paren (for parameters of function-type) or brace (for + ;; array/struct initialisation) or "=" or terminating delimiter + ;; (e.g. "," or ";" or "}"). + (and + pos + (< (point) limit) + + ;; The following form moves forward over the declarator's + ;; identifier (and what precedes it), returning t. If there + ;; wasn't one, it returns nil, terminating the `while'. + (let (got-identifier) + (setq paren-depth 0) + ;; Skip over type decl prefix operators, one for each iteration + ;; of the while. These are, e.g. "*" in "int *foo" or "(" and + ;; "*" in "int (*foo) (void)" (Note similar code in + ;; `c-forward-decl-or-cast-1'.) + (while (and (looking-at c-type-decl-prefix-key) + (if (and (c-major-mode-is 'c++-mode) + (match-beginning 3)) + ;; If the third submatch matches in C++ then + ;; we're looking at an identifier that's a + ;; prefix only if it specifies a member pointer. + (progn + (setq id-start (point)) + (c-forward-name) + (if (looking-at "\\(::\\)") + ;; We only check for a trailing "::" and + ;; let the "*" that should follow be + ;; matched in the next round. + t + ;; It turned out to be the real identifier, + ;; so flag that and stop. + (setq got-identifier t) + nil)) + t)) + (if (eq (char-after) ?\() + (progn + (setq paren-depth (1+ paren-depth)) + (forward-char)) + (goto-char (match-end 1))) + (c-forward-syntactic-ws)) + + ;; If we haven't passed the identifier already, do it now. + (unless got-identifier + (setq id-start (point)) + (c-forward-name)) + (setq id-end (point)) + + (/= id-end pos)) + + ;; Skip out of the parens surrounding the identifier. If closing + ;; parens are missing, this form returns nil. + (or (= paren-depth 0) + (c-safe (goto-char (scan-lists (point) 1 paren-depth)))) + + (<= (point) limit) + + ;; Skip over any trailing bit, such as "__attribute__". + (progn + (when (looking-at c-decl-hangon-key) + (c-forward-keyword-clause 1)) + (<= (point) limit)) + + ;; Search syntactically to the end of the declarator (";", + ;; ",", a closen paren, eob etc) or to the beginning of an + ;; initializer or function prototype ("=" or "\\s\("). + ;; Note that the open paren will match array specs in + ;; square brackets, and we treat them as initializers too. + (c-syntactic-re-search-forward + "[;,]\\|\\s)\\|\\'\\|\\(=\\|\\s(\\)" limit t t)) + + (setq next-pos (match-beginning 0) + id-face (if (eq (char-after next-pos) ?\() + 'font-lock-function-name-face + 'font-lock-variable-name-face) + got-init (and (match-beginning 1) + (char-after (match-beginning 1)))) + + (if types + ;; Register and fontify the identifer as a type. + (let ((c-promote-possible-types t)) + (goto-char id-start) + (c-forward-type)) + ;; Fontify the last symbol in the identifier if it isn't fontified + ;; already. The check is necessary only in certain cases where this + ;; function is used "sloppily", e.g. in `c-simple-decl-matchers'. + (when (and c-last-identifier-range + (not (get-text-property (car c-last-identifier-range) + 'face))) + (c-put-font-lock-face (car c-last-identifier-range) + (cdr c-last-identifier-range) + id-face))) + + (goto-char next-pos) + (setq pos nil) ; So as to terminate the enclosing `while' form. + (when list + ;; Jump past any initializer or function prototype to see if + ;; there's a ',' to continue at. + (cond ((eq id-face 'font-lock-function-name-face) + ;; Skip a parenthesized initializer (C++) or a function + ;; prototype. + (if (c-safe (c-forward-sexp 1) t) ; over the parameter list. + (c-forward-syntactic-ws limit) + (goto-char limit))) ; unbalanced parens + + (got-init ; "=" sign OR opening "(", "[", or "{" + ;; Skip an initializer expression. If we're at a '=' + ;; then accept a brace list directly after it to cope + ;; with array initializers. Otherwise stop at braces + ;; to avoid going past full function and class blocks. + (and (if (and (eq got-init ?=) + (= (c-forward-token-2 1 nil limit) 0) + (looking-at "{")) + (c-safe (c-forward-sexp) t) ; over { .... } + t) + ;; FIXME: Should look for c-decl-end markers here; + ;; we might go far into the following declarations + ;; in e.g. ObjC mode (see e.g. methods-4.m). + (c-syntactic-re-search-forward "[;,{]" limit 'move t) + (backward-char))) + + (t (c-forward-syntactic-ws limit))) + + ;; If a ',' is found we set pos to the next declarator and iterate. + (when (and (< (point) limit) (looking-at ",")) + (c-put-char-property (point) 'c-type separator-prop) + (forward-char) + (c-forward-syntactic-ws limit) + (setq pos (point)))))) ; acts to make the `while' form continue. + nil) + +(defconst c-font-lock-maybe-decl-faces + ;; List of faces that might be put at the start of a type when + ;; `c-font-lock-declarations' runs. This needs to be evaluated to + ;; ensure that face name aliases in Emacs are resolved. + (list nil + font-lock-type-face + c-reference-face-name + font-lock-keyword-face)) + +(defun c-font-lock-declarations (limit) + ;; Fontify all the declarations, casts and labels from the point to LIMIT. + ;; Assumes that strings and comments have been fontified already. + ;; + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + ;; + ;; This function might do hidden buffer changes. + + ;;(message "c-font-lock-declarations search from %s to %s" (point) limit) + + (save-restriction + (let (;; The position where `c-find-decl-spots' last stopped. + start-pos + ;; o - 'decl if we're in an arglist containing declarations + ;; (but if `c-recognize-paren-inits' is set it might also be + ;; an initializer arglist); + ;; o - '<> if the arglist is of angle bracket type; + ;; o - 'arglist if it's some other arglist; + ;; o - nil, if not in an arglist at all. This includes the + ;; parenthesised condition which follows "if", "while", etc. + context + ;; A list of starting positions of possible type declarations, or of + ;; the typedef preceding one, if any. + last-cast-end + ;; The result from `c-forward-decl-or-cast-1'. + decl-or-cast + ;; The maximum of the end positions of all the checked type + ;; decl expressions in the successfully identified + ;; declarations. The position might be either before or + ;; after the syntactic whitespace following the last token + ;; in the type decl expression. + (max-type-decl-end 0) + ;; Same as `max-type-decl-*', but used when we're before + ;; `token-pos'. + (max-type-decl-end-before-token 0) + ;; Set according to the context to direct the heuristics for + ;; recognizing C++ templates. + c-restricted-<>-arglists + ;; Turn on recording of identifier ranges in + ;; `c-forward-decl-or-cast-1' and `c-forward-label' for + ;; later fontification. + (c-record-type-identifiers t) + label-type + c-record-ref-identifiers + ;; Make `c-forward-type' calls mark up template arglists if + ;; it finds any. That's necessary so that we later will + ;; stop inside them to fontify types there. + (c-parse-and-markup-<>-arglists t) + lbrace ; position of some {. + ;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + + ;; Below we fontify a whole declaration even when it crosses the limit, + ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a + ;; time. That is however annoying during editing, e.g. the following is + ;; a common situation while the first line is being written: + ;; + ;; my_variable + ;; some_other_variable = 0; + ;; + ;; font-lock will put the limit at the beginning of the second line + ;; here, and if we go past it we'll fontify "my_variable" as a type and + ;; "some_other_variable" as an identifier, and the latter will not + ;; correct itself until the second line is changed. To avoid that we + ;; narrow to the limit if the region to fontify is a single line. + (if (<= limit (c-point 'bonl)) + (narrow-to-region + (point-min) + (save-excursion + ;; Narrow after any operator chars following the limit though, + ;; since those characters can be useful in recognizing a + ;; declaration (in particular the '{' that opens a function body + ;; after the header). + (goto-char limit) + (skip-chars-forward c-nonsymbol-chars) + (point)))) + + (c-find-decl-spots + limit + c-decl-start-re + c-font-lock-maybe-decl-faces + + (lambda (match-pos inside-macro) + (setq start-pos (point)) + (when + ;; The result of the form below is true when we don't recognize a + ;; declaration or cast. + (if (or (and (eq (get-text-property (point) 'face) + 'font-lock-keyword-face) + (looking-at c-not-decl-init-keywords)) + (and c-macro-with-semi-re + (looking-at c-macro-with-semi-re))) ; 2008-11-04 + ;; Don't do anything more if we're looking at a keyword that + ;; can't start a declaration. + t + + ;; Set `context' and `c-restricted-<>-arglists'. Look for + ;; "<" for the sake of C++-style template arglists. + ;; Ignore "(" when it's part of a control flow construct + ;; (e.g. "for ("). + (let ((type (and (> match-pos (point-min)) + (c-get-char-property (1- match-pos) 'c-type)))) + (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?<))) + (setq context nil + c-restricted-<>-arglists nil)) + ;; A control flow expression + ((and (eq (char-before match-pos) ?\() + (save-excursion + (goto-char match-pos) + (backward-char) + (c-backward-token-2) + (looking-at c-block-stmt-2-key))) + (setq context nil + c-restricted-<>-arglists t)) + ;; Near BOB. + ((<= match-pos (point-min)) + (setq context 'arglist + c-restricted-<>-arglists t)) + ;; Got a cached hit in a declaration arglist. + ((eq type 'c-decl-arg-start) + (setq context 'decl + c-restricted-<>-arglists nil)) + ;; Inside an angle bracket arglist. + ((or (eq type 'c-<>-arg-sep) + (eq (char-before match-pos) ?<)) + (setq context '<> + c-restricted-<>-arglists nil)) + ;; Got a cached hit in some other type of arglist. + (type + (setq context 'arglist + c-restricted-<>-arglists t)) + ((if inside-macro + (< match-pos max-type-decl-end-before-token) + (< match-pos max-type-decl-end)) + ;; The point is within the range of a previously + ;; encountered type decl expression, so the arglist + ;; is probably one that contains declarations. + ;; However, if `c-recognize-paren-inits' is set it + ;; might also be an initializer arglist. + (setq context 'decl + c-restricted-<>-arglists nil) + ;; The result of this check is cached with a char + ;; property on the match token, so that we can look + ;; it up again when refontifying single lines in a + ;; multiline declaration. + (c-put-char-property (1- match-pos) + 'c-type 'c-decl-arg-start)) + (t (setq context 'arglist + c-restricted-<>-arglists t)))) + + ;; Check we haven't missed a preceding "typedef". + (when (not (looking-at c-typedef-key)) + (c-backward-syntactic-ws) + (c-backward-token-2) + (or (looking-at c-typedef-key) + (goto-char start-pos))) + + ;; In QT, "more" is an irritating keyword that expands to nothing. + ;; We skip over it to prevent recognition of "more slots: " + ;; as a bitfield declaration. + (when (and (c-major-mode-is 'c++-mode) + (looking-at + (concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)"))) + (goto-char (match-end 1)) + (c-forward-syntactic-ws)) + + ;; Now analyze the construct. + (setq decl-or-cast (c-forward-decl-or-cast-1 + match-pos context last-cast-end)) + + (cond + ((eq decl-or-cast 'cast) + ;; Save the position after the previous cast so we can feed + ;; it to `c-forward-decl-or-cast-1' in the next round. That + ;; helps it discover cast chains like "(a) (b) c". + (setq last-cast-end (point)) + (c-fontify-recorded-types-and-refs) + nil) + + (decl-or-cast + ;; We've found a declaration. + + ;; Set `max-type-decl-end' or `max-type-decl-end-before-token' + ;; under the assumption that we're after the first type decl + ;; expression in the declaration now. That's not really true; + ;; we could also be after a parenthesized initializer + ;; expression in C++, but this is only used as a last resort + ;; to slant ambiguous expression/declarations, and overall + ;; it's worth the risk to occasionally fontify an expression + ;; as a declaration in an initializer expression compared to + ;; getting ambiguous things in normal function prototypes + ;; fontified as expressions. + (if inside-macro + (when (> (point) max-type-decl-end-before-token) + (setq max-type-decl-end-before-token (point))) + (when (> (point) max-type-decl-end) + (setq max-type-decl-end (point)))) + + ;; Back up to the type to fontify the declarator(s). + (goto-char (car decl-or-cast)) + + (let ((decl-list + (if context + ;; Should normally not fontify a list of + ;; declarators inside an arglist, but the first + ;; argument in the ';' separated list of a "for" + ;; statement is an exception. + (when (eq (char-before match-pos) ?\() + (save-excursion + (goto-char (1- match-pos)) + (c-backward-syntactic-ws) + (and (c-simple-skip-symbol-backward) + (looking-at c-paren-stmt-key)))) + t))) + + ;; Fix the `c-decl-id-start' or `c-decl-type-start' property + ;; before the first declarator if it's a list. + ;; `c-font-lock-declarators' handles the rest. + (when decl-list + (save-excursion + (c-backward-syntactic-ws) + (unless (bobp) + (c-put-char-property (1- (point)) 'c-type + (if (cdr decl-or-cast) + 'c-decl-type-start + 'c-decl-id-start))))) + + (c-font-lock-declarators + (point-max) decl-list (cdr decl-or-cast))) + + ;; A declaration has been successfully identified, so do all the + ;; fontification of types and refs that've been recorded. + (c-fontify-recorded-types-and-refs) + nil) + + ;; Restore point, since at this point in the code it has been + ;; left undefined by c-forward-decl-or-cast-1 above. + ((progn (goto-char start-pos) nil)) + + ;; If point is inside a bracelist, there's no point checking it + ;; being at a declarator. + ((let ((paren-state (c-parse-state))) + (setq lbrace (c-cheap-inside-bracelist-p paren-state))) + ;; Move past this bracelist to prevent an endless loop. + (goto-char lbrace) + (unless (c-safe (progn (forward-list) t)) + (goto-char start-pos) + (c-forward-token-2)) + nil) + + ;; If point is just after a ")" which is followed by an + ;; identifier which isn't a label, or at the matching "(", we're + ;; at either a macro invocation, a cast, or a + ;; for/while/etc. statement. The cast case is handled above. + ;; None of these cases can contain a declarator. + ((or (and (eq (char-before match-pos) ?\)) + (c-on-identifier) + (save-excursion (not (c-forward-label)))) + (and (eq (char-after) ?\() + (save-excursion + (and + (progn (c-backward-token-2) (c-on-identifier)) + (save-excursion (not (c-forward-label))) + (progn (c-backward-token-2) + (eq (char-after) ?\()))))) + (c-forward-token-2) ; Must prevent looping. + nil) + + ((and (not c-enums-contain-decls) + ;; An optimisation quickly to eliminate scans of long enum + ;; declarations in the next cond arm. + (let ((paren-state (c-parse-state))) + (and + (numberp (car paren-state)) + (save-excursion + (goto-char (car paren-state)) + (c-backward-token-2) + (or (looking-at c-brace-list-key) + (progn + (c-backward-token-2) + (looking-at c-brace-list-key))))))) + (c-forward-token-2) + nil) + + (t + ;; Are we at a declarator? Try to go back to the declaration + ;; to check this. If we get there, check whether a "typedef" + ;; is there, then fontify the declarators accordingly. + (let ((decl-search-lim (c-determine-limit 1000)) + paren-state bod-res encl-pos is-typedef + c-recognize-knr-p) ; Strictly speaking, bogus, but it + ; speeds up lisp.h tremendously. + (save-excursion + (unless (or (eobp) + (looking-at "\\s(\\|\\s)")) + (forward-char)) + (setq bod-res (car (c-beginning-of-decl-1 decl-search-lim))) + (if (and (eq bod-res 'same) + (progn + (c-backward-syntactic-ws) + (eq (char-before) ?\}))) + (c-beginning-of-decl-1 decl-search-lim)) + + ;; We're now putatively at the declaration. + (setq paren-state (c-parse-state)) + ;; At top level or inside a "{"? + (if (or (not (setq encl-pos + (c-most-enclosing-brace paren-state))) + (eq (char-after encl-pos) ?\{)) + (progn + (when (looking-at c-typedef-key) ; "typedef" + (setq is-typedef t) + (goto-char (match-end 0)) + (c-forward-syntactic-ws)) + ;; At a real declaration? + (if (memq (c-forward-type t) '(t known found)) + (progn + (c-font-lock-declarators limit t is-typedef) + nil) + ;; False alarm. Return t to go on to the next check. + (goto-char start-pos) + t)) + t)))))) + + ;; It was a false alarm. Check if we're in a label (or other + ;; construct with `:' except bitfield) instead. + (goto-char start-pos) + (when (setq label-type (c-forward-label t match-pos nil)) + ;; Can't use `c-fontify-types-and-refs' here since we + ;; use the label face at times. + (cond ((eq label-type 'goto-target) + (c-put-font-lock-face (caar c-record-ref-identifiers) + (cdar c-record-ref-identifiers) + c-label-face-name)) + ((eq label-type 'qt-1kwd-colon) + (c-put-font-lock-face (caar c-record-ref-identifiers) + (cdar c-record-ref-identifiers) + 'font-lock-keyword-face)) + ((eq label-type 'qt-2kwds-colon) + (mapc + (lambda (kwd) + (c-put-font-lock-face (car kwd) (cdr kwd) + 'font-lock-keyword-face)) + c-record-ref-identifiers))) + (setq c-record-ref-identifiers nil) + ;; `c-forward-label' has probably added a `c-decl-end' + ;; marker, so return t to `c-find-decl-spots' to signal + ;; that. + t)))) + + nil))) + +(defun c-font-lock-enum-tail (limit) + ;; Fontify an enum's identifiers when POINT is within the enum's brace + ;; block. + ;; + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + ;; + ;; Note that this function won't attempt to fontify beyond the end of the + ;; current enum block, if any. + (let* ((paren-state (c-parse-state)) + (encl-pos (c-most-enclosing-brace paren-state))) + (when (and + encl-pos + (eq (char-after encl-pos) ?\{) + (save-excursion + (goto-char encl-pos) + (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward) + (or (looking-at c-brace-list-key) ; "enum" + (progn (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward) + (looking-at c-brace-list-key))))) + (c-syntactic-skip-backward "^{," nil t) + (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start) + + (c-forward-syntactic-ws) + (c-font-lock-declarators limit t nil))) + nil) + +(defun c-font-lock-enclosing-decls (limit) + ;; Fontify the declarators of (nested) declarations we're in the middle of. + ;; This is mainly for when a jit-lock etc. chunk starts inside the brace + ;; block of a struct/union/class, etc. + ;; + ;; This function will be called from font-lock for a region bounded by POINT + ;; and LIMIT, as though it were to identify a keyword for + ;; font-lock-keyword-face. It always returns NIL to inhibit this and + ;; prevent a repeat invocation. See elisp/lispref page "Search-based + ;; Fontification". + (let* ((paren-state (c-parse-state)) + decl-context in-typedef ps-elt) + ;; Are we in any nested struct/union/class/etc. braces? + (while paren-state + (setq ps-elt (car paren-state) + paren-state (cdr paren-state)) + (when (and (atom ps-elt) + (eq (char-after ps-elt) ?\{)) + (goto-char ps-elt) + (setq decl-context (c-beginning-of-decl-1) + in-typedef (looking-at c-typedef-key)) + (if in-typedef (c-forward-token-2)) + (when (and c-opt-block-decls-with-vars-key + (looking-at c-opt-block-decls-with-vars-key)) + (goto-char ps-elt) + (when (c-safe (c-forward-sexp)) + (c-forward-syntactic-ws) + (c-font-lock-declarators limit t in-typedef))))))) + +(c-lang-defconst c-simple-decl-matchers + "Simple font lock matchers for types and declarations. These are used +on level 2 only and so aren't combined with `c-complex-decl-matchers'." + + t `(;; Objective-C methods. + ,@(when (c-major-mode-is 'objc-mode) + `((,(c-lang-const c-opt-method-key) + (,(byte-compile + (lambda (limit) + (let (;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + (save-restriction + (narrow-to-region (point-min) limit) + (c-font-lock-objc-method))) + nil)) + (goto-char (match-end 1)))))) + + ;; Fontify all type names and the identifiers in the + ;; declarations they might start. Use eval here since + ;; `c-known-type-key' gets its value from + ;; `*-font-lock-extra-types' on mode init. + (eval . (list ,(c-make-font-lock-search-function + 'c-known-type-key + '(1 'font-lock-type-face t) + '((c-font-lock-declarators limit t nil) + (save-match-data + (goto-char (match-end 1)) + (c-forward-syntactic-ws)) + (goto-char (match-end 1)))))) + + ;; Fontify types preceded by `c-type-prefix-kwds' and the + ;; identifiers in the declarations they might start. + ,@(when (c-lang-const c-type-prefix-kwds) + (let* ((prefix-re (c-make-keywords-re nil + (c-lang-const c-type-prefix-kwds))) + (type-match (+ 2 + (regexp-opt-depth prefix-re) + (c-lang-const c-simple-ws-depth)))) + `((,(c-make-font-lock-search-function + (concat "\\<\\(" prefix-re "\\)" ; 1 + (c-lang-const c-simple-ws) "+" + (concat "\\(" ; 2 + prefix-re + c-simple-ws + (c-lang-const c-symbol-key) + "\\)")) + `(,type-match + 'font-lock-type-face t) + `((c-font-lock-declarators limit t nil) + (save-match-data + (goto-char (match-end ,type-match)) + (c-forward-syntactic-ws)) + (goto-char (match-end ,type-match)))))))) + + ;; Fontify special declarations that lacks a type. + ,@(when (c-lang-const c-typeless-decl-kwds) + `((,(c-make-font-lock-search-function + (concat "\\<\\(" + (regexp-opt (c-lang-const c-typeless-decl-kwds)) + "\\)\\>") + '((c-font-lock-declarators limit t nil) + (save-match-data + (goto-char (match-end 1)) + (c-forward-syntactic-ws)) + (goto-char (match-end 1))))))) + + ;; Fontify generic colon labels in languages that support them. + ,@(when (c-lang-const c-recognize-colon-labels) + `(c-font-lock-labels)))) + +(c-lang-defconst c-complex-decl-matchers + "Complex font lock matchers for types and declarations. Used on level +3 and higher." + + ;; Note: This code in this form dumps a number of functions into the + ;; resulting constant, `c-matchers-3'. At run time, font lock will call + ;; each of them as a "FUNCTION" (see Elisp page "Search-based + ;; Fontification"). The font lock region is delimited by POINT and the + ;; single parameter, LIMIT. Each of these functions returns NIL (thus + ;; inhibiting spurious font-lock-keyword-face highlighting and another + ;; call). + + t `(;; Initialize some things before the search functions below. + c-font-lock-complex-decl-prepare + + ,@(if (c-major-mode-is 'objc-mode) + ;; Fontify method declarations in Objective-C, but first + ;; we have to put the `c-decl-end' `c-type' property on + ;; all the @-style directives that haven't been handled in + ;; `c-basic-matchers-before'. + `(,(c-make-font-lock-search-function + (c-make-keywords-re t + ;; Exclude "@class" since that directive ends with a + ;; semicolon anyway. + (delete "@class" + (append (c-lang-const c-protection-kwds) + (c-lang-const c-other-decl-kwds) + nil))) + '((c-put-char-property (1- (match-end 1)) + 'c-type 'c-decl-end))) + c-font-lock-objc-methods)) + + ;; Fontify all declarations, casts and normal labels. + c-font-lock-declarations + + ;; Fontify declarators when POINT is within their declaration. + c-font-lock-enclosing-decls + + ;; Fontify angle bracket arglists like templates in C++. + ,@(when (c-lang-const c-recognize-<>-arglists) + `(c-font-lock-<>-arglists)) + + ;; The first two rules here mostly find occurences that + ;; `c-font-lock-declarations' has found already, but not + ;; declarations containing blocks in the type (see note below). + ;; It's also useful to fontify these everywhere to show e.g. when + ;; a type keyword is accidentally used as an identifier. + + ;; Fontify basic types. + ,(let ((re (c-make-keywords-re nil + (c-lang-const c-primitive-type-kwds)))) + (if (c-major-mode-is 'pike-mode) + ;; No symbol is a keyword after "->" in Pike. + `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)" + "\\<\\(" re "\\)\\>") + 2 font-lock-type-face) + `(,(concat "\\<\\(" re "\\)\\>") + 1 'font-lock-type-face))) + + ;; Fontify types preceded by `c-type-prefix-kwds' (e.g. "struct"). + ,@(when (c-lang-const c-type-prefix-kwds) + `((,(byte-compile + `(lambda (limit) + (c-fontify-types-and-refs + ((c-promote-possible-types t) + ;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + (save-restriction + ;; Narrow to avoid going past the limit in + ;; `c-forward-type'. + (narrow-to-region (point) limit) + (while (re-search-forward + ,(concat "\\<\\(" + (c-make-keywords-re nil + (c-lang-const c-type-prefix-kwds)) + "\\)\\>") + limit t) + (unless (c-skip-comments-and-strings limit) + (c-forward-syntactic-ws) + ;; Handle prefix declaration specifiers. + (when (or (looking-at c-prefix-spec-kwds-re) + (and (c-major-mode-is 'java-mode) + (looking-at "@[A-Za-z0-9]+"))) + (c-forward-keyword-clause 1)) + ,(if (c-major-mode-is 'c++-mode) + `(when (and (c-forward-type) + (eq (char-after) ?=)) + ;; In C++ we additionally check for a "class + ;; X = Y" construct which is used in + ;; templates, to fontify Y as a type. + (forward-char) + (c-forward-syntactic-ws) + (c-forward-type)) + `(c-forward-type)) + ))))))))) + + ;; Fontify symbols after closing braces as declaration + ;; identifiers under the assumption that they are part of + ;; declarations like "class Foo { ... } foo;". It's too + ;; expensive to check this accurately by skipping past the + ;; brace block, so we use the heuristic that it's such a + ;; declaration if the first identifier is on the same line as + ;; the closing brace. `c-font-lock-declarations' will later + ;; override it if it turns out to be an new declaration, but + ;; it will be wrong if it's an expression (see the test + ;; decls-8.cc). +;; ,@(when (c-lang-const c-opt-block-decls-with-vars-key) +;; `((,(c-make-font-lock-search-function +;; (concat "}" +;; (c-lang-const c-single-line-syntactic-ws) +;; "\\(" ; 1 + c-single-line-syntactic-ws-depth +;; (c-lang-const c-type-decl-prefix-key) +;; "\\|" +;; (c-lang-const c-symbol-key) +;; "\\)") +;; `((c-font-lock-declarators limit t nil) ; That `nil' says use `font-lock-variable-name-face'; +;; ; `t' would mean `font-lock-function-name-face'. +;; (progn +;; (c-put-char-property (match-beginning 0) 'c-type +;; 'c-decl-id-start) +;; ; 'c-decl-type-start) +;; (goto-char (match-beginning +;; ,(1+ (c-lang-const +;; c-single-line-syntactic-ws-depth))))) +;; (goto-char (match-end 0))))))) + + ;; Fontify the type in C++ "new" expressions. + ,@(when (c-major-mode-is 'c++-mode) + ;; This pattern is a probably a "(MATCHER . ANCHORED-HIGHLIGHTER)" + ;; (see Elisp page "Search-based Fontification"). + `(("\\" + (c-font-lock-c++-new)))) + )) + +(defun c-font-lock-labels (limit) + ;; Fontify all statement labels from the point to LIMIT. Assumes + ;; that strings and comments have been fontified already. Nil is + ;; always returned. + ;; + ;; Note: This function is only used on decoration level 2; this is + ;; taken care of directly by the gargantuan + ;; `c-font-lock-declarations' on higher levels. + ;; + ;; This function might do hidden buffer changes. + + (let (continue-pos id-start + ;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + + (while (re-search-forward ":[^:]" limit t) + (setq continue-pos (point)) + (goto-char (match-beginning 0)) + (unless (c-skip-comments-and-strings limit) + + (c-backward-syntactic-ws) + (and (setq id-start (c-on-identifier)) + + (not (get-text-property id-start 'face)) + + (progn + (goto-char id-start) + (c-backward-syntactic-ws) + (or + ;; Check for a char that precedes a statement. + (memq (char-before) '(?\} ?\{ ?\;)) + ;; Check for a preceding label. We exploit the font + ;; locking made earlier by this function. + (and (eq (char-before) ?:) + (progn + (backward-char) + (c-backward-syntactic-ws) + (not (bobp))) + (eq (get-text-property (1- (point)) 'face) + c-label-face-name)) + ;; Check for a keyword that precedes a statement. + (c-after-conditional))) + + (progn + ;; Got a label. + (goto-char id-start) + (looking-at c-symbol-key) + (c-put-font-lock-face (match-beginning 0) (match-end 0) + c-label-face-name))) + + (goto-char continue-pos)))) + nil) + +(c-lang-defconst c-basic-matchers-after + "Font lock matchers for various things that should be fontified after +generic casts and declarations are fontified. Used on level 2 and +higher." + + t `(,@(when (c-lang-const c-brace-id-list-kwds) + ;; Fontify the remaining identifiers inside an enum list when we start + ;; inside it. + `(c-font-lock-enum-tail + ;; Fontify the identifiers inside enum lists. (The enum type + ;; name is handled by `c-simple-decl-matchers' or + ;; `c-complex-decl-matchers' below. + (,(c-make-font-lock-search-function + (concat + "\\<\\(" + (c-make-keywords-re nil (c-lang-const c-brace-id-list-kwds)) + "\\)\\>" + ;; Disallow various common punctuation chars that can't come + ;; before the '{' of the enum list, to avoid searching too far. + "[^\]\[{}();,/#=]*" + "{") + '((c-font-lock-declarators limit t nil) + (save-match-data + (goto-char (match-end 0)) + (c-put-char-property (1- (point)) 'c-type + 'c-decl-id-start) + (c-forward-syntactic-ws)) + (goto-char (match-end 0))))))) + + ;; Fontify labels after goto etc. + ,@(when (c-lang-const c-before-label-kwds) + `(;; (Got three different interpretation levels here, + ;; which makes it a bit complicated: 1) The backquote + ;; stuff is expanded when compiled or loaded, 2) the + ;; eval form is evaluated at font-lock setup (to + ;; substitute c-label-face-name correctly), and 3) the + ;; resulting structure is interpreted during + ;; fontification.) + (eval + . ,(let* ((c-before-label-re + (c-make-keywords-re nil + (c-lang-const c-before-label-kwds)))) + `(list + ,(concat "\\<\\(" c-before-label-re "\\)\\>" + "\\s *" + "\\(" ; identifier-offset + (c-lang-const c-symbol-key) + "\\)") + (list ,(+ (regexp-opt-depth c-before-label-re) 2) + c-label-face-name nil t)))))) + + ;; Fontify the clauses after various keywords. + ,@(when (or (c-lang-const c-type-list-kwds) + (c-lang-const c-ref-list-kwds) + (c-lang-const c-colon-type-list-kwds)) + `((,(c-make-font-lock-BO-decl-search-function + (concat "\\<\\(" + (c-make-keywords-re nil + (append (c-lang-const c-type-list-kwds) + (c-lang-const c-ref-list-kwds) + (c-lang-const c-colon-type-list-kwds))) + "\\)\\>") + '((c-fontify-types-and-refs ((c-promote-possible-types t)) + (c-forward-keyword-clause 1) + (if (> (point) limit) (goto-char limit)))))))) + + ,@(when (c-lang-const c-paren-type-kwds) + `((,(c-make-font-lock-search-function + (concat "\\<\\(" + (c-make-keywords-re nil + (c-lang-const c-paren-type-kwds)) + "\\)\\>") + '((c-fontify-types-and-refs ((c-promote-possible-types t)) + (c-forward-keyword-clause 1) + (if (> (point) limit) (goto-char limit)))))))))) + +(c-lang-defconst c-matchers-1 + t (c-lang-const c-cpp-matchers)) + +(c-lang-defconst c-matchers-2 + t (append (c-lang-const c-matchers-1) + (c-lang-const c-basic-matchers-before) + (c-lang-const c-simple-decl-matchers) + (c-lang-const c-basic-matchers-after))) + +(c-lang-defconst c-matchers-3 + t (append (c-lang-const c-matchers-1) + (c-lang-const c-basic-matchers-before) + (c-lang-const c-complex-decl-matchers) + (c-lang-const c-basic-matchers-after))) + +(defun c-compose-keywords-list (base-list) + ;; Incorporate the font lock keyword lists according to + ;; `c-doc-comment-style' on the given keyword list and return it. + ;; This is used in the function bindings of the + ;; `*-font-lock-keywords-*' symbols since we have to build the list + ;; when font-lock is initialized. + + (unless (memq c-doc-face-name c-literal-faces) + (setq c-literal-faces (cons c-doc-face-name c-literal-faces))) + + (let* ((doc-keywords + (if (consp (car-safe c-doc-comment-style)) + (cdr-safe (or (assq c-buffer-is-cc-mode c-doc-comment-style) + (assq 'other c-doc-comment-style))) + c-doc-comment-style)) + (list (nconc (apply 'nconc + (mapcar + (lambda (doc-style) + (let ((sym (intern + (concat (symbol-name doc-style) + "-font-lock-keywords")))) + (cond ((fboundp sym) + (funcall sym)) + ((boundp sym) + (append (eval sym) nil))))) + (if (listp doc-keywords) + doc-keywords + (list doc-keywords)))) + base-list))) + + ;; Kludge: If `c-font-lock-complex-decl-prepare' is on the list we + ;; move it first since the doc comment font lockers might add + ;; `c-type' text properties, so they have to be cleared before that. + (when (memq 'c-font-lock-complex-decl-prepare list) + (setq list (cons 'c-font-lock-complex-decl-prepare + (delq 'c-font-lock-complex-decl-prepare + (append list nil))))) + + list)) + +(defun c-override-default-keywords (def-var) + ;; This is used to override the value on a `*-font-lock-keywords' + ;; variable only if it's nil or has the same value as one of the + ;; `*-font-lock-keywords-*' variables. Older font-lock packages + ;; define a default value for `*-font-lock-keywords' which we want + ;; to override, but we should otoh avoid clobbering a user setting. + ;; This heuristic for that isn't perfect, but I can't think of any + ;; better. /mast + (when (and (boundp def-var) + (memq (symbol-value def-var) + (cons nil + (mapcar + (lambda (suffix) + (let ((sym (intern (concat (symbol-name def-var) + suffix)))) + (and (boundp sym) (symbol-value sym)))) + '("-1" "-2" "-3"))))) + ;; The overriding is done by unbinding the variable so that the normal + ;; defvar will install its default value later on. + (makunbound def-var))) + + +;;; C. + +(c-override-default-keywords 'c-font-lock-keywords) + +(defconst c-font-lock-keywords-1 (c-lang-const c-matchers-1 c) + "Minimal font locking for C mode. +Fontifies only preprocessor directives (in addition to the syntactic +fontification of strings and comments).") + +(defconst c-font-lock-keywords-2 (c-lang-const c-matchers-2 c) + "Fast normal font locking for C mode. +In addition to `c-font-lock-keywords-1', this adds fontification of +keywords, simple types, declarations that are easy to recognize, the +user defined types on `c-font-lock-extra-types', and the doc comment +styles specified by `c-doc-comment-style'.") + +(defconst c-font-lock-keywords-3 (c-lang-const c-matchers-3 c) + "Accurate normal font locking for C mode. +Like `c-font-lock-keywords-2' but detects declarations in a more +accurate way that works in most cases for arbitrary types without the +need for `c-font-lock-extra-types'.") + +(defvar c-font-lock-keywords c-font-lock-keywords-3 + "Default expressions to highlight in C mode.") + +(defun c-font-lock-keywords-2 () + (c-compose-keywords-list c-font-lock-keywords-2)) +(defun c-font-lock-keywords-3 () + (c-compose-keywords-list c-font-lock-keywords-3)) +(defun c-font-lock-keywords () + (c-compose-keywords-list c-font-lock-keywords)) + + +;;; C++. + +(defun c-font-lock-c++-new (limit) + ;; FIXME!!! Put in a comment about the context of this function's + ;; invocation. I think it's called as an ANCHORED-MATCHER within an + ;; ANCHORED-HIGHLIGHTER. (2007/2/10). + ;; + ;; Assuming point is after a "new" word, check that it isn't inside + ;; a string or comment, and if so try to fontify the type in the + ;; allocation expression. Nil is always returned. + ;; + ;; As usual, C++ takes the prize in coming up with a hard to parse + ;; syntax. :P + ;; + ;; This function might do hidden buffer changes. + + (unless (c-skip-comments-and-strings limit) + (save-excursion + (catch 'false-alarm + ;; A "new" keyword is followed by one to three expressions, where + ;; the type is the middle one, and the only required part. + (let (expr1-pos expr2-pos + ;; Enable recording of identifier ranges in `c-forward-type' + ;; etc for later fontification. Not using + ;; `c-fontify-types-and-refs' here since the ranges should + ;; be fontified selectively only when an allocation + ;; expression is successfully recognized. + (c-record-type-identifiers t) + c-record-ref-identifiers + ;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + (c-forward-syntactic-ws) + + ;; The first placement arglist is always parenthesized, if it + ;; exists. + (when (eq (char-after) ?\() + (setq expr1-pos (1+ (point))) + (condition-case nil + (c-forward-sexp) + (scan-error (throw 'false-alarm t))) + (c-forward-syntactic-ws)) + + ;; The second expression is either a type followed by some "*" or + ;; "[...]" or similar, or a parenthesized type followed by a full + ;; identifierless declarator. + (setq expr2-pos (1+ (point))) + (cond ((eq (char-after) ?\()) + ((let ((c-promote-possible-types t)) + (c-forward-type))) + (t (setq expr2-pos nil))) + + (when expr1-pos + (cond + ((not expr2-pos) + ;; No second expression, so the first has to be a + ;; parenthesized type. + (goto-char expr1-pos) + (let ((c-promote-possible-types t)) + (c-forward-type))) + + ((eq (char-before expr2-pos) ?\() + ;; Got two parenthesized expressions, so we have to look + ;; closer at them to decide which is the type. No need to + ;; handle `c-record-ref-identifiers' since all references + ;; has already been handled by other fontification rules. + (let (expr1-res expr2-res) + + (goto-char expr1-pos) + (when (setq expr1-res (c-forward-type)) + (unless (looking-at + (cc-eval-when-compile + (concat (c-lang-const c-symbol-start c++) + "\\|[*:\)\[]"))) + ;; There's something after the would-be type that + ;; can't be there, so this is a placement arglist. + (setq expr1-res nil))) + + (goto-char expr2-pos) + (when (setq expr2-res (c-forward-type)) + (unless (looking-at + (cc-eval-when-compile + (concat (c-lang-const c-symbol-start c++) + "\\|[*:\)\[]"))) + ;; There's something after the would-be type that can't + ;; be there, so this is an initialization expression. + (setq expr2-res nil)) + (when (and (c-go-up-list-forward) + (progn (c-forward-syntactic-ws) + (eq (char-after) ?\())) + ;; If there's a third initialization expression + ;; then the second one is the type, so demote the + ;; first match. + (setq expr1-res nil))) + + ;; We fontify the most likely type, with a preference for + ;; the first argument since a placement arglist is more + ;; unusual than an initializer. + (cond ((memq expr1-res '(t known prefix))) + ((memq expr2-res '(t known prefix))) + ((eq expr1-res 'found) + (let ((c-promote-possible-types t)) + (goto-char expr1-pos) + (c-forward-type))) + ((eq expr2-res 'found) + (let ((c-promote-possible-types t)) + (goto-char expr2-pos) + (c-forward-type))) + ((and (eq expr1-res 'maybe) (not expr2-res)) + (let ((c-promote-possible-types t)) + (goto-char expr1-pos) + (c-forward-type))) + ((and (not expr1-res) (eq expr2-res 'maybe)) + (let ((c-promote-possible-types t)) + (goto-char expr2-pos) + (c-forward-type))) + ;; If both type matches are 'maybe then we're + ;; too uncertain to promote either of them. + ))))) + + ;; Fontify the type that now is recorded in + ;; `c-record-type-identifiers', if any. + (c-fontify-recorded-types-and-refs))))) + nil) + +(c-override-default-keywords 'c++-font-lock-keywords) + +(defconst c++-font-lock-keywords-1 (c-lang-const c-matchers-1 c++) + "Minimal font locking for C++ mode. +Fontifies only preprocessor directives (in addition to the syntactic +fontification of strings and comments).") + +(defconst c++-font-lock-keywords-2 (c-lang-const c-matchers-2 c++) + "Fast normal font locking for C++ mode. +In addition to `c++-font-lock-keywords-1', this adds fontification of +keywords, simple types, declarations that are easy to recognize, the +user defined types on `c++-font-lock-extra-types', and the doc comment +styles specified by `c-doc-comment-style'.") + +(defconst c++-font-lock-keywords-3 (c-lang-const c-matchers-3 c++) + "Accurate normal font locking for C++ mode. +Like `c++-font-lock-keywords-2' but detects declarations in a more +accurate way that works in most cases for arbitrary types without the +need for `c++-font-lock-extra-types'.") + +(defvar c++-font-lock-keywords c++-font-lock-keywords-3 + "Default expressions to highlight in C++ mode.") + +(defun c++-font-lock-keywords-2 () + (c-compose-keywords-list c++-font-lock-keywords-2)) +(defun c++-font-lock-keywords-3 () + (c-compose-keywords-list c++-font-lock-keywords-3)) +(defun c++-font-lock-keywords () + (c-compose-keywords-list c++-font-lock-keywords)) + + +;;; Objective-C. + +(defun c-font-lock-objc-method () + ;; Assuming the point is after the + or - that starts an Objective-C + ;; method declaration, fontify it. This must be done before normal + ;; casts, declarations and labels are fontified since they will get + ;; false matches in these things. + ;; + ;; This function might do hidden buffer changes. + + (c-fontify-types-and-refs + ((first t) + (c-promote-possible-types t)) + + (while (and + (progn + (c-forward-syntactic-ws) + + ;; An optional method type. + (if (eq (char-after) ?\() + (progn + (forward-char) + (c-forward-syntactic-ws) + (c-forward-type) + (prog1 (c-go-up-list-forward) + (c-forward-syntactic-ws))) + t)) + + ;; The name. The first time it's the first part of + ;; the function name, the rest of the time it's an + ;; argument name. + (looking-at c-symbol-key) + (progn + (goto-char (match-end 0)) + (c-put-font-lock-face (match-beginning 0) + (point) + (if first + 'font-lock-function-name-face + 'font-lock-variable-name-face)) + (c-forward-syntactic-ws) + + ;; Another optional part of the function name. + (when (looking-at c-symbol-key) + (goto-char (match-end 0)) + (c-put-font-lock-face (match-beginning 0) + (point) + 'font-lock-function-name-face) + (c-forward-syntactic-ws)) + + ;; There's another argument if a colon follows. + (eq (char-after) ?:))) + (forward-char) + (setq first nil)))) + +(defun c-font-lock-objc-methods (limit) + ;; Fontify method declarations in Objective-C. Nil is always + ;; returned. + ;; + ;; This function might do hidden buffer changes. + + (let (;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + + (c-find-decl-spots + limit + "[-+]" + nil + (lambda (match-pos inside-macro) + (forward-char) + (c-font-lock-objc-method)))) + nil) + +(c-override-default-keywords 'objc-font-lock-keywords) + +(defconst objc-font-lock-keywords-1 (c-lang-const c-matchers-1 objc) + "Minimal font locking for Objective-C mode. +Fontifies only compiler directives (in addition to the syntactic +fontification of strings and comments).") + +(defconst objc-font-lock-keywords-2 (c-lang-const c-matchers-2 objc) + "Fast normal font locking for Objective-C mode. +In addition to `objc-font-lock-keywords-1', this adds fontification of +keywords, simple types, declarations that are easy to recognize, the +user defined types on `objc-font-lock-extra-types', and the doc +comment styles specified by `c-doc-comment-style'.") + +(defconst objc-font-lock-keywords-3 (c-lang-const c-matchers-3 objc) + "Accurate normal font locking for Objective-C mode. +Like `objc-font-lock-keywords-2' but detects declarations in a more +accurate way that works in most cases for arbitrary types without the +need for `objc-font-lock-extra-types'.") + +(defvar objc-font-lock-keywords objc-font-lock-keywords-3 + "Default expressions to highlight in Objective-C mode.") + +(defun objc-font-lock-keywords-2 () + (c-compose-keywords-list objc-font-lock-keywords-2)) +(defun objc-font-lock-keywords-3 () + (c-compose-keywords-list objc-font-lock-keywords-3)) +(defun objc-font-lock-keywords () + (c-compose-keywords-list objc-font-lock-keywords)) + +;; Kludge to override the default value that +;; `objc-font-lock-extra-types' might have gotten from the font-lock +;; package. The value replaced here isn't relevant now anyway since +;; those types are builtin and therefore listed directly in +;; `c-primitive-type-kwds'. +(when (equal (sort (append objc-font-lock-extra-types nil) 'string-lessp) + '("BOOL" "Class" "IMP" "SEL")) + (setq objc-font-lock-extra-types + (cc-eval-when-compile (list (concat "[" c-upper "]\\sw*"))))) + + +;;; Java. + +(c-override-default-keywords 'java-font-lock-keywords) + +(defconst java-font-lock-keywords-1 (c-lang-const c-matchers-1 java) + "Minimal font locking for Java mode. +Fontifies nothing except the syntactic fontification of strings and +comments.") + +(defconst java-font-lock-keywords-2 (c-lang-const c-matchers-2 java) + "Fast normal font locking for Java mode. +In addition to `java-font-lock-keywords-1', this adds fontification of +keywords, simple types, declarations that are easy to recognize, the +user defined types on `java-font-lock-extra-types', and the doc +comment styles specified by `c-doc-comment-style'.") + +(defconst java-font-lock-keywords-3 (c-lang-const c-matchers-3 java) + "Accurate normal font locking for Java mode. +Like `java-font-lock-keywords-2' but detects declarations in a more +accurate way that works in most cases for arbitrary types without the +need for `java-font-lock-extra-types'.") + +(defvar java-font-lock-keywords java-font-lock-keywords-3 + "Default expressions to highlight in Java mode.") + +(defun java-font-lock-keywords-2 () + (c-compose-keywords-list java-font-lock-keywords-2)) +(defun java-font-lock-keywords-3 () + (c-compose-keywords-list java-font-lock-keywords-3)) +(defun java-font-lock-keywords () + (c-compose-keywords-list java-font-lock-keywords)) + + +;;; CORBA IDL. + +(c-override-default-keywords 'idl-font-lock-keywords) + +(defconst idl-font-lock-keywords-1 (c-lang-const c-matchers-1 idl) + "Minimal font locking for CORBA IDL mode. +Fontifies nothing except the syntactic fontification of strings and +comments.") + +(defconst idl-font-lock-keywords-2 (c-lang-const c-matchers-2 idl) + "Fast normal font locking for CORBA IDL mode. +In addition to `idl-font-lock-keywords-1', this adds fontification of +keywords, simple types, declarations that are easy to recognize, the +user defined types on `idl-font-lock-extra-types', and the doc comment +styles specified by `c-doc-comment-style'.") + +(defconst idl-font-lock-keywords-3 (c-lang-const c-matchers-3 idl) + "Accurate normal font locking for CORBA IDL mode. +Like `idl-font-lock-keywords-2' but detects declarations in a more +accurate way that works in most cases for arbitrary types without the +need for `idl-font-lock-extra-types'.") + +(defvar idl-font-lock-keywords idl-font-lock-keywords-3 + "Default expressions to highlight in CORBA IDL mode.") + +(defun idl-font-lock-keywords-2 () + (c-compose-keywords-list idl-font-lock-keywords-2)) +(defun idl-font-lock-keywords-3 () + (c-compose-keywords-list idl-font-lock-keywords-3)) +(defun idl-font-lock-keywords () + (c-compose-keywords-list idl-font-lock-keywords)) + + +;;; Pike. + +(c-override-default-keywords 'pike-font-lock-keywords) + +(defconst pike-font-lock-keywords-1 (c-lang-const c-matchers-1 pike) + "Minimal font locking for Pike mode. +Fontifies only preprocessor directives (in addition to the syntactic +fontification of strings and comments).") + +(defconst pike-font-lock-keywords-2 (c-lang-const c-matchers-2 pike) + "Fast normal font locking for Pike mode. +In addition to `pike-font-lock-keywords-1', this adds fontification of +keywords, simple types, declarations that are easy to recognize, the +user defined types on `pike-font-lock-extra-types', and the doc +comment styles specified by `c-doc-comment-style'.") + +(defconst pike-font-lock-keywords-3 (c-lang-const c-matchers-3 pike) + "Accurate normal font locking for Pike mode. +Like `pike-font-lock-keywords-2' but detects declarations in a more +accurate way that works in most cases for arbitrary types without the +need for `pike-font-lock-extra-types'.") + +(defvar pike-font-lock-keywords pike-font-lock-keywords-3 + "Default expressions to highlight in Pike mode.") + +(defun pike-font-lock-keywords-2 () + (c-compose-keywords-list pike-font-lock-keywords-2)) +(defun pike-font-lock-keywords-3 () + (c-compose-keywords-list pike-font-lock-keywords-3)) +(defun pike-font-lock-keywords () + (c-compose-keywords-list pike-font-lock-keywords)) + + +;;; Doc comments. + +(defun c-font-lock-doc-comments (prefix limit keywords) + ;; Fontify the comments between the point and LIMIT whose start + ;; matches PREFIX with `c-doc-face-name'. Assumes comments have been + ;; fontified with `font-lock-comment-face' already. nil is always + ;; returned. + ;; + ;; After the fontification of a matching comment, fontification + ;; according to KEYWORDS is applied inside it. It's a list like + ;; `font-lock-keywords' except that anchored matches and eval + ;; clauses aren't supported and that some abbreviated forms can't be + ;; used. The buffer is narrowed to the comment while KEYWORDS is + ;; applied; leading comment starters are included but trailing + ;; comment enders for block comment are not. + ;; + ;; Note that faces added through KEYWORDS should never replace the + ;; existing `c-doc-face-name' face since the existence of that face + ;; is used as a flag in other code to skip comments. + ;; + ;; This function might do hidden buffer changes. + + (let (comment-beg region-beg) + (if (eq (get-text-property (point) 'face) + 'font-lock-comment-face) + ;; Handle the case when the fontified region starts inside a + ;; comment. + (let ((range (c-literal-limits))) + (setq region-beg (point)) + (when range + (goto-char (car range))) + (when (looking-at prefix) + (setq comment-beg (point))))) + + (while (or + comment-beg + + ;; Search for the prefix until a match is found at the start + ;; of a comment. + (while (when (re-search-forward prefix limit t) + (setq comment-beg (match-beginning 0)) + (or (not (c-got-face-at comment-beg + c-literal-faces)) + (and (/= comment-beg (point-min)) + (c-got-face-at (1- comment-beg) + c-literal-faces)))) + (setq comment-beg nil)) + (setq region-beg comment-beg)) + + (if (eq (elt (parse-partial-sexp comment-beg (+ comment-beg 2)) 7) t) + ;; Collect a sequence of doc style line comments. + (progn + (goto-char comment-beg) + (while (and (progn + (c-forward-single-comment) + (skip-syntax-forward " ") + (< (point) limit)) + (looking-at prefix)))) + (goto-char comment-beg) + (c-forward-single-comment)) + (if (> (point) limit) (goto-char limit)) + (setq comment-beg nil) + + (let ((region-end (point)) + (keylist keywords) keyword matcher highlights) + (c-put-font-lock-face region-beg region-end c-doc-face-name) + (save-restriction + ;; Narrow to the doc comment. Among other things, this + ;; helps by making "^" match at the start of the comment. + ;; Do not include a trailing block comment ender, though. + (and (> region-end (1+ region-beg)) + (progn (goto-char region-end) + (backward-char 2) + (looking-at "\\*/")) + (setq region-end (point))) + (narrow-to-region region-beg region-end) + + (while keylist + (setq keyword (car keylist) + keylist (cdr keylist) + matcher (car keyword)) + (goto-char region-beg) + (while (if (stringp matcher) + (re-search-forward matcher region-end t) + (funcall matcher region-end)) + (setq highlights (cdr keyword)) + (if (consp (car highlights)) + (while highlights + (font-lock-apply-highlight (car highlights)) + (setq highlights (cdr highlights))) + (font-lock-apply-highlight highlights)))) + + (goto-char region-end))))) + nil) +(put 'c-font-lock-doc-comments 'lisp-indent-function 2) + +(defun c-find-invalid-doc-markup (regexp limit) + ;; Used to fontify invalid markup in doc comments after the correct + ;; ones have been fontified: Find the first occurence of REGEXP + ;; between the point and LIMIT that only is fontified with + ;; `c-doc-face-name'. If a match is found then submatch 0 surrounds + ;; the first char and t is returned, otherwise nil is returned. + ;; + ;; This function might do hidden buffer changes. + (let (start) + (while (if (re-search-forward regexp limit t) + (not (eq (get-text-property + (setq start (match-beginning 0)) 'face) + c-doc-face-name)) + (setq start nil))) + (when start + (store-match-data (list (copy-marker start) + (copy-marker (1+ start)))) + t))) + +;; GtkDoc patterns contributed by Masatake YAMATO . + +(defconst gtkdoc-font-lock-doc-comments + (let ((symbol "[a-zA-Z0-9_]+") + (header "^ \\* ")) + `((,(concat header "\\(" symbol "\\):[ \t]*$") + 1 ,c-doc-markup-face-name prepend nil) + (,(concat symbol "()") + 0 ,c-doc-markup-face-name prepend nil) + (,(concat header "\\(" "@" symbol "\\):") + 1 ,c-doc-markup-face-name prepend nil) + (,(concat "[#%]" symbol) + 0 ,c-doc-markup-face-name prepend nil)) + )) + +(defconst gtkdoc-font-lock-doc-protection + `(("< \\(public\\|private\\|protected\\) >" + 1 ,c-doc-markup-face-name prepend nil))) + +(defconst gtkdoc-font-lock-keywords + `((,(lambda (limit) + (c-font-lock-doc-comments "/\\*\\*$" limit + gtkdoc-font-lock-doc-comments) + (c-font-lock-doc-comments "/\\*< " limit + gtkdoc-font-lock-doc-protection) + )))) + +;; Javadoc. + +(defconst javadoc-font-lock-doc-comments + `(("{@[a-z]+[^}\n\r]*}" ; "{@foo ...}" markup. + 0 ,c-doc-markup-face-name prepend nil) + ("^\\(/\\*\\)?\\(\\s \\|\\*\\)*\\(@[a-z]+\\)" ; "@foo ..." markup. + 3 ,c-doc-markup-face-name prepend nil) + (,(concat "") + 0 ,c-doc-markup-face-name prepend nil) + ("&\\(\\sw\\|[.:]\\)+;" ; HTML entities. + 0 ,c-doc-markup-face-name prepend nil) + ;; Fontify remaining markup characters as invalid. Note + ;; that the Javadoc spec is hazy about when "@" is + ;; allowed in non-markup use. + (,(lambda (limit) + (c-find-invalid-doc-markup "[<>&]\\|{@" limit)) + 0 'font-lock-warning-face prepend nil))) + +(defconst javadoc-font-lock-keywords + `((,(lambda (limit) + (c-font-lock-doc-comments "/\\*\\*" limit + javadoc-font-lock-doc-comments))))) + +;; Pike autodoc. + +(defconst autodoc-decl-keywords + ;; Adorned regexp matching the keywords that introduce declarations + ;; in Pike Autodoc. + (cc-eval-when-compile + (c-make-keywords-re t '("@decl" "@elem" "@index" "@member") 'pike-mode))) + +(defconst autodoc-decl-type-keywords + ;; Adorned regexp matching the keywords that are followed by a type. + (cc-eval-when-compile + (c-make-keywords-re t '("@elem" "@member") 'pike-mode))) + +(defun autodoc-font-lock-line-markup (limit) + ;; Fontify all line oriented keywords between the point and LIMIT. + ;; Nil is always returned. + ;; + ;; This function might do hidden buffer changes. + + (let ((line-re (concat "^\\(\\(/\\*!\\|\\s *\\(" + c-current-comment-prefix + "\\)\\)\\s *\\)@[A-Za-z_-]+\\(\\s \\|$\\)")) + (markup-faces (list c-doc-markup-face-name c-doc-face-name))) + + (while (re-search-forward line-re limit t) + (goto-char (match-end 1)) + + (if (looking-at autodoc-decl-keywords) + (let* ((kwd-pos (point)) + (start (match-end 1)) + (pos start) + end) + + (c-put-font-lock-face (point) pos markup-faces) + + ;; Put a declaration end mark at the markup keyword and + ;; remove the faces from the rest of the line so that it + ;; gets refontified as a declaration later on by + ;; `c-font-lock-declarations'. + (c-put-char-property (1- pos) 'c-type 'c-decl-end) + (goto-char pos) + (while (progn + (end-of-line) + (setq end (point)) + (and (eq (char-before) ?@) + (not (eobp)) + (progn (forward-char) + (skip-syntax-forward " ") + (looking-at c-current-comment-prefix)))) + (goto-char (match-end 0)) + (c-remove-font-lock-face pos (1- end)) + (c-put-font-lock-face (1- end) end markup-faces) + (setq pos (point))) + + ;; Include the final newline in the removed area. This + ;; has no visual effect but it avoids some tricky special + ;; cases in the testsuite wrt the differences in string + ;; fontification in Emacs vs XEmacs. + (c-remove-font-lock-face pos (min (1+ (point)) (point-max))) + + ;; Must handle string literals explicitly inside the declaration. + (goto-char start) + (while (re-search-forward + "\"\\([^\\\"]\\|\\\\.\\)*\"\\|'\\([^\\']\\|\\\\.\\)*'" + end 'move) + (c-put-font-lock-string-face (match-beginning 0) + (point))) + + ;; Fontify types after keywords that always are followed + ;; by them. + (goto-char kwd-pos) + (when (looking-at autodoc-decl-type-keywords) + (c-fontify-types-and-refs ((c-promote-possible-types t)) + (goto-char start) + (c-forward-syntactic-ws) + (c-forward-type)))) + + ;; Mark each whole line as markup, as long as the logical line + ;; continues. + (while (progn + (c-put-font-lock-face (point) + (progn (end-of-line) (point)) + markup-faces) + (and (eq (char-before) ?@) + (not (eobp)) + (progn (forward-char) + (skip-syntax-forward " ") + (looking-at c-current-comment-prefix)))) + (goto-char (match-end 0)))))) + + nil) + +(defconst autodoc-font-lock-doc-comments + `(("@\\(\\w+{\\|\\[\\([^\]@\n\r]\\|@@\\)*\\]\\|[@}]\\|$\\)" + ;; In-text markup. + 0 ,c-doc-markup-face-name prepend nil) + (autodoc-font-lock-line-markup) + ;; Fontify remaining markup characters as invalid. + (,(lambda (limit) + (c-find-invalid-doc-markup "@" limit)) + 0 'font-lock-warning-face prepend nil) + )) + +(defun autodoc-font-lock-keywords () + ;; Note that we depend on that `c-current-comment-prefix' has got + ;; its proper value here. + ;; + ;; This function might do hidden buffer changes. + + ;; The `c-type' text property with `c-decl-end' is used to mark the + ;; end of the `autodoc-decl-keywords' occurrences to fontify the + ;; following declarations. + (setq c-type-decl-end-used t) + + `((,(lambda (limit) + (c-font-lock-doc-comments "/[*/]!" limit + autodoc-font-lock-doc-comments))))) + + +;; 2006-07-10: awk-font-lock-keywords has been moved back to cc-awk.el. +(cc-provide 'cc-fonts) + +;;; arch-tag: 2f65f405-735f-4da5-8d4b-b957844c5203 +;;; cc-fonts.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-guess.el b/site-lisp/cc-mode/5.32.3/cc-guess.el new file mode 100644 index 0000000..ca517a1 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-guess.el @@ -0,0 +1,578 @@ +;;; cc-guess.el --- guess indentation values by scanning existing code + +;; Copyright (C) 1985,1987,1992-2003, 2004, 2005, 2006, 2007, 2008, +;; 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Author: 1994-1995 Barry A. Warsaw +;; 2011- Masatake YAMATO +;; Maintainer: bug-cc-mode@gnu.org +;; Created: August 1994, split from cc-mode.el +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU EMACS 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; see the file COPYING. If not, see +;; . + +;;; Commentary: +;; +;; This file contains routines that help guess the cc-mode style in a +;; particular region/buffer. Here style means `c-offsets-alist' and +;; `c-basic-offset'. +;; +;; The main entry point of this program is `c-guess' command but there +;; are some variants. +;; +;; Suppose the major mode for the current buffer is one of the modes +;; provided by cc-mode. `c-guess' guesses the indentation style by +;; examining the indentation in the region between beginning of buffer +;; and `c-guess-region-max'. + +;; and installs the guessed style. The name for installed style is given +;; by `c-guess-style-name'. +;; +;; `c-guess-buffer' does the same but in the whole buffer. +;; `c-guess-region' does the same but in the region between the point +;; and the mark. `c-guess-no-install', `c-guess-buffer-no-install' +;; and `c-guess-region-no-install' guess the indentation style but +;; don't install it. You can review a guessed style with `c-guess-view'. +;; After reviewing, use `c-guess-install' to install the style +;; if you prefer it. +;; +;; If you want to reuse the guessed style in another buffer, +;; run `c-set-style' command with the name of the guessed style: +;; "*c-guess*:". +;; Once the guessed style is installed explicitly with `c-guess-install' +;; or implicitly with `c-guess', `c-guess-buffer', or `c-guess-region', +;; a style name is given by `c-guess-style-name' with the above form. +;; +;; If you want to reuse the guessed style in future emacs sessions, +;; you may want to put it to your .emacs. `c-guess-view' is for +;; you. It emits emacs lisp code which defines the last guessed +;; style, in a temporary buffer. You can put the emitted code into +;; your .emacs. This command was suggested by Alan Mackenzie. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-engine) +(cc-require 'cc-styles) +(cc-bytecomp-defvar make-progress-reporter) +(cc-bytecomp-defvar progress-reporter-update) +(cc-bytecomp-defvar progress-reporter-done) + + + +(defcustom c-guess-offset-threshold 10 + "Threshold of acceptable offsets when examining indent information. +Discard an examined offset if its absolute value is greater than this. + +The offset of a line included in the indent information returned by +`c-guess-basic-syntax'." + :type 'integer + :group 'c) + +(defcustom c-guess-region-max 50000 + "The maximum region size for examining indent information with `c-guess'. +It takes a long time to examine indent information from a large region; +this option helps you limit that time. `nil' means no limit." + :type 'integer + :group 'c) + + +;;;###autoload +(defvar c-guess-guessed-offsets-alist nil + "Currently guessed offsets-alist.") +;;;###autoload +(defvar c-guess-guessed-basic-offset nil + "Currently guessed basic-offset.") + +(defvar c-guess-accumulator nil) +;; Accumulated examined indent information. Information is represented +;; in a list. Each element in it has following structure: +;; +;; (syntactic-symbol ((indentation-offset1 . number-of-times1) +;; (indentation-offset2 . number-of-times2) +;; ...)) +;; +;; This structure is built by `c-guess-accumulate-offset'. +;; +;; Here we call the pair (indentation-offset1 . number-of-times1) a +;; counter. `c-guess-sort-accumulator' sorts the order of +;; counters by number-of-times. +;; Use `c-guess-dump-accumulator' to see the value. + +(defconst c-guess-conversions + '((c . c-lineup-C-comments) + (inher-cont . c-lineup-multi-inher) + (string . -1000) + (comment-intro . c-lineup-comment) + (arglist-cont-nonempty . c-lineup-arglist) + (arglist-close . c-lineup-close-paren) + (cpp-macro . -1000))) + + +;;;###autoload +(defun c-guess (&optional accumulate) + "Guess the style in the region up to `c-guess-region-max', and install it. + +The style is given a name based on the file's absolute file name. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch." + (interactive "P") + (c-guess-region (point-min) + (min (point-max) (or c-guess-region-max + (point-max))) + accumulate)) + +;;;###autoload +(defun c-guess-no-install (&optional accumulate) + "Guess the style in the region up to `c-guess-region-max'; don't install it. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch." + (interactive "P") + (c-guess-region-no-install (point-min) + (min (point-max) (or c-guess-region-max + (point-max))) + accumulate)) + +;;;###autoload +(defun c-guess-buffer (&optional accumulate) + "Guess the style on the whole current buffer, and install it. + +The style is given a name based on the file's absolute file name. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch." + (interactive "P") + (c-guess-region (point-min) + (point-max) + accumulate)) + +;;;###autoload +(defun c-guess-buffer-no-install (&optional accumulate) + "Guess the style on the whole current buffer; don't install it. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch." + (interactive "P") + (c-guess-region-no-install (point-min) + (point-max) + accumulate)) + +;;;###autoload +(defun c-guess-region (start end &optional accumulate) + "Guess the style on the region and install it. + +The style is given a name based on the file's absolute file name. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous guess is extended, otherwise a new guess is +made from scratch." + (interactive "r\nP") + (c-guess-region-no-install start end accumulate) + (c-guess-install)) + + +(defsubst c-guess-empty-line-p () + (eq (line-beginning-position) + (line-end-position))) + +;;;###autoload +(defun c-guess-region-no-install (start end &optional accumulate) + "Guess the style on the region; don't install it. + +Every line of code in the region is examined and values for the following two +variables are guessed: + +* `c-basic-offset', and +* the indentation values of the various syntactic symbols in + `c-offsets-alist'. + +The guessed values are put into `c-guess-guessed-basic-offset' and +`c-guess-guessed-offsets-alist'. + +Frequencies of use are taken into account when guessing, so minor +inconsistencies in the indentation style shouldn't produce wrong guesses. + +If given a prefix argument (or if the optional argument ACCUMULATE is +non-nil) then the previous examination is extended, otherwise a new +guess is made from scratch. + +Note that the larger the region to guess in, the slower the guessing. +So you can limit the region with `c-guess-region-max'." + (interactive "r\nP") + (let ((accumulator (when accumulate c-guess-accumulator))) + (setq c-guess-accumulator (c-guess-examine start end accumulator)) + (let ((pair (c-guess-guess c-guess-accumulator))) + (setq c-guess-guessed-basic-offset (car pair) + c-guess-guessed-offsets-alist (cdr pair))))) + + +(defun c-guess-examine (start end accumulator) + (let ((reporter (when (fboundp 'make-progress-reporter) + (make-progress-reporter "Examining Indentation " + start + end)))) + (save-excursion + (goto-char start) + (while (< (point) end) + (unless (c-guess-empty-line-p) + (mapc (lambda (s) + (setq accumulator (or (c-guess-accumulate accumulator s) + accumulator))) + (c-save-buffer-state () (c-guess-basic-syntax)))) + (when reporter (progress-reporter-update reporter (point))) + (forward-line 1))) + (when reporter (progress-reporter-done reporter))) + (c-guess-sort-accumulator accumulator)) + +(defun c-guess-guess (accumulator) + ;; Guess basic-offset and offsets-alist from ACCUMULATOR, + ;; then return them as a cons: (basic-offset . offsets-alist). + ;; See the comments at `c-guess-accumulator' about the format + ;; ACCUMULATOR. + (let* ((basic-offset (c-guess-make-basic-offset accumulator)) + (typical-offsets-alist (c-guess-make-offsets-alist + accumulator)) + (symbolic-offsets-alist (c-guess-symbolize-offsets-alist + typical-offsets-alist + basic-offset)) + (merged-offsets-alist (c-guess-merge-offsets-alists + (copy-tree c-guess-conversions) + symbolic-offsets-alist))) + (cons basic-offset merged-offsets-alist))) + +(defun c-guess-current-offset (relpos) + ;; Calculate relative indentation (point) to RELPOS. + (- (progn (back-to-indentation) + (current-column)) + (save-excursion + (goto-char relpos) + (current-column)))) + +(defun c-guess-accumulate (accumulator syntax-element) + ;; Add SYNTAX-ELEMENT to ACCUMULATOR. + (let ((symbol (car syntax-element)) + (relpos (cadr syntax-element))) + (when (numberp relpos) + (let ((offset (c-guess-current-offset relpos))) + (when (< (abs offset) c-guess-offset-threshold) + (c-guess-accumulate-offset accumulator + symbol + offset)))))) + +(defun c-guess-accumulate-offset (accumulator symbol offset) + ;; Added SYMBOL and OFFSET to ACCUMULATOR. See + ;; `c-guess-accumulator' about the structure of ACCUMULATOR. + (let* ((entry (assoc symbol accumulator)) + (counters (cdr entry)) + counter) + (if entry + (progn + (setq counter (assoc offset counters)) + (if counter + (setcdr counter (1+ (cdr counter))) + (setq counters (cons (cons offset 1) counters)) + (setcdr entry counters)) + accumulator) + (cons (cons symbol (cons (cons offset 1) nil)) accumulator)))) + +(defun c-guess-sort-accumulator (accumulator) + ;; Sort each element of ACCUMULATOR by the number-of-times. See + ;; `c-guess-accumulator' for more details. + (mapcar + (lambda (entry) + (let ((symbol (car entry)) + (counters (cdr entry))) + (cons symbol (sort counters + (lambda (a b) + (if (> (cdr a) (cdr b)) + t + (and + (eq (cdr a) (cdr b)) + (< (car a) (car b))))))))) + accumulator)) + +(defun c-guess-make-offsets-alist (accumulator) + ;; Throw away the rare cases in accumulator and make an offsets-alist structure. + (mapcar + (lambda (entry) + (cons (car entry) + (car (car (cdr entry))))) + accumulator)) + +(defun c-guess-merge-offsets-alists (strong weak) + ;; Merge two offsets-alists into one. + ;; When two offsets-alists have the same symbol + ;; entry, give STRONG priority over WEAK. + (mapc + (lambda (weak-elt) + (unless (assoc (car weak-elt) strong) + (setq strong (cons weak-elt strong)))) + weak) + strong) + +(defun c-guess-make-basic-offset (accumulator) + ;; As candidate for `c-basic-offset', find the most frequently appearing + ;; indentation-offset in ACCUMULATOR. + (let* (;; Drop the value related to `c' syntactic-symbol. + ;; (`c': Inside a multiline C style block comment.) + ;; The impact for values of `c' is too large for guessing + ;; `basic-offset' if the target source file is small and its license + ;; notice is at top of the file. + (accumulator (assq-delete-all 'c (copy-tree accumulator))) + ;; Drop syntactic-symbols from ACCUMULATOR. + (alist (apply #'append (mapcar (lambda (elts) + (mapcar (lambda (elt) + (cons (abs (car elt)) + (cdr elt))) + (cdr elts))) + accumulator))) + ;; Gather all indentation-offsets other than 0. + ;; 0 is meaningless as `basic-offset'. + (offset-list (delete 0 + (delete-dups (mapcar + (lambda (elt) (car elt)) + alist)))) + ;; Sum of number-of-times for offset: + ;; (offset . sum) + (summed (mapcar (lambda (offset) + (cons offset + (apply #'+ + (mapcar (lambda (a) + (if (eq (car a) offset) + (cdr a) + 0)) + alist)))) + offset-list))) + ;; + ;; Find the majority. + ;; + (let ((majority '(nil . 0))) + (while summed + (when (< (cdr majority) (cdr (car summed))) + (setq majority (car summed))) + (setq summed (cdr summed))) + (car majority)))) + +(defun c-guess-symbolize-offsets-alist (offsets-alist basic-offset) + ;; Convert the representation of OFFSETS-ALIST to an alist using + ;; `+', `-', `++', `--', `*', or `/'. These symbols represent + ;; a value relative to BASIC-OFFSET. Their meaning can be found + ;; in the CC Mode manual. + (mapcar + (lambda (elt) + (let ((s (car elt)) + (v (cdr elt))) + (cond + ((integerp v) + (cons s (c-guess-symbolize-integer v + basic-offset))) + (t elt)))) + offsets-alist)) + +(defun c-guess-symbolize-integer (int basic-offset) + (let ((aint (abs int))) + (cond + ((eq int basic-offset) '+) + ((eq aint basic-offset) '-) + ((eq int (* 2 basic-offset)) '++) + ((eq aint (* 2 basic-offset)) '--) + ((eq (* 2 int) basic-offset) '*) + ((eq (* 2 aint) basic-offset) '-) + (t int)))) + +(defun c-guess-style-name () + ;; Make a style name for the guessed style. + (format "*c-guess*:%s" (buffer-file-name))) + +(defun c-guess-make-style (basic-offset offsets-alist) + (when basic-offset + ;; Make a style from guessed values. + (let* ((offsets-alist (c-guess-merge-offsets-alists + offsets-alist + c-offsets-alist))) + `((c-basic-offset . ,basic-offset) + (c-offsets-alist . ,offsets-alist))))) + +;;;###autoload +(defun c-guess-install (&optional style-name) + "Install the latest guessed style into the current buffer. +\(This guessed style is a combination of `c-guess-guessed-basic-offset', +`c-guess-guessed-offsets-alist' and `c-offsets-alist'.) + +The style is entered into CC Mode's style system by +`c-add-style'. Its name is either STYLE-NAME, or a name based on +the absolute file name of the file if STYLE-NAME is nil." + (interactive "sNew style name (empty for default name): ") + (let* ((style (c-guess-make-style c-guess-guessed-basic-offset + c-guess-guessed-offsets-alist))) + (if style + (let ((style-name (or (if (equal style-name "") + nil + style-name) + (c-guess-style-name)))) + (c-add-style style-name style t) + (message "Style \"%s\" is installed" style-name)) + (error "Not yet guessed")))) + +(defun c-guess-dump-accumulator () + "Show `c-guess-accumulator'." + (interactive) + (with-output-to-temp-buffer "*Accumulated Examined Indent Information*" + (pp c-guess-accumulator))) + +(defun c-guess-reset-accumulator () + "Reset `c-guess-accumulator'." + (interactive) + (setq c-guess-accumulator nil)) + +(defun c-guess-dump-guessed-values () + "Show `c-guess-guessed-basic-offset' and `c-guess-guessed-offsets-alist'." + (interactive) + (with-output-to-temp-buffer "*Guessed Values*" + (princ "basic-offset: \n\t") + (pp c-guess-guessed-basic-offset) + (princ "\n\n") + (princ "offsets-alist: \n") + (pp c-guess-guessed-offsets-alist) + )) + +(defun c-guess-dump-guessed-style (&optional printer) + "Show the guessed style. +`pp' is used to print the style but if PRINTER is given, +PRINTER is used instead. If PRINTER is not `nil', it +is called with one argument, the guessed style." + (interactive) + (let ((style (c-guess-make-style c-guess-guessed-basic-offset + c-guess-guessed-offsets-alist))) + (if style + (with-output-to-temp-buffer "*Guessed Style*" + (funcall (if printer printer 'pp) style)) + (error "Not yet guessed")))) + +(defun c-guess-guessed-syntactic-symbols () + ;; Return syntactic symbols in c-guess-guessed-offsets-alist + ;; but not in c-guess-conversions. + (let ((alist c-guess-guessed-offsets-alist) + elt + (symbols nil)) + (while alist + (setq elt (car alist) + alist (cdr alist)) + (unless (assq (car elt) c-guess-conversions) + (setq symbols (cons (car elt) + symbols)))) + symbols)) + +(defun c-guess-view-reorder-offsets-alist-in-style (style guessed-syntactic-symbols) + ;; Reorder the `c-offsets-alist' field of STYLE. + ;; If an entry in `c-offsets-alist' holds a guessed value, move it to + ;; front in the field. In addition alphabetical sort by entry name is done. + (setq style (copy-tree style)) + (let ((offsets-alist-cell (assq 'c-offsets-alist style)) + (guessed-syntactic-symbols (c-guess-guessed-syntactic-symbols))) + (setcdr offsets-alist-cell + (sort (cdr offsets-alist-cell) + (lambda (a b) + (let ((a-guessed? (memq (car a) guessed-syntactic-symbols)) + (b-guessed? (memq (car b) guessed-syntactic-symbols))) + (cond + ((or (and a-guessed? b-guessed?) + (not (or a-guessed? b-guessed?))) + (string-lessp (symbol-name (car a)) + (symbol-name (car b)))) + (a-guessed? t) + (b-guessed? nil))))))) + style) + +(defun c-guess-view-mark-guessed-entries (guessed-syntactic-symbols) + ;; Put " ; Guess value" markers on all entries which hold + ;; guessed values. + ;; `c-basic-offset' is always considered as holding a guessed value. + (let ((needs-markers (cons 'c-basic-offset + guessed-syntactic-symbols))) + (while needs-markers + (goto-char (point-min)) + (when (search-forward (concat "(" + (symbol-name (car needs-markers)) + " ") nil t) + (move-end-of-line 1) + (comment-dwim nil) + (insert " Guessed value")) + (setq needs-markers + (cdr needs-markers))))) + +(defun c-guess-view (&optional with-name) + "Emit emacs lisp code which defines the last guessed style. +So you can put the code into .emacs if you prefer the +guessed code. +\"STYLE NAME HERE\" is used as the name for the style in the +emitted code. If WITH-NAME is given, it is used instead. +WITH-NAME is expected as a string but if this function +called interactively with prefix argument, the value for +WITH-NAME is asked to the user." + (interactive "P") + (let* ((temporary-style-name (cond + ((stringp with-name) with-name) + (with-name (read-from-minibuffer + "New style name: ")) + (t + "STYLE NAME HERE"))) + (guessed-style-name (c-guess-style-name)) + (current-style-name c-indentation-style) + (parent-style-name (if (string-equal guessed-style-name + current-style-name) + ;; The guessed style is already installed. + ;; It cannot be used as the parent style. + ;; Use the default style for the current + ;; major mode as the parent style. + (cc-choose-style-for-mode + major-mode + c-default-style) + ;; The guessed style is not installed yet. + current-style-name))) + (c-guess-dump-guessed-style + (lambda (style) + (let ((guessed-syntactic-symbols (c-guess-guessed-syntactic-symbols))) + (pp `(c-add-style ,temporary-style-name + ',(cons parent-style-name + (c-guess-view-reorder-offsets-alist-in-style + style + guessed-syntactic-symbols)))) + (with-current-buffer standard-output + (lisp-interaction-mode) + (c-guess-view-mark-guessed-entries + guessed-syntactic-symbols) + (buffer-enable-undo))))))) + + +(cc-provide 'cc-guess) +;;; cc-guess.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-langs.el b/site-lisp/cc-mode/5.32.3/cc-langs.el new file mode 100644 index 0000000..37412c4 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-langs.el @@ -0,0 +1,3234 @@ +;;; cc-langs.el --- language specific settings for CC Mode + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2002- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 22-Apr-1997 (split from cc-mode.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; HACKERS NOTE: There's heavy macro magic here. If you need to make +;; changes in this or other files containing `c-lang-defconst' but +;; don't want to read through the longer discussion below then read +;; this: +;; +;; o A change in a `c-lang-defconst' or `c-lang-defvar' will not take +;; effect if the file containing the mode init function (typically +;; cc-mode.el) is byte compiled. +;; o To make changes show in font locking you need to reevaluate the +;; `*-font-lock-keywords-*' constants, which normally is easiest to +;; do with M-x eval-buffer in cc-fonts.el. +;; o In either case it's necessary to reinitialize the mode to make +;; the changes show in an existing buffer. + +;;; Introduction to the language dependent variable system: +;; +;; This file contains all the language dependent variables, except +;; those specific for font locking which reside in cc-fonts.el. As +;; far as possible, all the differences between the languages that CC +;; Mode supports are described with these variables only, so that the +;; code can be shared. +;; +;; The language constant system (see cc-defs.el) is used to specify +;; various language dependent info at a high level, such as lists of +;; keywords, and then from them generate - at compile time - the +;; various regexps and other low-level structures actually employed in +;; the code at runtime. +;; +;; This system is also designed to make it easy for developers of +;; derived modes to customize the source constants for new language +;; variants, without having to keep up with the exact regexps etc that +;; are used in each CC Mode version. It's possible from an external +;; package to add a new language by inheriting an existing one, and +;; then change specific constants as necessary for the new language. +;; The old values for those constants (and the values of all the other +;; high-level constants) may be used to build the new ones, and those +;; new values will in turn be used by the low-level definitions here +;; to build the runtime constants appropriately for the new language +;; in the current version of CC Mode. +;; +;; Like elsewhere in CC Mode, the existence of a doc string signifies +;; that a language constant is part of the external API, and that it +;; therefore can be used with a high confidence that it will continue +;; to work with future versions of CC Mode. Even so, it's not +;; unlikely that such constants will change meaning slightly as this +;; system is refined further; a certain degree of dependence on the CC +;; Mode version is unavoidable when hooking in at this level. Also +;; note that there's still work to be done to actually use these +;; constants everywhere inside CC Mode; there are still hardcoded +;; values in many places in the code. +;; +;; Separate packages will also benefit from the compile time +;; evaluation; the byte compiled file(s) for them will contain the +;; compiled runtime constants ready for use by (the byte compiled) CC +;; Mode, and the source definitions in this file don't have to be +;; loaded then. However, if a byte compiled package is loaded that +;; has been compiled with a different version of CC Mode than the one +;; currently loaded, then the compiled-in values will be discarded and +;; new ones will be built when the mode is initialized. That will +;; automatically trig a load of the file(s) containing the source +;; definitions (i.e. this file and/or cc-fonts.el) if necessary. +;; +;; A small example of a derived mode is available at +;; . It also +;; contains some useful hints for derived mode developers. + +;;; Using language variables: +;; +;; The `c-lang-defvar' forms in this file comprise the language +;; variables that CC Mode uses. It does not work to use +;; `c-lang-defvar' anywhere else (which isn't much of a limitation +;; since these variables sole purpose is to interface with the CC Mode +;; core functions). The values in these `c-lang-defvar's are not +;; evaluated right away but instead collected to a single large `setq' +;; that can be inserted for a particular language with the +;; `c-init-language-vars' macro. + +;; This file is only required at compile time, or when not running +;; from byte compiled files, or when the source definitions for the +;; language constants are requested. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) + + +;; This file is not always loaded. See note above. +(cc-external-require 'cl) + + +;;; Setup for the `c-lang-defvar' system. + +(eval-and-compile + ;; These are used to collect the init forms from the subsequent + ;; `c-lang-defvar' and `c-lang-setvar'. They are used to build the + ;; lambda in `c-make-init-lang-vars-fun' below, and to build `defvar's + ;; and `make-variable-buffer-local's in cc-engine and + ;; `make-local-variable's in `c-init-language-vars-for'. + (defvar c-lang-variable-inits nil) + (defvar c-lang-variable-inits-tail nil) + (setq c-lang-variable-inits (list nil) + c-lang-variable-inits-tail c-lang-variable-inits) + (defvar c-emacs-variable-inits nil) + (defvar c-emacs-variable-inits-tail nil) + (setq c-emacs-variable-inits (list nil) + c-emacs-variable-inits-tail c-emacs-variable-inits)) + +(defmacro c-lang-defvar (var val &optional doc) + "Declares the buffer local variable VAR to get the value VAL. VAL is +evaluated and assigned at mode initialization. More precisely, VAL is +evaluated and bound to VAR when the result from the macro +`c-init-language-vars' is evaluated. + +`c-lang-const' is typically used in VAL to get the right value for the +language being initialized, and such calls will be macro expanded to +the evaluated constant value at compile time." + + (when (and (not doc) + (eq (car-safe val) 'c-lang-const) + (eq (nth 1 val) var) + (not (nth 2 val))) + ;; Special case: If there's no docstring and the value is a + ;; simple (c-lang-const foo) where foo is the same name as VAR + ;; then take the docstring from the language constant foo. + (setq doc (get (intern (symbol-name (nth 1 val)) c-lang-constants) + 'variable-documentation))) + (or (stringp doc) + (setq doc nil)) + + (let ((elem (assq var (cdr c-lang-variable-inits)))) + (if elem + (setcdr elem (list val doc)) + (setcdr c-lang-variable-inits-tail (list (list var val doc))) + (setq c-lang-variable-inits-tail (cdr c-lang-variable-inits-tail)))) + + ;; Return the symbol, like the other def* forms. + `',var) + +(defmacro c-lang-setvar (var val) + "Causes the variable VAR to be made buffer local and to get set to the +value VAL. VAL is evaluated and assigned at mode initialization. More +precisely, VAL is evaluated and bound to VAR when the result from the +macro `c-init-language-vars' is evaluated. VAR is typically a standard +Emacs variable like `comment-start'. + +`c-lang-const' is typically used in VAL to get the right value for the +language being initialized, and such calls will be macro expanded to +the evaluated constant value at compile time." + (let ((elem (assq var (cdr c-emacs-variable-inits)))) + (if elem + (setcdr elem (list val)) ; Maybe remove "list", sometime. 2006-07-19 + (setcdr c-emacs-variable-inits-tail (list (list var val))) + (setq c-emacs-variable-inits-tail (cdr c-emacs-variable-inits-tail)))) + + ;; Return the symbol, like the other def* forms. + `',var) + +(put 'c-lang-defvar 'lisp-indent-function 'defun) +(eval-after-load "edebug" + '(def-edebug-spec c-lang-defvar + (&define name def-form &optional stringp))) + +(eval-and-compile + ;; Some helper functions used when building the language constants. + + (defun c-filter-ops (ops opgroup-filter op-filter &optional xlate) + ;; Extract a subset of the operators in the list OPS in a DWIM:ey + ;; way. The return value is a plain list of operators: + ;; + ;; OPS either has the structure of `c-operators', is a single + ;; group in `c-operators', or is a plain list of operators. + ;; + ;; OPGROUP-FILTER specifies how to select the operator groups. It + ;; can be t to choose all groups, a list of group type symbols + ;; (such as 'prefix) to accept, or a function which will be called + ;; with the group symbol for each group and should return non-nil + ;; if that group is to be included. + ;; + ;; If XLATE is given, it's a function which is called for each + ;; matching operator and its return value is collected instead. + ;; If it returns a list, the elements are spliced directly into + ;; the final result, which is returned as a list with duplicates + ;; removed using `equal'. + ;; + ;; `c-mode-syntax-table' for the current mode is in effect during + ;; the whole procedure. + (unless (listp (car-safe ops)) + (setq ops (list ops))) + (cond ((eq opgroup-filter t) + (setq opgroup-filter (lambda (opgroup) t))) + ((not (functionp opgroup-filter)) + (setq opgroup-filter `(lambda (opgroup) + (memq opgroup ',opgroup-filter))))) + (cond ((eq op-filter t) + (setq op-filter (lambda (op) t))) + ((stringp op-filter) + (setq op-filter `(lambda (op) + (string-match ,op-filter op))))) + (unless xlate + (setq xlate 'identity)) + (c-with-syntax-table (c-lang-const c-mode-syntax-table) + (delete-duplicates + (mapcan (lambda (opgroup) + (when (if (symbolp (car opgroup)) + (when (funcall opgroup-filter (car opgroup)) + (setq opgroup (cdr opgroup)) + t) + t) + (mapcan (lambda (op) + (when (funcall op-filter op) + (let ((res (funcall xlate op))) + (if (listp res) res (list res))))) + opgroup))) + ops) + :test 'equal)))) + + +;;; Various mode specific values that aren't language related. + +(c-lang-defconst c-mode-menu + ;; The definition for the mode menu. The menu title is prepended to + ;; this before it's fed to `easy-menu-define'. + t `(["Comment Out Region" comment-region + (c-fn-region-is-active-p)] + ["Uncomment Region" (comment-region (region-beginning) + (region-end) '(4)) + (c-fn-region-is-active-p)] + ["Indent Expression" c-indent-exp + (memq (char-after) '(?\( ?\[ ?\{))] + ["Indent Line or Region" c-indent-line-or-region t] + ["Fill Comment Paragraph" c-fill-paragraph t] + "----" + ["Backward Statement" c-beginning-of-statement t] + ["Forward Statement" c-end-of-statement t] + ,@(when (c-lang-const c-opt-cpp-prefix) + ;; Only applicable if there's a cpp preprocessor. + `(["Up Conditional" c-up-conditional t] + ["Backward Conditional" c-backward-conditional t] + ["Forward Conditional" c-forward-conditional t] + "----" + ["Macro Expand Region" c-macro-expand + (c-fn-region-is-active-p)] + ["Backslashify" c-backslash-region + (c-fn-region-is-active-p)])) + "----" + ("Style..." + ["Set Style..." c-set-style t] + ["Show Current Style Name" (message + "Style Name: %s" + c-indentation-style) t] + ["Guess Style from this Buffer" c-guess-buffer-no-install t] + ["Install the Last Guessed Style" c-guess-install + (and c-guess-guessed-offsets-alist + c-guess-guessed-basic-offset) ] + ["View the Last Guessed Style" c-guess-view + (and c-guess-guessed-offsets-alist + c-guess-guessed-basic-offset) ]) + "----" + ("Toggle..." + ["Syntactic indentation" c-toggle-syntactic-indentation t] + ["Electric mode" c-toggle-electric-state t] + ["Auto newline" c-toggle-auto-newline t] + ["Hungry delete" c-toggle-hungry-state t] + ["Subword mode" c-subword-mode t]))) + + +;;; Syntax tables. + +(defun c-populate-syntax-table (table) + "Populate the given syntax table as necessary for a C-like language. +This includes setting ' and \" as string delimiters, and setting up +the comment syntax to handle both line style \"//\" and block style +\"/*\" \"*/\" comments." + + (modify-syntax-entry ?_ "_" table) + (modify-syntax-entry ?\\ "\\" table) + (modify-syntax-entry ?+ "." table) + (modify-syntax-entry ?- "." table) + (modify-syntax-entry ?= "." table) + (modify-syntax-entry ?% "." table) + (modify-syntax-entry ?< "." table) + (modify-syntax-entry ?> "." table) + (modify-syntax-entry ?& "." table) + (modify-syntax-entry ?| "." table) + (modify-syntax-entry ?\' "\"" table) + (modify-syntax-entry ?\240 "." table) + + ;; Set up block and line oriented comments. The new C + ;; standard mandates both comment styles even in C, so since + ;; all languages now require dual comments, we make this the + ;; default. + (cond + ;; XEmacs + ((memq '8-bit c-emacs-features) + (modify-syntax-entry ?/ ". 1456" table) + (modify-syntax-entry ?* ". 23" table)) + ;; Emacs + ((memq '1-bit c-emacs-features) + (modify-syntax-entry ?/ ". 124b" table) + (modify-syntax-entry ?* ". 23" table)) + ;; incompatible + (t (error "CC Mode is incompatible with this version of Emacs"))) + + (modify-syntax-entry ?\n "> b" table) + ;; Give CR the same syntax as newline, for selective-display + (modify-syntax-entry ?\^m "> b" table)) + +(c-lang-defconst c-make-mode-syntax-table + "Functions that generates the mode specific syntax tables. +The syntax tables aren't stored directly since they're quite large." + t `(lambda () + (let ((table (make-syntax-table))) + (c-populate-syntax-table table) + ;; Mode specific syntaxes. + ,(cond ((or (c-major-mode-is 'objc-mode) (c-major-mode-is 'java-mode)) + ;; Let '@' be part of symbols in ObjC to cope with + ;; its compiler directives as single keyword tokens. + ;; This is then necessary since it's assumed that + ;; every keyword is a single symbol. + `(modify-syntax-entry ?@ "_" table)) + ((c-major-mode-is 'pike-mode) + `(modify-syntax-entry ?@ "." table))) + table))) + +(c-lang-defconst c-mode-syntax-table + ;; The syntax tables in evaluated form. Only used temporarily when + ;; the constants in this file are evaluated. + t (funcall (c-lang-const c-make-mode-syntax-table))) + +(c-lang-defconst c++-make-template-syntax-table + ;; A variant of `c++-mode-syntax-table' that defines `<' and `>' as + ;; parenthesis characters. Used temporarily when template argument + ;; lists are parsed. Note that this encourages incorrect parsing of + ;; templates since they might contain normal operators that uses the + ;; '<' and '>' characters. Therefore this syntax table might go + ;; away when CC Mode handles templates correctly everywhere. + t nil + (java c++) `(lambda () + (let ((table (funcall ,(c-lang-const c-make-mode-syntax-table)))) + (modify-syntax-entry ?< "(>" table) + (modify-syntax-entry ?> ")<" table) + table))) +(c-lang-defvar c++-template-syntax-table + (and (c-lang-const c++-make-template-syntax-table) + (funcall (c-lang-const c++-make-template-syntax-table)))) + +(c-lang-defconst c-no-parens-syntax-table + ;; A variant of the standard syntax table which is used to find matching + ;; "<"s and ">"s which have been marked as parens using syntax table + ;; properties. The other paren characters (e.g. "{", ")" "]") are given a + ;; non-paren syntax here. so that the list commands will work on "< ... >" + ;; even when there's unbalanced other parens inside them. + ;; + ;; This variable is nil for languages which don't have template stuff. + t `(lambda () + (if (c-lang-const c-recognize-<>-arglists) + (let ((table (funcall ,(c-lang-const c-make-mode-syntax-table)))) + (modify-syntax-entry ?\( "." table) + (modify-syntax-entry ?\) "." table) + (modify-syntax-entry ?\[ "." table) + (modify-syntax-entry ?\] "." table) + (modify-syntax-entry ?\{ "." table) + (modify-syntax-entry ?\} "." table) + table)))) +(c-lang-defvar c-no-parens-syntax-table + (funcall (c-lang-const c-no-parens-syntax-table))) + +(c-lang-defconst c-identifier-syntax-modifications + "A list that describes the modifications that should be done to the +mode syntax table to get a syntax table that matches all identifiers +and keywords as words. + +The list is just like the one used in `font-lock-defaults': Each +element is a cons where the car is the character to modify and the cdr +the new syntax, as accepted by `modify-syntax-entry'." + ;; The $ character is not allowed in most languages (one exception + ;; is Java which allows it for legacy reasons) but we still classify + ;; it as an indentifier character since it's often used in various + ;; machine generated identifiers. + t '((?_ . "w") (?$ . "w")) + (objc java) (append '((?@ . "w")) + (c-lang-const c-identifier-syntax-modifications)) + awk '((?_ . "w"))) +(c-lang-defvar c-identifier-syntax-modifications + (c-lang-const c-identifier-syntax-modifications)) + +(c-lang-defvar c-identifier-syntax-table + (let ((table (copy-syntax-table (c-mode-var "mode-syntax-table"))) + (mods c-identifier-syntax-modifications) + mod) + (while mods + (setq mod (car mods) + mods (cdr mods)) + (modify-syntax-entry (car mod) (cdr mod) table)) + table) + "Syntax table built on the mode syntax table but additionally +classifies symbol constituents like '_' and '$' as word constituents, +so that all identifiers are recognized as words.") + +(c-lang-defconst c-get-state-before-change-functions + ;; For documentation see the following c-lang-defvar of the same name. + ;; The value here may be a list of functions or a single function. + t nil + c++ '(c-extend-region-for-CPP + c-before-change-check-<>-operators + c-invalidate-macro-cache) + (c objc) '(c-extend-region-for-CPP c-invalidate-macro-cache) + ;; java 'c-before-change-check-<>-operators + awk 'c-awk-record-region-clear-NL) +(c-lang-defvar c-get-state-before-change-functions + (let ((fs (c-lang-const c-get-state-before-change-functions))) + (if (listp fs) + fs + (list fs))) + "If non-nil, a list of functions called from c-before-change-hook. +Typically these will record enough state to allow +`c-before-font-lock-function' to extend the region to fontify, +and may do such things as removing text-properties which must be +recalculated. + +These functions will be run in the order given. Each of them +takes 2 parameters, the BEG and END supplied to every +before-change function; on entry, the buffer will have been +widened and match-data will have been saved; point is undefined +on both entry and exit; the return value is ignored. + +The functions are called even when font locking isn't enabled. + +When the mode is initialized, the functions are called with +parameters \(point-min) and \(point-max).") + +(c-lang-defconst c-before-font-lock-functions + ;; For documentation see the following c-lang-defvar of the same name. + ;; The value here may be a list of functions or a single function. + t 'c-change-set-fl-decl-start + (c c++ objc) '(c-neutralize-syntax-in-and-mark-CPP + c-change-set-fl-decl-start) + awk 'c-awk-extend-and-syntax-tablify-region) +(c-lang-defvar c-before-font-lock-functions + (let ((fs (c-lang-const c-before-font-lock-functions))) + (if (listp fs) + fs + (list fs))) + "If non-nil, a list of functions called just before font locking. +Typically they will extend the region about to be fontified \(see +below) and will set `syntax-table' text properties on the region. + +These functions will be run in the order given. Each of them +takes 3 parameters, the BEG, END, and OLD-LEN supplied to every +after-change function; point is undefined on both entry and exit; +on entry, the buffer will have been widened and match-data will +have been saved; the return value is ignored. + +The functions may extend the region to be fontified by setting the +buffer local variables c-new-BEG and c-new-END. + +The functions are called even when font locking is disabled. + +When the mode is initialized, these functions are called with +parameters \(point-min), \(point-max) and .") + +(c-lang-defconst c-before-context-fontification-functions + awk nil + t 'c-context-set-fl-decl-start) + ;; For documentation see the following c-lang-defvar of the same name. + ;; The value here may be a list of functions or a single function. +(c-lang-defvar c-before-context-fontification-functions + (let ((fs (c-lang-const c-before-context-fontification-functions))) + (if (listp fs) + fs + (list fs))) + "If non-nil, a list of functions called just before context (or +other non-change) fontification is done. Typically they will +extend the region. + +These functions will be run in the order given. Each of them +takes 2 parameters, the BEG and END of the region to be +fontified. Point is undefined on both entry and exit. On entry, +the buffer will have been widened and match-data will have been +saved; the return value is a cons of the adjusted +region, (NEW-BEG . NEW-END).") + + +;;; Syntactic analysis ("virtual semicolons") for line-oriented languages (AWK). +(c-lang-defconst c-at-vsemi-p-fn + "Contains a function \"Is there a virtual semicolon at POS or point?\". +Such a function takes one optional parameter, a buffer position (defaults to +point), and returns nil or t. This variable contains nil for languages which +don't have EOL terminated statements. " + t nil + (c c++ objc) 'c-at-macro-vsemi-p + awk 'c-awk-at-vsemi-p) +(c-lang-defvar c-at-vsemi-p-fn (c-lang-const c-at-vsemi-p-fn)) + +(c-lang-defconst c-vsemi-status-unknown-p-fn + "Contains a function \"are we unsure whether there is a virtual semicolon on this line?\". +The (admittedly kludgey) purpose of such a function is to prevent an infinite +recursion in c-beginning-of-statement-1 when point starts at a `while' token. +The function MUST NOT UNDER ANY CIRCUMSTANCES call c-beginning-of-statement-1, +even indirectly. This variable contains nil for languages which don't have +EOL terminated statements." + t nil + (c c++ objc) 'c-macro-vsemi-status-unknown-p + awk 'c-awk-vsemi-status-unknown-p) +(c-lang-defvar c-vsemi-status-unknown-p-fn + (c-lang-const c-vsemi-status-unknown-p-fn)) + + +;;; Lexer-level syntax (identifiers, tokens etc). + +(c-lang-defconst c-has-bitfields + "Whether the language has bitfield declarations." + t nil + (c c++ objc) t) +(c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields)) + +(c-lang-defconst c-modified-constant + "Regexp that matches a \"modified\" constant literal such as \"L'a'\", +a \"long character\". In particular, this recognizes forms of constant +which c-backward-sexp needs to be called twice to move backwards over." + t nil + (c c++ objc) "L'\\([^\\'\t\f\n\r]\\|\\\\.\\)'") +;; FIXME!!! Extend this to cover strings, if needed. 2008-04-11 +(c-lang-defvar c-modified-constant (c-lang-const c-modified-constant)) + +(c-lang-defconst c-symbol-start + "Regexp that matches the start of a symbol, i.e. any identifier or +keyword. It's unspecified how far it matches. Does not contain a \\| +operator at the top level." + t (concat "[" c-alpha "_]") + java (concat "[" c-alpha "_@]") + objc (concat "[" c-alpha "@]") + pike (concat "[" c-alpha "_`]")) +(c-lang-defvar c-symbol-start (c-lang-const c-symbol-start)) + +(c-lang-defconst c-symbol-chars + "Set of characters that can be part of a symbol. +This is of the form that fits inside [ ] in a regexp." + ;; Pike note: With the backquote identifiers this would include most + ;; operator chars too, but they are handled with other means instead. + t (concat c-alnum "_$") + objc (concat c-alnum "_$@")) +(c-lang-defvar c-symbol-chars (c-lang-const c-symbol-chars)) + +(c-lang-defconst c-symbol-key + "Regexp matching identifiers and keywords (with submatch 0). Assumed +to match if `c-symbol-start' matches on the same position." + t (concat (c-lang-const c-symbol-start) + "[" (c-lang-const c-symbol-chars) "]*") + pike (concat + ;; Use the value from C here since the operator backquote is + ;; covered by the other alternative. + (c-lang-const c-symbol-key c) + "\\|" + (c-make-keywords-re nil + (c-lang-const c-overloadable-operators)))) +(c-lang-defvar c-symbol-key (c-lang-const c-symbol-key)) + +(c-lang-defconst c-symbol-key-depth + ;; Number of regexp grouping parens in `c-symbol-key'. + t (regexp-opt-depth (c-lang-const c-symbol-key))) + +(c-lang-defconst c-nonsymbol-chars + "This is the set of chars that can't be part of a symbol, i.e. the +negation of `c-symbol-chars'." + t (concat "^" (c-lang-const c-symbol-chars))) +(c-lang-defvar c-nonsymbol-chars (c-lang-const c-nonsymbol-chars)) + +(c-lang-defconst c-nonsymbol-key + "Regexp that matches any character that can't be part of a symbol. +It's usually appended to other regexps to avoid matching a prefix. +It's assumed to not contain any submatchers." + ;; The same thing regarding Unicode identifiers applies here as to + ;; `c-symbol-key'. + t (concat "[" (c-lang-const c-nonsymbol-chars) "]")) + +(c-lang-defconst c-identifier-ops + "The operators that make up fully qualified identifiers. nil in +languages that don't have such things. See `c-operators' for a +description of the format. Binary operators can concatenate symbols, +e.g. \"::\" in \"A::B::C\". Prefix operators can precede identifiers, +e.g. \"~\" in \"~A::B\". Other types of operators aren't supported. + +This value is by default merged into `c-operators'." + t nil + c++ '((prefix "~" "??-" "compl") + (right-assoc "::") + (prefix "::")) + ;; Java has "." to concatenate identifiers but it's also used for + ;; normal indexing. There's special code in the Java font lock + ;; rules to fontify qualified identifiers based on the standard + ;; naming conventions. We still define "." here to make + ;; `c-forward-name' move over as long names as possible which is + ;; necessary to e.g. handle throws clauses correctly. + java '((left-assoc ".")) + idl '((left-assoc "::") + (prefix "::")) + pike '((left-assoc "::") + (prefix "::") + (left-assoc "."))) + +(c-lang-defconst c-opt-identifier-concat-key + ;; Appendable adorned regexp matching the operators that join + ;; symbols to fully qualified identifiers, or nil in languages that + ;; don't have such things. + ;; + ;; This was a docstring constant in 5.30. It still works but is now + ;; considered internal - change `c-identifier-ops' instead. + t (let ((ops (c-filter-ops (c-lang-const c-identifier-ops) + '(left-assoc right-assoc) + t))) + (when ops + (c-make-keywords-re 'appendable ops)))) +(c-lang-defvar c-opt-identifier-concat-key + (c-lang-const c-opt-identifier-concat-key) + 'dont-doc) + +(c-lang-defconst c-opt-identifier-concat-key-depth + ;; Number of regexp grouping parens in `c-opt-identifier-concat-key'. + t (regexp-opt-depth (c-lang-const c-opt-identifier-concat-key))) + +(c-lang-defconst c-opt-identifier-prefix-key + ;; Appendable adorned regexp matching operators that might precede + ;; an identifier and that are part of the identifier in that case. + ;; nil in languages without such things. + t (let ((ops (c-filter-ops (c-lang-const c-identifier-ops) + '(prefix) + t))) + (when ops + (c-make-keywords-re 'appendable ops)))) + +(c-lang-defconst c-after-id-concat-ops + "Operators that can occur after a binary operator on `c-identifier-ops' +in identifiers. nil in languages that don't have such things. + +Operators here should also have appropriate entries in `c-operators' - +it's not taken care of by default." + t nil + ;; '~' for destructors in C++, '*' for member pointers. + c++ '("~" "*") + ;; In Java we recognize '*' to deal with "foo.bar.*" that can occur + ;; in import declarations. (This will also match bogus things like + ;; "foo.*bar" but we don't bother.) + java '("*")) + +(c-lang-defconst c-opt-after-id-concat-key + ;; Regexp that must match the token after + ;; `c-opt-identifier-concat-key' for it to be considered an + ;; identifier concatenation operator (which e.g. causes the + ;; preceding identifier to be fontified as a reference). Assumed to + ;; be a string if `c-opt-identifier-concat-key' is. + ;; + ;; This was a docstring constant in 5.30. It still works but is now + ;; considered internal - change `c-after-id-concat-ops' instead. + t (concat (c-lang-const c-symbol-start) + (if (c-lang-const c-after-id-concat-ops) + (concat "\\|" (c-make-keywords-re 'appendable + (c-lang-const c-after-id-concat-ops))) + ""))) + +(c-lang-defconst c-identifier-start + "Regexp that matches the start of an (optionally qualified) identifier. +It should also match all keywords. It's unspecified how far it +matches." + t (concat (c-lang-const c-symbol-start) + (if (c-lang-const c-opt-identifier-prefix-key) + (concat "\\|" + (c-lang-const c-opt-identifier-prefix-key)) + ""))) +(c-lang-defvar c-identifier-start (c-lang-const c-identifier-start)) + +(c-lang-defconst c-identifier-key + "Regexp matching a fully qualified identifier, like \"A::B::c\" in +C++. It does not recognize the full range of syntactic whitespace +between the tokens; `c-forward-name' has to be used for that. It +should also not match identifiers containing parenthesis groupings, +e.g. identifiers with template arguments such as \"A\" in C++." + ;; This regexp is more complex than strictly necessary to ensure + ;; that it can be matched with a minimum of backtracking. + t (concat (if (c-lang-const c-opt-identifier-prefix-key) + (concat + "\\(" + (c-lang-const c-opt-identifier-prefix-key) + (c-lang-const c-simple-ws) "*" + "\\)?") + "") + "\\(" (c-lang-const c-symbol-key) "\\)" + (if (c-lang-const c-opt-identifier-concat-key) + (concat + "\\(" + (c-lang-const c-simple-ws) "*" + (c-lang-const c-opt-identifier-concat-key) + (c-lang-const c-simple-ws) "*" + (if (c-lang-const c-after-id-concat-ops) + (concat + "\\(" + (c-make-keywords-re 'appendable + (c-lang-const c-after-id-concat-ops)) + (concat + ;; For flexibility, consider the symbol match + ;; optional if we've hit a + ;; `c-after-id-concat-ops' operator. This is + ;; also necessary to handle the "*" that can + ;; end import declaration identifiers in Java. + "\\(" + (c-lang-const c-simple-ws) "*" + "\\(" (c-lang-const c-symbol-key) "\\)" + "\\)?") + "\\|" + "\\(" (c-lang-const c-symbol-key) "\\)" + "\\)") + (concat "\\(" (c-lang-const c-symbol-key) "\\)")) + "\\)*") + ""))) +(c-lang-defvar c-identifier-key (c-lang-const c-identifier-key)) + +(c-lang-defconst c-identifier-last-sym-match + ;; This was a docstring constant in 5.30 but it's no longer used. + ;; It's only kept to avoid breaking third party code. + ;; + ;; Used to identify the submatch in `c-identifier-key' that + ;; surrounds the last symbol in the qualified identifier. It's a + ;; list of submatch numbers, of which the first that has a match is + ;; taken. It's assumed that at least one does when the regexp has + ;; matched. + t nil) + +(c-lang-defconst c-string-escaped-newlines + "Set if the language support backslash escaped newlines inside string +literals." + t nil + (c c++ objc pike) t) +(c-lang-defvar c-string-escaped-newlines + (c-lang-const c-string-escaped-newlines)) + +(c-lang-defconst c-multiline-string-start-char + "Set if the language supports multiline string literals without escaped +newlines. If t, all string literals are multiline. If a character, +only literals where the open quote is immediately preceded by that +literal are multiline." + t nil + pike ?#) +(c-lang-defvar c-multiline-string-start-char + (c-lang-const c-multiline-string-start-char)) + +(c-lang-defconst c-opt-cpp-symbol + "The symbol which starts preprocessor constructs when in the margin." + t "#" + (java awk) nil) +(c-lang-defvar c-opt-cpp-symbol (c-lang-const c-opt-cpp-symbol)) + +(c-lang-defconst c-opt-cpp-prefix + "Regexp matching the prefix of a cpp directive in the languages that +normally use that macro preprocessor. Tested at bol or at boi. +Assumed to not contain any submatches or \\| operators." + ;; TODO (ACM, 2005-04-01). Amend the following to recognise escaped NLs; + ;; amend all uses of c-opt-cpp-prefix which count regexp-depth. + t "\\s *#\\s *" + (java awk) nil) +(c-lang-defvar c-opt-cpp-prefix (c-lang-const c-opt-cpp-prefix)) + +(c-lang-defconst c-anchored-cpp-prefix + "Regexp matching the prefix of a cpp directive anchored to BOL, +in the languages that have a macro preprocessor." + t (if (c-lang-const c-opt-cpp-prefix) + (concat "^" (c-lang-const c-opt-cpp-prefix)))) +(c-lang-defvar c-anchored-cpp-prefix (c-lang-const c-anchored-cpp-prefix)) + +(c-lang-defconst c-opt-cpp-start + "Regexp matching the prefix of a cpp directive including the directive +name, or nil in languages without preprocessor support. The first +submatch surrounds the directive name." + t (if (c-lang-const c-opt-cpp-prefix) + (concat (c-lang-const c-opt-cpp-prefix) + "\\([" c-alnum "]+\\)")) + ;; Pike, being a scripting language, recognizes hash-bangs too. + pike (concat (c-lang-const c-opt-cpp-prefix) + "\\([" c-alnum "]+\\|!\\)")) +(c-lang-defvar c-opt-cpp-start (c-lang-const c-opt-cpp-start)) + +(c-lang-defconst c-cpp-message-directives + "List of cpp directives (without the prefix) that are followed by a +string message." + t (if (c-lang-const c-opt-cpp-prefix) + '("error")) + (c c++ objc pike) '("error" "warning")) + +(c-lang-defconst c-cpp-include-directives + "List of cpp directives (without the prefix) that are followed by a +file name in angle brackets or quotes." + t (if (c-lang-const c-opt-cpp-prefix) + '("include")) + objc '("include" "import")) + +(c-lang-defconst c-opt-cpp-macro-define + "Cpp directive (without the prefix) that is followed by a macro +definition, or nil if the language doesn't have any." + t (if (c-lang-const c-opt-cpp-prefix) + "define")) +(c-lang-defvar c-opt-cpp-macro-define + (c-lang-const c-opt-cpp-macro-define)) + +(c-lang-defconst c-opt-cpp-macro-define-start + ;; Regexp matching everything up to the macro body of a cpp define, or the + ;; end of the logical line if there is none. Submatch 1 is the name of the + ;; macro. Set if c-opt-cpp-macro-define is. + t (if (c-lang-const c-opt-cpp-macro-define) + (concat (c-lang-const c-opt-cpp-prefix) + (c-lang-const c-opt-cpp-macro-define) + "[ \t]+\\(\\(\\sw\\|_\\)+\\)\\(\([^\)]*\)\\)?" + ;; ^ ^ #defined name + "\\([ \t]\\|\\\\\n\\)*"))) +(c-lang-defvar c-opt-cpp-macro-define-start + (c-lang-const c-opt-cpp-macro-define-start)) + +(c-lang-defconst c-opt-cpp-macro-define-id + ;; Regexp matching everything up to the end of the identifier defined + ;; by a cpp define. + t (if (c-lang-const c-opt-cpp-macro-define) + (concat (c-lang-const c-opt-cpp-prefix) ; # + (c-lang-const c-opt-cpp-macro-define) ; define + "[ \t]+\\(\\sw\\|_\\)+"))) +(c-lang-defvar c-opt-cpp-macro-define-id + (c-lang-const c-opt-cpp-macro-define-id)) + +(c-lang-defconst c-cpp-expr-directives + "List of cpp directives (without the prefix) that are followed by an +expression." + t (if (c-lang-const c-opt-cpp-prefix) + '("if" "elif"))) + +(c-lang-defconst c-cpp-expr-intro-re + "Regexp which matches the start of a CPP directive which contains an +expression, or nil if there aren't any in the language." + t (if (c-lang-const c-cpp-expr-directives) + (concat + (c-lang-const c-opt-cpp-prefix) + (c-make-keywords-re t (c-lang-const c-cpp-expr-directives))))) +(c-lang-defvar c-cpp-expr-intro-re + (c-lang-const c-cpp-expr-intro-re)) + +(c-lang-defconst c-cpp-expr-functions + "List of functions in cpp expressions." + t (if (c-lang-const c-opt-cpp-prefix) + '("defined")) + pike '("defined" "efun" "constant")) + +(c-lang-defconst c-assignment-operators + "List of all assignment operators." + t '("=" "*=" "/=" "%=" "+=" "-=" ">>=" "<<=" "&=" "^=" "|=") + java (append (c-lang-const c-assignment-operators) + '(">>>=")) + c++ (append (c-lang-const c-assignment-operators) + '("and_eq" "or_eq" "xor_eq" "??!=" "??'=")) + idl nil) + +(c-lang-defconst c-operators + "List describing all operators, along with their precedence and +associativity. The order in the list corresponds to the precedence of +the operators: The operators in each element are a group with the same +precedence, and the group has higher precedence than the groups in all +following elements. The car of each element describes the type of the +operator group, and the cdr is a list of the operator tokens in it. +The operator group types are: + +'prefix Unary prefix operators. +'postfix Unary postfix operators. +'postfix-if-paren + Unary postfix operators if and only if the chars have + parenthesis syntax. +'left-assoc Binary left associative operators (i.e. a+b+c means (a+b)+c). +'right-assoc Binary right associative operators (i.e. a=b=c means a=(b=c)). +'right-assoc-sequence + Right associative operator that constitutes of a + sequence of tokens that separate expressions. All the + tokens in the group are in this case taken as + describing the sequence in one such operator, and the + order between them is therefore significant. + +Operators containing a character with paren syntax are taken to match +with a corresponding open/close paren somewhere else. A postfix +operator with close paren syntax is taken to end a postfix expression +started somewhere earlier, rather than start a new one at point. Vice +versa for prefix operators with open paren syntax. + +Note that operators like \".\" and \"->\" which in language references +often are described as postfix operators are considered binary here, +since CC Mode treats every identifier as an expression." + + ;; There's currently no code in CC Mode that exploit all the info + ;; in this variable; precedence, associativity etc are present as a + ;; preparation for future work. + + t `(;; Preprocessor. + ,@(when (c-lang-const c-opt-cpp-prefix) + `((prefix "#" + ,@(when (c-major-mode-is '(c-mode c++-mode)) + '("%:" "??="))) + (left-assoc "##" + ,@(when (c-major-mode-is '(c-mode c++-mode)) + '("%:%:" "??=??="))))) + + ;; Primary. + ,@(c-lang-const c-identifier-ops) + ,@(cond ((or (c-major-mode-is 'c++-mode) (c-major-mode-is 'java-mode)) + `((postfix-if-paren "<" ">"))) ; Templates. + ((c-major-mode-is 'pike-mode) + `((prefix "global" "predef"))) + ((c-major-mode-is 'java-mode) + `((prefix "super")))) + + ;; Postfix. + ,@(when (c-major-mode-is 'c++-mode) + ;; The following need special treatment. + `((prefix "dynamic_cast" "static_cast" + "reinterpret_cast" "const_cast" "typeid"))) + (left-assoc "." + ,@(unless (c-major-mode-is 'java-mode) + '("->"))) + (postfix "++" "--" "[" "]" "(" ")" + ,@(when (c-major-mode-is '(c-mode c++-mode)) + '("<:" ":>" "??(" "??)"))) + + ;; Unary. + (prefix "++" "--" "+" "-" "!" "~" + ,@(when (c-major-mode-is 'c++-mode) '("not" "compl")) + ,@(when (c-major-mode-is '(c-mode c++-mode)) + '("*" "&" "sizeof" "??-")) + ,@(when (c-major-mode-is 'objc-mode) + '("@selector" "@protocol" "@encode")) + ;; The following need special treatment. + ,@(cond ((c-major-mode-is 'c++-mode) + '("new" "delete")) + ((c-major-mode-is 'java-mode) + '("new")) + ((c-major-mode-is 'pike-mode) + '("class" "lambda" "catch" "throw" "gauge"))) + "(" ")" ; Cast. + ,@(when (c-major-mode-is 'pike-mode) + '("[" "]"))) ; Type cast. + + ;; Member selection. + ,@(when (c-major-mode-is 'c++-mode) + `((left-assoc ".*" "->*"))) + + ;; Multiplicative. + (left-assoc "*" "/" "%") + + ;; Additive. + (left-assoc "+" "-") + + ;; Shift. + (left-assoc "<<" ">>" + ,@(when (c-major-mode-is 'java-mode) + '(">>>"))) + + ;; Relational. + (left-assoc "<" ">" "<=" ">=" + ,@(when (c-major-mode-is 'java-mode) + '("instanceof"))) + + ;; Equality. + (left-assoc "==" "!=" + ,@(when (c-major-mode-is 'c++-mode) '("not_eq"))) + + ;; Bitwise and. + (left-assoc "&" + ,@(when (c-major-mode-is 'c++-mode) '("bitand"))) + + ;; Bitwise exclusive or. + (left-assoc "^" + ,@(when (c-major-mode-is '(c-mode c++-mode)) + '("??'")) + ,@(when (c-major-mode-is 'c++-mode) '("xor"))) + + ;; Bitwise or. + (left-assoc "|" + ,@(when (c-major-mode-is '(c-mode c++-mode)) + '("??!")) + ,@(when (c-major-mode-is 'c++-mode) '("bitor"))) + + ;; Logical and. + (left-assoc "&&" + ,@(when (c-major-mode-is 'c++-mode) '("and"))) + + ;; Logical or. + (left-assoc "||" + ,@(when (c-major-mode-is '(c-mode c++-mode)) + '("??!??!")) + ,@(when (c-major-mode-is 'c++-mode) '("or"))) + + ;; Conditional. + (right-assoc-sequence "?" ":") + + ;; Assignment. + (right-assoc ,@(c-lang-const c-assignment-operators)) + + ;; Exception. + ,@(when (c-major-mode-is 'c++-mode) + '((prefix "throw"))) + + ;; Sequence. + (left-assoc ",")) + + ;; IDL got its own definition since it has a much smaller operator + ;; set than the other languages. + idl `(;; Preprocessor. + (prefix "#") + (left-assoc "##") + ;; Primary. + ,@(c-lang-const c-identifier-ops) + ;; Unary. + (prefix "+" "-" "~") + ;; Multiplicative. + (left-assoc "*" "/" "%") + ;; Additive. + (left-assoc "+" "-") + ;; Shift. + (left-assoc "<<" ">>") + ;; And. + (left-assoc "&") + ;; Xor. + (left-assoc "^") + ;; Or. + (left-assoc "|"))) + +(c-lang-defconst c-operator-list + ;; The operators as a flat list (without duplicates). + t (c-filter-ops (c-lang-const c-operators) t t)) + +(c-lang-defconst c-overloadable-operators + "List of the operators that are overloadable, in their \"identifier +form\". See also `c-op-identifier-prefix'." + t nil + c++ '("new" "delete" ;; Can be followed by "[]" but we ignore that. + "+" "-" "*" "/" "%" + "^" "??'" "xor" "&" "bitand" "|" "??!" "bitor" "~" "??-" "compl" + "!" "=" "<" ">" "+=" "-=" "*=" "/=" "%=" "^=" + "??'=" "xor_eq" "&=" "and_eq" "|=" "??!=" "or_eq" + "<<" ">>" ">>=" "<<=" "==" "!=" "not_eq" "<=" ">=" + "&&" "and" "||" "??!??!" "or" "++" "--" "," "->*" "->" + "()" "[]" "<::>" "??(??)") + ;; These work like identifiers in Pike. + pike '("`+" "`-" "`&" "`|" "`^" "`<<" "`>>" "`*" "`/" "`%" "`~" + "`==" "`<" "`>" "`!" "`[]" "`[]=" "`->" "`->=" "`()" "``+" + "``-" "``&" "``|" "``^" "``<<" "``>>" "``*" "``/" "``%" + "`+=")) + +(c-lang-defconst c-overloadable-operators-regexp + ;; Regexp tested after an "operator" token in C++. + t nil + c++ (c-make-keywords-re nil (c-lang-const c-overloadable-operators))) +(c-lang-defvar c-overloadable-operators-regexp + (c-lang-const c-overloadable-operators-regexp)) + +(c-lang-defconst c-opt-op-identifier-prefix + "Regexp matching the token before the ones in +`c-overloadable-operators' when operators are specified in their +\"identifier form\". This typically matches \"operator\" in C++ where +operator functions are specified as e.g. \"operator +\". It's nil in +languages without operator functions or where the complete operator +identifier is listed in `c-overloadable-operators'. + +This regexp is assumed to not match any non-operator identifier." + t nil + c++ (c-make-keywords-re t '("operator"))) +(c-lang-defvar c-opt-op-identifier-prefix + (c-lang-const c-opt-op-identifier-prefix)) + +;; Note: the following alias is an old name which was a mis-spelling. It has +;; been corrected above and throughout cc-engine.el. It will be removed at +;; some release very shortly in the future. ACM, 2006-04-14. +(defalias 'c-opt-op-identitier-prefix 'c-opt-op-identifier-prefix) +(make-obsolete-variable 'c-opt-op-identitier-prefix 'c-opt-op-identifier-prefix + "CC Mode 5.31.4, 2006-04-14") + +(c-lang-defconst c-other-op-syntax-tokens + "List of the tokens made up of characters in the punctuation or +parenthesis syntax classes that have uses other than as expression +operators." + t '("{" "}" "(" ")" "[" "]" ";" ":" "," "=" "/*" "*/" "//") + (c c++ pike) (append '("#" "##" ; Used by cpp. + "::" "...") + (c-lang-const c-other-op-syntax-tokens)) + (c c++) (append '("*") (c-lang-const c-other-op-syntax-tokens)) + c++ (append '("&" "<%" "%>" "<:" ":>" "%:" "%:%:") + (c-lang-const c-other-op-syntax-tokens)) + objc (append '("#" "##" ; Used by cpp. + "+" "-") (c-lang-const c-other-op-syntax-tokens)) + idl (append '("#" "##") ; Used by cpp. + (c-lang-const c-other-op-syntax-tokens)) + pike (append '("..") + (c-lang-const c-other-op-syntax-tokens) + (c-lang-const c-overloadable-operators)) + awk '("{" "}" "(" ")" "[" "]" ";" "," "=" "/")) + +(c-lang-defconst c-all-op-syntax-tokens + ;; List of all tokens in the punctuation and parenthesis syntax + ;; classes. + t (delete-duplicates (append (c-lang-const c-other-op-syntax-tokens) + (c-lang-const c-operator-list)) + :test 'string-equal)) + +(c-lang-defconst c-nonsymbol-token-char-list + ;; List containing all chars not in the word, symbol or + ;; syntactically irrelevant syntax classes, i.e. all punctuation, + ;; parenthesis and string delimiter chars. + t (c-with-syntax-table (c-lang-const c-mode-syntax-table) + ;; Only go through the chars in the printable ASCII range. No + ;; language so far has 8-bit or widestring operators. + (let (list (char 32)) + (while (< char 127) + (or (memq (char-syntax char) '(?w ?_ ?< ?> ?\ )) + (setq list (cons (c-int-to-char char) list))) + (setq char (1+ char))) + list))) + +(c-lang-defconst c-nonsymbol-token-regexp + ;; Regexp matching all tokens in the punctuation and parenthesis + ;; syntax classes. Note that this also matches ".", which can start + ;; a float. + t (c-make-keywords-re nil + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + "\\`\\(\\s.\\|\\s\(\\|\\s\)\\)+\\'"))) +(c-lang-defvar c-nonsymbol-token-regexp + (c-lang-const c-nonsymbol-token-regexp)) + +(c-lang-defconst c-assignment-op-regexp + ;; Regexp matching all assignment operators and only them. The + ;; beginning of the first submatch is used to detect the end of the + ;; token, along with the end of the whole match. + t (if (c-lang-const c-assignment-operators) + (concat + ;; Need special case for "=" since it's a prefix of "==". + "=\\([^=]\\|$\\)" + "\\|" + (c-make-keywords-re nil + (set-difference (c-lang-const c-assignment-operators) + '("=") + :test 'string-equal))) + "\\<\\>")) +(c-lang-defvar c-assignment-op-regexp + (c-lang-const c-assignment-op-regexp)) + +(c-lang-defconst c-<>-multichar-token-regexp + ;; Regexp matching all tokens containing "<" or ">" which are longer + ;; than one char. + t (c-make-keywords-re nil + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + ".[<>]\\|[<>]."))) +(c-lang-defvar c-<>-multichar-token-regexp + (c-lang-const c-<>-multichar-token-regexp)) + +(c-lang-defconst c-<-op-cont-regexp + ;; Regexp matching the second and subsequent characters of all + ;; multicharacter tokens that begin with "<". + t (c-make-keywords-re nil + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + "\\`<." + (lambda (op) (substring op 1))))) + +(c-lang-defvar c-<-op-cont-regexp (c-lang-const c-<-op-cont-regexp)) + +(c-lang-defconst c->-op-cont-regexp + ;; Regexp matching the second and subsequent characters of all + ;; multicharacter tokens that begin with ">". + t (c-make-keywords-re nil + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + "\\`>." + (lambda (op) (substring op 1)))) + java (c-make-keywords-re nil + (c-filter-ops (c-lang-const c-all-op-syntax-tokens) + t + "\\`>[^>]\\|\\`>>[^>]" + (lambda (op) (substring op 1))))) + +(c-lang-defvar c->-op-cont-regexp (c-lang-const c->-op-cont-regexp)) + +(c-lang-defconst c-stmt-delim-chars + ;; The characters that should be considered to bound statements. To + ;; optimize `c-crosses-statement-barrier-p' somewhat, it's assumed to + ;; begin with "^" to negate the set. If ? : operators should be + ;; detected then the string must end with "?:". + t "^;{}?:") +(c-lang-defvar c-stmt-delim-chars (c-lang-const c-stmt-delim-chars)) + +(c-lang-defconst c-stmt-delim-chars-with-comma + ;; Variant of `c-stmt-delim-chars' that additionally contains ','. + t "^;,{}?:") +(c-lang-defvar c-stmt-delim-chars-with-comma + (c-lang-const c-stmt-delim-chars-with-comma)) + + +;;; Syntactic whitespace. + +(c-lang-defconst c-simple-ws + "Regexp matching an ordinary whitespace character. +Does not contain a \\| operator at the top level." + ;; "\\s " is not enough since it doesn't match line breaks. + t "\\(\\s \\|[\n\r]\\)") + +(c-lang-defconst c-simple-ws-depth + ;; Number of regexp grouping parens in `c-simple-ws'. + t (regexp-opt-depth (c-lang-const c-simple-ws))) + +(c-lang-defconst c-line-comment-starter + "String that starts line comments, or nil if such don't exist. +Line comments are always terminated by newlines. At least one of +`c-block-comment-starter' and this one is assumed to be set. + +Note that it's currently not enough to set this to support a new +comment style. Other stuff like the syntax table must also be set up +properly." + t "//" + awk "#") +(c-lang-defvar c-line-comment-starter (c-lang-const c-line-comment-starter)) + +(c-lang-defconst c-block-comment-starter + "String that starts block comments, or nil if such don't exist. +Block comments are ended by `c-block-comment-ender', which is assumed +to be set if this is. At least one of `c-line-comment-starter' and +this one is assumed to be set. + +Note that it's currently not enough to set this to support a new +comment style. Other stuff like the syntax table must also be set up +properly." + t "/*" + awk nil) + +(c-lang-defconst c-block-comment-ender + "String that ends block comments, or nil if such don't exist. + +Note that it's currently not enough to set this to support a new +comment style. Other stuff like the syntax table must also be set up +properly." + t "*/" + awk nil) + +(c-lang-defconst c-comment-start-regexp + ;; Regexp to match the start of any type of comment. + t (let ((re (c-make-keywords-re nil + (list (c-lang-const c-line-comment-starter) + (c-lang-const c-block-comment-starter))))) + (if (memq 'gen-comment-delim c-emacs-features) + (concat re "\\|\\s!") + re))) +(c-lang-defvar c-comment-start-regexp (c-lang-const c-comment-start-regexp)) + +(c-lang-defconst c-block-comment-start-regexp + ;; Regexp which matches the start of a block comment (if such exists in the + ;; language) + t (if (c-lang-const c-block-comment-starter) + (regexp-quote (c-lang-const c-block-comment-starter)) + "\\<\\>")) +(c-lang-defvar c-block-comment-start-regexp + (c-lang-const c-block-comment-start-regexp)) + +(c-lang-defconst c-line-comment-start-regexp + ;; Regexp which matches the start of a line comment (if such exists in the + ;; language; it does in all 7 CC Mode languages). + t (if (c-lang-const c-line-comment-starter) + (regexp-quote (c-lang-const c-line-comment-starter)) + "\\<\\>")) +(c-lang-defvar c-line-comment-start-regexp + (c-lang-const c-line-comment-start-regexp)) + +(c-lang-defconst c-literal-start-regexp + ;; Regexp to match the start of comments and string literals. + t (concat (c-lang-const c-comment-start-regexp) + "\\|" + (if (memq 'gen-string-delim c-emacs-features) + "\"|" + "\""))) +(c-lang-defvar c-literal-start-regexp (c-lang-const c-literal-start-regexp)) + +(c-lang-defconst c-doc-comment-start-regexp + "Regexp to match the start of documentation comments." + t "\\<\\>" + ;; From font-lock.el: `doxygen' uses /*! while others use /**. + (c c++ objc) "/\\*[*!]" + java "/\\*\\*" + pike "/[/*]!") +(c-lang-defvar c-doc-comment-start-regexp + (c-lang-const c-doc-comment-start-regexp)) + +(c-lang-defconst comment-start + "String that starts comments inserted with M-; etc. +`comment-start' is initialized from this." + ;; Default: Prefer line comments to block comments, and pad with a space. + t (concat (or (c-lang-const c-line-comment-starter) + (c-lang-const c-block-comment-starter)) + " ") + ;; In C we still default to the block comment style since line + ;; comments aren't entirely portable. + c "/* ") +(c-lang-setvar comment-start (c-lang-const comment-start)) + +(c-lang-defconst comment-end + "String that ends comments inserted with M-; etc. +`comment-end' is initialized from this." + ;; Default: Use block comment style if comment-start uses block + ;; comments, and pad with a space in that case. + t (if (string-match (concat "\\`\\(" + (c-lang-const c-block-comment-start-regexp) + "\\)") + (c-lang-const comment-start)) + (concat " " (c-lang-const c-block-comment-ender)) + "")) +(c-lang-setvar comment-end (c-lang-const comment-end)) + +(c-lang-defconst comment-start-skip + "Regexp to match the start of a comment plus everything up to its body. +`comment-start-skip' is initialized from this." + ;; Default: Allow the last char of the comment starter(s) to be + ;; repeated, then allow any amount of horizontal whitespace. + t (concat "\\(" + (c-concat-separated + (mapcar (lambda (cs) + (when cs + (concat (regexp-quote cs) "+"))) + (list (c-lang-const c-line-comment-starter) + (c-lang-const c-block-comment-starter))) + "\\|") + "\\)\\s *")) +(c-lang-setvar comment-start-skip (c-lang-const comment-start-skip)) + +(c-lang-defconst c-syntactic-ws-start + ;; Regexp matching any sequence that can start syntactic whitespace. + ;; The only uncertain case is '#' when there are cpp directives. + t (concat "\\s \\|" + (c-make-keywords-re nil + (append (list (c-lang-const c-line-comment-starter) + (c-lang-const c-block-comment-starter) + (when (c-lang-const c-opt-cpp-prefix) + "#")) + '("\n" "\r"))) + "\\|\\\\[\n\r]" + (when (memq 'gen-comment-delim c-emacs-features) + "\\|\\s!"))) +(c-lang-defvar c-syntactic-ws-start (c-lang-const c-syntactic-ws-start)) + +(c-lang-defconst c-syntactic-ws-end + ;; Regexp matching any single character that might end syntactic whitespace. + t (concat "\\s \\|" + (c-make-keywords-re nil + (append (when (c-lang-const c-block-comment-ender) + (list + (string + (elt (c-lang-const c-block-comment-ender) + (1- (length + (c-lang-const c-block-comment-ender))))))) + '("\n" "\r"))) + (when (memq 'gen-comment-delim c-emacs-features) + "\\|\\s!"))) +(c-lang-defvar c-syntactic-ws-end (c-lang-const c-syntactic-ws-end)) + +(c-lang-defconst c-unterminated-block-comment-regexp + ;; Regexp matching an unterminated block comment that doesn't + ;; contain line breaks, or nil in languages without block comments. + ;; Does not contain a \| operator at the top level. + t (when (c-lang-const c-block-comment-starter) + (concat + (regexp-quote (c-lang-const c-block-comment-starter)) + ;; It's messy to cook together a regexp that matches anything + ;; but c-block-comment-ender. + (let ((end (c-lang-const c-block-comment-ender))) + (cond ((= (length end) 1) + (concat "[^" end "\n\r]*")) + ((= (length end) 2) + (concat "[^" (substring end 0 1) "\n\r]*" + "\\(" + (regexp-quote (substring end 0 1)) "+" + "[^" + ;; The quoting rules inside char classes are silly. :P + (cond ((= (elt end 0) (elt end 1)) + (concat (substring end 0 1) "\n\r")) + ((= (elt end 1) ?\]) + (concat (substring end 1 2) "\n\r" + (substring end 0 1))) + (t + (concat (substring end 0 1) "\n\r" + (substring end 1 2)))) + "]" + "[^" (substring end 0 1) "\n\r]*" + "\\)*")) + (t + (error "Can't handle a block comment ender of length %s" + (length end)))))))) + +(c-lang-defconst c-block-comment-regexp + ;; Regexp matching a block comment that doesn't contain line breaks, + ;; or nil in languages without block comments. The reason we don't + ;; allow line breaks is to avoid going very far and risk running out + ;; of regexp stack; this regexp is intended to handle only short + ;; comments that might be put in the middle of limited constructs + ;; like declarations. Does not contain a \| operator at the top + ;; level. + t (when (c-lang-const c-unterminated-block-comment-regexp) + (concat + (c-lang-const c-unterminated-block-comment-regexp) + (let ((end (c-lang-const c-block-comment-ender))) + (cond ((= (length end) 1) + (regexp-quote end)) + ((= (length end) 2) + (concat (regexp-quote (substring end 0 1)) "+" + (regexp-quote (substring end 1 2)))) + (t + (error "Can't handle a block comment ender of length %s" + (length end)))))))) + +(c-lang-defconst c-nonwhite-syntactic-ws + ;; Regexp matching a piece of syntactic whitespace that isn't a + ;; sequence of simple whitespace characters. As opposed to + ;; `c-(forward|backward)-syntactic-ws', this doesn't regard cpp + ;; directives as syntactic whitespace. + t (c-concat-separated + (list (when (c-lang-const c-line-comment-starter) + (concat (regexp-quote (c-lang-const c-line-comment-starter)) + "[^\n\r]*[\n\r]")) + (c-lang-const c-block-comment-regexp) + "\\\\[\n\r]" + (when (memq 'gen-comment-delim c-emacs-features) + "\\s!\\S!*\\s!")) + "\\|")) + +(c-lang-defconst c-syntactic-ws + ;; Regexp matching syntactic whitespace, including possibly the + ;; empty string. As opposed to `c-(forward|backward)-syntactic-ws', + ;; this doesn't regard cpp directives as syntactic whitespace. Does + ;; not contain a \| operator at the top level. + t (concat (c-lang-const c-simple-ws) "*" + "\\(" + (concat "\\(" (c-lang-const c-nonwhite-syntactic-ws) "\\)" + (c-lang-const c-simple-ws) "*") + "\\)*")) + +(c-lang-defconst c-syntactic-ws-depth + ;; Number of regexp grouping parens in `c-syntactic-ws'. + t (regexp-opt-depth (c-lang-const c-syntactic-ws))) + +(c-lang-defconst c-nonempty-syntactic-ws + ;; Regexp matching syntactic whitespace, which is at least one + ;; character long. As opposed to `c-(forward|backward)-syntactic-ws', + ;; this doesn't regard cpp directives as syntactic whitespace. Does + ;; not contain a \| operator at the top level. + t (concat "\\(" + (c-lang-const c-simple-ws) + "\\|" + (c-lang-const c-nonwhite-syntactic-ws) + "\\)+")) + +(c-lang-defconst c-nonempty-syntactic-ws-depth + ;; Number of regexp grouping parens in `c-nonempty-syntactic-ws'. + t (regexp-opt-depth (c-lang-const c-nonempty-syntactic-ws))) + +(c-lang-defconst c-single-line-syntactic-ws + ;; Regexp matching syntactic whitespace without any line breaks. As + ;; opposed to `c-(forward|backward)-syntactic-ws', this doesn't + ;; regard cpp directives as syntactic whitespace. Does not contain + ;; a \| operator at the top level. + t (if (c-lang-const c-block-comment-regexp) + (concat "\\s *\\(" + (c-lang-const c-block-comment-regexp) + "\\s *\\)*") + "\\s *")) + +(c-lang-defconst c-single-line-syntactic-ws-depth + ;; Number of regexp grouping parens in `c-single-line-syntactic-ws'. + t (regexp-opt-depth (c-lang-const c-single-line-syntactic-ws))) + +(c-lang-defconst c-syntactic-eol + ;; Regexp that matches when there is no syntactically significant + ;; text before eol. Macros are regarded as syntactically + ;; significant text here. + t (concat (c-lang-const c-single-line-syntactic-ws) + ;; Match eol (possibly inside a block comment or preceded + ;; by a line continuation backslash), or the beginning of a + ;; line comment. Note: This has to be modified for awk + ;; where line comments start with '#'. + "\\(" + (c-concat-separated + (list (when (c-lang-const c-line-comment-starter) + (regexp-quote (c-lang-const c-line-comment-starter))) + (when (c-lang-const c-unterminated-block-comment-regexp) + (concat (c-lang-const c-unterminated-block-comment-regexp) + "$")) + "\\\\$" + "$") + "\\|") + "\\)")) +(c-lang-defvar c-syntactic-eol (c-lang-const c-syntactic-eol)) + + +;;; Defun handling. + +;; The Emacs variables beginning-of-defun-function and end-of-defun-function +;; will be set so that commands like `mark-defun' and `narrow-to-defun' work +;; right. In older Emacsen, the key sequences C-M-a and C-M-e are, however, +;; bound directly to the CC Mode functions, allowing optimisation for large n. +;; From Emacs 23, this isn't necessary any more, since n is passed to the two +;; functions. +(c-lang-defconst beginning-of-defun-function + "Function to which beginning-of-defun-function will be set." + t 'c-beginning-of-defun + awk 'c-awk-beginning-of-defun) +(c-lang-setvar beginning-of-defun-function + (c-lang-const beginning-of-defun-function)) + +(c-lang-defconst end-of-defun-function + "Function to which end-of-defun-function will be set." + t 'c-end-of-defun + awk 'c-awk-end-of-defun) +(c-lang-setvar end-of-defun-function (c-lang-const end-of-defun-function)) + + +;;; In-comment text handling. + +(c-lang-defconst c-paragraph-start + "Regexp to append to `paragraph-start'." + t "$" + java "\\(@[a-zA-Z]+\\>\\|$\\)" ; For Javadoc. + pike "\\(@[a-zA-Z_-]+\\>\\([^{]\\|$\\)\\|$\\)") ; For Pike refdoc. +(c-lang-defvar c-paragraph-start (c-lang-const c-paragraph-start)) + +(c-lang-defconst c-paragraph-separate + "Regexp to append to `paragraph-separate'." + t "$" + pike (c-lang-const c-paragraph-start)) +(c-lang-defvar c-paragraph-separate (c-lang-const c-paragraph-separate)) + + +;;; Keyword lists. + +;; Note: All and only all language constants containing keyword lists +;; should end with "-kwds"; they're automatically collected into the +;; `c-kwds-lang-consts' list below and used to build `c-keywords' etc. + +(c-lang-defconst c-primitive-type-kwds + "Primitive type keywords. As opposed to the other keyword lists, the +keywords listed here are fontified with the type face instead of the +keyword face. + +If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses +will be handled. + +Do not try to modify this list for end user customizations; the +`*-font-lock-extra-types' variable, where `*' is the mode prefix, is +the appropriate place for that." + t '("char" "double" "float" "int" "long" "short" "signed" + "unsigned" "void") + c (append + '("_Bool" "_Complex" "_Imaginary") ; Conditionally defined in C99. + (c-lang-const c-primitive-type-kwds)) + c++ (append + '("bool" "wchar_t") + (c-lang-const c-primitive-type-kwds)) + ;; Objective-C extends C, but probably not the new stuff in C99. + objc (append + '("id" "Class" "SEL" "IMP" "BOOL") + (c-lang-const c-primitive-type-kwds)) + java '("boolean" "byte" "char" "double" "float" "int" "long" "short" "void") + idl '("Object" "ValueBase" "any" "boolean" "char" "double" "fixed" "float" + "long" "octet" "sequence" "short" "string" "void" "wchar" "wstring" + ;; In CORBA PSDL: + "ref" + ;; The following can't really end a type, but we have to specify them + ;; here due to the assumption in `c-primitive-type-prefix-kwds'. It + ;; doesn't matter that much. + "unsigned" "strong") + pike '(;; this_program isn't really a keyword, but it's practically + ;; used as a builtin type. + "array" "float" "function" "int" "mapping" "mixed" "multiset" + "object" "program" "string" "this_program" "void")) + +(c-lang-defconst c-primitive-type-key + ;; An adorned regexp that matches `c-primitive-type-kwds'. + t (c-make-keywords-re t (c-lang-const c-primitive-type-kwds))) +(c-lang-defvar c-primitive-type-key (c-lang-const c-primitive-type-key)) + +(c-lang-defconst c-primitive-type-prefix-kwds + "Keywords that might act as prefixes for primitive types. Assumed to +be a subset of `c-primitive-type-kwds'." + t nil + (c c++) '("long" "short" "signed" "unsigned") + idl '("long" "unsigned" + ;; In CORBA PSDL: + "strong")) + +(c-lang-defconst c-typedef-kwds + "Prefix keyword\(s\) like \"typedef\" which make a type declaration out +of a variable declaration." + t '("typedef") + (awk idl java) nil) + +(c-lang-defconst c-typedef-key + ;; Adorned regexp matching `c-typedef-kwds'. + t (c-make-keywords-re t (c-lang-const c-typedef-kwds))) +(c-lang-defvar c-typedef-key (c-lang-const c-typedef-key)) + +(c-lang-defconst c-type-prefix-kwds + "Keywords where the following name - if any - is a type name, and +where the keyword together with the symbol works as a type in +declarations. + +Note that an alternative if the second part doesn't hold is +`c-type-list-kwds'. Keywords on this list are typically also present +on one of the `*-decl-kwds' lists." + t nil + c '("struct" "union" "enum") + c++ (append '("class" "typename") + (c-lang-const c-type-prefix-kwds c))) + +(c-lang-defconst c-type-prefix-key + ;; Adorned regexp matching `c-type-prefix-kwds'. + t (c-make-keywords-re t (c-lang-const c-type-prefix-kwds))) +(c-lang-defvar c-type-prefix-key (c-lang-const c-type-prefix-key)) + +(c-lang-defconst c-type-modifier-kwds + "Type modifier keywords. These can occur almost anywhere in types +but they don't build a type of themselves. Unlike the keywords on +`c-primitive-type-kwds', they are fontified with the keyword face and +not the type face." + t nil + c '("const" "restrict" "volatile") + c++ '("const" "volatile" "throw") + objc '("const" "volatile")) + +(c-lang-defconst c-opt-type-modifier-key + ;; Adorned regexp matching `c-type-modifier-kwds', or nil in + ;; languages without such keywords. + t (and (c-lang-const c-type-modifier-kwds) + (c-make-keywords-re t (c-lang-const c-type-modifier-kwds)))) +(c-lang-defvar c-opt-type-modifier-key (c-lang-const c-opt-type-modifier-key)) + +(c-lang-defconst c-opt-type-component-key + ;; An adorned regexp that matches `c-primitive-type-prefix-kwds' and + ;; `c-type-modifier-kwds', or nil in languages without any of them. + t (and (or (c-lang-const c-primitive-type-prefix-kwds) + (c-lang-const c-type-modifier-kwds)) + (c-make-keywords-re t + (append (c-lang-const c-primitive-type-prefix-kwds) + (c-lang-const c-type-modifier-kwds))))) +(c-lang-defvar c-opt-type-component-key + (c-lang-const c-opt-type-component-key)) + +(c-lang-defconst c-type-start-kwds + ;; All keywords that can start a type (i.e. are either a type prefix + ;; or a complete type). + t (delete-duplicates (append (c-lang-const c-primitive-type-kwds) + (c-lang-const c-type-prefix-kwds) + (c-lang-const c-type-modifier-kwds)) + :test 'string-equal)) + +(c-lang-defconst c-class-decl-kwds + "Keywords introducing declarations where the following block (if any) +contains another declaration level that should be considered a class. + +If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses +will be handled. + +Note that presence on this list does not automatically treat the +following identifier as a type; the keyword must also be present on +`c-type-prefix-kwds' or `c-type-list-kwds' to accomplish that." + t nil + c '("struct" "union") + c++ '("class" "struct" "union") + objc '("struct" "union" + "@interface" "@implementation" "@protocol") + java '("class" "@interface" "interface") + idl '("component" "eventtype" "exception" "home" "interface" "struct" + "union" "valuetype" + ;; In CORBA PSDL: + "storagehome" "storagetype" + ;; In CORBA CIDL: + "catalog" "executor" "manages" "segment") + pike '("class")) + +(c-lang-defconst c-class-key + ;; Regexp matching the start of a class. + t (c-make-keywords-re t (c-lang-const c-class-decl-kwds))) +(c-lang-defvar c-class-key (c-lang-const c-class-key)) + +(c-lang-defconst c-brace-list-decl-kwds + "Keywords introducing declarations where the following block (if +any) is a brace list. + +If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses +will be handled." + t '("enum") + (awk) nil) + +(c-lang-defconst c-brace-list-key + ;; Regexp matching the start of declarations where the following + ;; block is a brace list. + t (c-make-keywords-re t (c-lang-const c-brace-list-decl-kwds))) +(c-lang-defvar c-brace-list-key (c-lang-const c-brace-list-key)) + +(c-lang-defconst c-other-block-decl-kwds + "Keywords where the following block (if any) contains another +declaration level that should not be considered a class. For every +keyword here, CC Mode will add a set of special syntactic symbols for +those blocks. E.g. if the keyword is \"foo\" then there will be +`foo-open', `foo-close', and `infoo' symbols. + +The intention is that this category should be used for block +constructs that aren't related to object orientation concepts like +classes (which thus also include e.g. interfaces, templates, +contracts, structs, etc). The more pragmatic distinction is that +while most want some indentation inside classes, it's fairly common +that they don't want it in some of these constructs, so it should be +simple to configure that differently from classes. See also +`c-class-decl-kwds'. + +If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses +will be handled." + t nil + (c objc) '("extern") + c++ '("namespace" "extern") + idl '("module" + ;; In CORBA CIDL: + "composition")) + +(c-lang-defconst c-other-decl-block-key + ;; Regexp matching the start of blocks besides classes that contain + ;; another declaration level. + t (c-make-keywords-re t (c-lang-const c-other-block-decl-kwds))) +(c-lang-defvar c-other-decl-block-key (c-lang-const c-other-decl-block-key)) + +(c-lang-defvar c-other-decl-block-key-in-symbols-alist + (mapcar + (lambda (elt) + (cons elt + (if (string= elt "extern") + 'inextern-lang + (intern (concat "in" elt))))) + (c-lang-const c-other-block-decl-kwds)) + "Alist associating keywords in c-other-decl-block-decl-kwds with +their matching \"in\" syntactic symbols.") + +(c-lang-defconst c-typedef-decl-kwds + "Keywords introducing declarations where the identifier(s) being +declared are types. + +If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses +will be handled." + ;; Default to `c-class-decl-kwds' and `c-brace-list-decl-kwds' + ;; (since e.g. "Foo" is a type that's being defined in "class Foo + ;; {...}"). + t (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-brace-list-decl-kwds)) + ;; Languages that have a "typedef" construct. + (c c++ objc idl pike) (append (c-lang-const c-typedef-decl-kwds) + '("typedef")) + ;; Unlike most other languages, exception names are not handled as + ;; types in IDL since they only can occur in "raises" specs. + idl (delete "exception" (append (c-lang-const c-typedef-decl-kwds) nil))) + +(c-lang-defconst c-typedef-decl-key + t (c-make-keywords-re t (c-lang-const c-typedef-decl-kwds))) +(c-lang-defvar c-typedef-decl-key (c-lang-const c-typedef-decl-key)) + +(c-lang-defconst c-typeless-decl-kwds + "Keywords introducing declarations where the \(first) identifier +\(declarator) follows directly after the keyword, without any type. + +If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses +will be handled." + ;; Default to `c-class-decl-kwds' and `c-brace-list-decl-kwds' + ;; (since e.g. "Foo" is the identifier being defined in "class Foo + ;; {...}"). + t (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-brace-list-decl-kwds)) + ;; Note: "manages" for CORBA CIDL clashes with its presence on + ;; `c-type-list-kwds' for IDL. + idl (append (c-lang-const c-typeless-decl-kwds) + '("factory" "finder" "native" + ;; In CORBA PSDL: + "key" "stores" + ;; In CORBA CIDL: + "facet")) + pike (append (c-lang-const c-class-decl-kwds) + '("constant"))) + +(c-lang-defconst c-modifier-kwds + "Keywords that can prefix normal declarations of identifiers +\(and typically act as flags). Things like argument declarations +inside function headers are also considered declarations in this +sense. + +If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses +will be handled." + t nil + (c c++) '("auto" "extern" "inline" "register" "static") + c++ (append '("explicit" "friend" "mutable" "template" "using" "virtual") + (c-lang-const c-modifier-kwds)) + objc '("auto" "bycopy" "byref" "extern" "in" "inout" "oneway" "out" "static") + ;; FIXME: Some of those below ought to be on `c-other-decl-kwds' instead. + idl '("abstract" "attribute" "const" "consumes" "custom" "emits" "import" + "in" "inout" "local" "multiple" "oneway" "out" "private" "provides" + "public" "publishes" "readonly" "typeid" "typeprefix" "uses" + ;; In CORBA PSDL: + "primary" "state" + ;; In CORBA CIDL: + "bindsTo" "delegatesTo" "implements" "proxy" "storedOn") + ;; Note: "const" is not used in Java, but it's still a reserved keyword. + java '("abstract" "const" "final" "native" "private" "protected" "public" + "static" "strictfp" "synchronized" "transient" "volatile") + pike '("final" "inline" "local" "nomask" "optional" "private" "protected" + "public" "static" "variant")) + +(c-lang-defconst c-other-decl-kwds + "Keywords that can start or prefix any declaration level construct, +besides those on `c-class-decl-kwds', `c-brace-list-decl-kwds', +`c-other-block-decl-kwds', `c-typedef-decl-kwds', +`c-typeless-decl-kwds' and `c-modifier-kwds'. + +If any of these also are on `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses +will be handled." + t nil + objc '("@class" "@end" "@defs") + java '("import" "package") + pike '("import" "inherit")) + +(c-lang-defconst c-decl-start-kwds + "Keywords that always start declarations, wherever they occur. +This can be used for declarations that aren't recognized by the normal +combination of `c-decl-prefix-re' and `c-decl-start-re'." + t nil + ;; Classes can be declared anywhere in a Pike expression. + pike '("class")) + +(c-lang-defconst c-decl-hangon-kwds + "Keywords that can occur anywhere in a declaration level construct. +This is used for self-contained things that can be tacked on anywhere +on a declaration and that should be ignored to be able to recognize it +correctly. Typical cases are compiler extensions like +\"__attribute__\" or \"__declspec\": + + __declspec(noreturn) void foo(); + class __declspec(dllexport) classname {...}; + void foo() __attribute__((noreturn)); + +Note that unrecognized plain symbols are skipped anyway if they occur +before the type, so such things are not necessary to mention here. +Mentioning them here is necessary only if they can occur in other +places, or if they are followed by a construct that must be skipped +over \(like the parens in the \"__attribute__\" and \"__declspec\" +examples above). In the last case, they alse need to be present on +one of `c-type-list-kwds', `c-ref-list-kwds', +`c-colon-type-list-kwds', `c-paren-nontype-kwds', `c-paren-type-kwds', +`c-<>-type-kwds', or `c-<>-arglist-kwds'." + ;; NB: These are currently not recognized in all parts of a + ;; declaration. Specifically, they aren't recognized in the middle + ;; of multi-token types, inside declarators, and between the + ;; identifier and the arglist paren of a function declaration. + ;; + ;; FIXME: This ought to be user customizable since compiler stuff + ;; like this usually is wrapped in project specific macros. (It'd + ;; of course be even better if we could cope without knowing this.) + t nil + (c c++) '(;; GCC extension. + "__attribute__" + ;; MSVC extension. + "__declspec")) + +(c-lang-defconst c-decl-hangon-key + ;; Adorned regexp matching `c-decl-hangon-kwds'. + t (c-make-keywords-re t (c-lang-const c-decl-hangon-kwds))) +(c-lang-defvar c-decl-hangon-key (c-lang-const c-decl-hangon-key)) + +(c-lang-defconst c-prefix-spec-kwds + ;; All keywords that can occur in the preamble of a declaration. + ;; They typically occur before the type, but they are also matched + ;; after presumptive types since we often can't be sure that + ;; something is a type or just some sort of macro in front of the + ;; declaration. They might be ambiguous with types or type + ;; prefixes. + t (delete-duplicates (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-brace-list-decl-kwds) + (c-lang-const c-other-block-decl-kwds) + (c-lang-const c-typedef-decl-kwds) + (c-lang-const c-typeless-decl-kwds) + (c-lang-const c-modifier-kwds) + (c-lang-const c-other-decl-kwds) + (c-lang-const c-decl-start-kwds) + (c-lang-const c-decl-hangon-kwds)) + :test 'string-equal)) + +(c-lang-defconst c-prefix-spec-kwds-re + ;; Adorned regexp of `c-prefix-spec-kwds'. + t (c-make-keywords-re t (c-lang-const c-prefix-spec-kwds))) + +(c-lang-defvar c-prefix-spec-kwds-re (c-lang-const c-prefix-spec-kwds-re)) + +(c-lang-defconst c-specifier-key + ;; Adorned regexp of the keywords in `c-prefix-spec-kwds' that aren't + ;; ambiguous with types or type prefixes. These are the keywords (like + ;; extern, namespace, but NOT template) that can modify a declaration. + t (c-make-keywords-re t + (set-difference (c-lang-const c-prefix-spec-kwds) + (append (c-lang-const c-type-start-kwds) + (c-lang-const c-<>-arglist-kwds)) + :test 'string-equal))) +(c-lang-defvar c-specifier-key (c-lang-const c-specifier-key)) + +(c-lang-defconst c-postfix-spec-kwds + ;; Keywords that can occur after argument list of a function header + ;; declaration, i.e. in the "K&R region". + t (append (c-lang-const c-postfix-decl-spec-kwds) + (c-lang-const c-decl-hangon-kwds))) + +(c-lang-defconst c-not-decl-init-keywords + ;; Adorned regexp matching all keywords that can't appear at the + ;; start of a declaration. + t (c-make-keywords-re t + (set-difference (c-lang-const c-keywords) + (append (c-lang-const c-type-start-kwds) + (c-lang-const c-prefix-spec-kwds)) + :test 'string-equal))) +(c-lang-defvar c-not-decl-init-keywords + (c-lang-const c-not-decl-init-keywords)) + +(c-lang-defconst c-not-primitive-type-keywords + "List of all keywords apart from primitive types (like \"int\")." + t (set-difference (c-lang-const c-keywords) + (c-lang-const c-primitive-type-kwds) + :test 'string-equal) + ;; The "more" for C++ is the QT keyword (as in "more slots:"). + ;; This variable is intended for use in c-beginning-of-statement-1. + c++ (append (c-lang-const c-not-primitive-type-keywords) '("more"))) + +(c-lang-defconst c-not-primitive-type-keywords-regexp + t (c-make-keywords-re t + (c-lang-const c-not-primitive-type-keywords))) +(c-lang-defvar c-not-primitive-type-keywords-regexp + (c-lang-const c-not-primitive-type-keywords-regexp)) + +(c-lang-defconst c-protection-kwds + "Access protection label keywords in classes." + t nil + c++ '("private" "protected" "public") + objc '("@private" "@protected" "@public")) + +(c-lang-defconst c-block-decls-with-vars + "Keywords introducing declarations that can contain a block which +might be followed by variable declarations, e.g. like \"foo\" in +\"class Foo { ... } foo;\". So if there is a block in a declaration +like that, it ends with the following ';' and not right away. + +The keywords on list are assumed to also be present on one of the +`*-decl-kwds' lists." + t nil + (c objc) '("struct" "union" "enum" "typedef") + c++ '("class" "struct" "union" "enum" "typedef")) + +(c-lang-defconst c-opt-block-decls-with-vars-key + ;; Regexp matching the `c-block-decls-with-vars' keywords, or nil in + ;; languages without such constructs. + t (and (c-lang-const c-block-decls-with-vars) + (c-make-keywords-re t (c-lang-const c-block-decls-with-vars)))) +(c-lang-defvar c-opt-block-decls-with-vars-key + (c-lang-const c-opt-block-decls-with-vars-key)) + +(c-lang-defconst c-postfix-decl-spec-kwds + "Keywords introducing extra declaration specifiers in the region +between the header and the body \(i.e. the \"K&R-region\") in +declarations." + t nil + java '("extends" "implements" "throws") + idl '("context" "getraises" "manages" "primarykey" "raises" "setraises" + "supports" + ;; In CORBA PSDL: + "as" "const" "implements" "of" "ref")) + +(c-lang-defconst c-nonsymbol-sexp-kwds + "Keywords that may be followed by a nonsymbol sexp before whatever +construct it's part of continues." + t nil + (c c++ objc) '("extern")) + +(c-lang-defconst c-type-list-kwds + "Keywords that may be followed by a comma separated list of type +identifiers, where each optionally can be prefixed by keywords. (Can +also be used for the special case when the list can contain only one +element.) + +Assumed to be mutually exclusive with `c-ref-list-kwds'. There's no +reason to put keywords on this list if they are on `c-type-prefix-kwds'. +There's also no reason to add keywords that prefixes a normal +declaration consisting of a type followed by a declarator (list), so +the keywords on `c-modifier-kwds' should normally not be listed here +either. + +Note: Use `c-typeless-decl-kwds' for keywords followed by a function +or variable identifier (that's being defined)." + t nil + c++ '("operator") + objc '("@class") + java '("import" "new" "extends" "super" "implements" "throws") + idl '("manages" "native" "primarykey" "supports" + ;; In CORBA PSDL: + "as" "implements" "of" "scope") + pike '("inherit")) + +(c-lang-defconst c-ref-list-kwds + "Keywords that may be followed by a comma separated list of +reference (i.e. namespace/scope/module) identifiers, where each +optionally can be prefixed by keywords. (Can also be used for the +special case when the list can contain only one element.) Assumed to +be mutually exclusive with `c-type-list-kwds'. + +Note: Use `c-typeless-decl-kwds' for keywords followed by a function +or variable identifier (that's being defined)." + t nil + c++ '("namespace") + java '("package") + idl '("import" "module" + ;; In CORBA CIDL: + "composition") + pike '("import")) + +(c-lang-defconst c-colon-type-list-kwds + "Keywords that may be followed (not necessarily directly) by a colon +and then a comma separated list of type identifiers, where each +optionally can be prefixed by keywords. (Can also be used for the +special case when the list can contain only one element.)" + t nil + c++ '("class" "struct") + idl '("component" "eventtype" "home" "interface" "valuetype" + ;; In CORBA PSDL: + "storagehome" "storagetype")) + +(c-lang-defconst c-colon-type-list-re + "Regexp matched after the keywords in `c-colon-type-list-kwds' to skip +forward to the colon. The end of the match is assumed to be directly +after the colon, so the regexp should end with \":\". Must be a +regexp if `c-colon-type-list-kwds' isn't nil." + t (if (c-lang-const c-colon-type-list-kwds) + ;; Disallow various common punctuation chars that can't come + ;; before the ":" that starts the inherit list after "class" + ;; or "struct" in C++. (Also used as default for other + ;; languages.) + "[^\]\[{}();,/#=:]*:")) +(c-lang-defvar c-colon-type-list-re (c-lang-const c-colon-type-list-re)) + +(c-lang-defconst c-paren-nontype-kwds + "Keywords that may be followed by a parenthesis expression that doesn't +contain type identifiers." + t nil + (c c++) '(;; GCC extension. + "__attribute__" + ;; MSVC extension. + "__declspec")) + +(c-lang-defconst c-paren-type-kwds + "Keywords that may be followed by a parenthesis expression containing +type identifiers separated by arbitrary tokens." + t nil + c++ '("throw") + objc '("@defs") + idl '("switch") + pike '("array" "function" "int" "mapping" "multiset" "object" "program")) + +(c-lang-defconst c-paren-any-kwds + t (delete-duplicates (append (c-lang-const c-paren-nontype-kwds) + (c-lang-const c-paren-type-kwds)) + :test 'string-equal)) + +(c-lang-defconst c-<>-type-kwds + "Keywords that may be followed by an angle bracket expression +containing type identifiers separated by \",\". The difference from +`c-<>-arglist-kwds' is that unknown names are taken to be types and +not other identifiers. `c-recognize-<>-arglists' is assumed to be set +if this isn't nil." + t nil + objc '("id") + idl '("sequence" + ;; In CORBA PSDL: + "ref")) + +(c-lang-defconst c-<>-arglist-kwds + "Keywords that can be followed by a C++ style template arglist; see +`c-recognize-<>-arglists' for details. That language constant is +assumed to be set if this isn't nil." + t nil + c++ '("template") + idl '("fixed" "string" "wstring")) + +(c-lang-defconst c-<>-sexp-kwds + ;; All keywords that can be followed by an angle bracket sexp. + t (delete-duplicates (append (c-lang-const c-<>-type-kwds) + (c-lang-const c-<>-arglist-kwds)) + :test 'string-equal)) + +(c-lang-defconst c-opt-<>-sexp-key + ;; Adorned regexp matching keywords that can be followed by an angle + ;; bracket sexp. Always set when `c-recognize-<>-arglists' is. + t (if (c-lang-const c-recognize-<>-arglists) + (c-make-keywords-re t (c-lang-const c-<>-sexp-kwds)))) +(c-lang-defvar c-opt-<>-sexp-key (c-lang-const c-opt-<>-sexp-key)) + +(c-lang-defconst c-brace-id-list-kwds + "Keywords that may be followed by a brace block containing a comma +separated list of identifier definitions, i.e. like the list of +identifiers that follows the type in a normal declaration." + t (c-lang-const c-brace-list-decl-kwds)) + +(c-lang-defconst c-block-stmt-1-kwds + "Statement keywords followed directly by a substatement." + t '("do" "else") + c++ '("do" "else" "try") + java '("do" "else" "finally" "try") + idl nil) + +(c-lang-defconst c-block-stmt-1-key + ;; Regexp matching the start of any statement followed directly by a + ;; substatement (doesn't match a bare block, however). + t (c-make-keywords-re t (c-lang-const c-block-stmt-1-kwds))) +(c-lang-defvar c-block-stmt-1-key (c-lang-const c-block-stmt-1-key)) + +(c-lang-defconst c-block-stmt-2-kwds + "Statement keywords followed by a paren sexp and then by a substatement." + t '("for" "if" "switch" "while") + c++ '("for" "if" "switch" "while" "catch") + java '("for" "if" "switch" "while" "catch" "synchronized") + idl nil + pike '("for" "if" "switch" "while" "foreach") + awk '("for" "if" "while")) + +(c-lang-defconst c-block-stmt-2-key + ;; Regexp matching the start of any statement followed by a paren sexp + ;; and then by a substatement. + t (c-make-keywords-re t (c-lang-const c-block-stmt-2-kwds))) +(c-lang-defvar c-block-stmt-2-key (c-lang-const c-block-stmt-2-key)) + +(c-lang-defconst c-block-stmt-kwds + ;; Union of `c-block-stmt-1-kwds' and `c-block-stmt-2-kwds'. + t (delete-duplicates (append (c-lang-const c-block-stmt-1-kwds) + (c-lang-const c-block-stmt-2-kwds)) + :test 'string-equal)) + +(c-lang-defconst c-opt-block-stmt-key + ;; Regexp matching the start of any statement that has a + ;; substatement (except a bare block). Nil in languages that + ;; don't have such constructs. + t (if (or (c-lang-const c-block-stmt-1-kwds) + (c-lang-const c-block-stmt-2-kwds)) + (c-make-keywords-re t + (append (c-lang-const c-block-stmt-1-kwds) + (c-lang-const c-block-stmt-2-kwds))))) +(c-lang-defvar c-opt-block-stmt-key (c-lang-const c-opt-block-stmt-key)) + +(c-lang-defconst c-simple-stmt-kwds + "Statement keywords followed by an expression or nothing." + t '("break" "continue" "goto" "return") + ;; Note: `goto' is not valid in Java, but the keyword is still reserved. + java '("break" "continue" "goto" "return" "throw") + idl nil + pike '("break" "continue" "return") + awk '(;; Not sure about "delete", "exit", "getline", etc. ; ACM 2002/5/30 + "break" "continue" "return" "delete" "exit" "getline" "next" + "nextfile" "print" "printf")) + +(c-lang-defconst c-simple-stmt-key + ;; Adorned regexp matching `c-simple-stmt-kwds'. + t (c-make-keywords-re t (c-lang-const c-simple-stmt-kwds))) +(c-lang-defvar c-simple-stmt-key (c-lang-const c-simple-stmt-key)) + +(c-lang-defconst c-paren-stmt-kwds + "Statement keywords followed by a parenthesis expression that +nevertheless contains a list separated with ';' and not ','." + t '("for") + idl nil) + +(c-lang-defconst c-paren-stmt-key + ;; Adorned regexp matching `c-paren-stmt-kwds'. + t (c-make-keywords-re t (c-lang-const c-paren-stmt-kwds))) +(c-lang-defvar c-paren-stmt-key (c-lang-const c-paren-stmt-key)) + +(c-lang-defconst c-asm-stmt-kwds + "Statement keywords followed by an assembler expression." + t nil + (c c++) '("asm" "__asm__")) ;; Not standard, but common. + +(c-lang-defconst c-opt-asm-stmt-key + ;; Regexp matching the start of an assembler statement. Nil in + ;; languages that don't support that. + t (if (c-lang-const c-asm-stmt-kwds) + (c-make-keywords-re t (c-lang-const c-asm-stmt-kwds)))) +(c-lang-defvar c-opt-asm-stmt-key (c-lang-const c-opt-asm-stmt-key)) + +(c-lang-defconst c-case-kwds + "The keyword\(s) which introduce a \"case\" like construct. +This construct is \" :\"." + t '("case") + awk nil) + +(c-lang-defconst c-case-kwds-regexp + ;; Adorned regexp matching any "case"-like keyword. + t (c-make-keywords-re t (c-lang-const c-case-kwds))) +(c-lang-defvar c-case-kwds-regexp (c-lang-const c-case-kwds-regexp)) + +(c-lang-defconst c-label-kwds + "Keywords introducing colon terminated labels in blocks." + t '("case" "default")) + +(c-lang-defconst c-label-kwds-regexp + ;; Adorned regexp matching any keyword that introduces a label. + t (c-make-keywords-re t (c-lang-const c-label-kwds))) +(c-lang-defvar c-label-kwds-regexp (c-lang-const c-label-kwds-regexp)) + +(c-lang-defconst c-before-label-kwds + "Keywords that might be followed by a label identifier." + t '("goto") + (java pike) (append '("break" "continue") + (c-lang-const c-before-label-kwds)) + idl nil + awk nil) + +(c-lang-defconst c-constant-kwds + "Keywords for constants." + t nil + (c c++) '("NULL" ;; Not a keyword, but practically works as one. + "false" "true") ; Defined in C99. + objc '("nil" "Nil" "YES" "NO" "NS_DURING" "NS_HANDLER" "NS_ENDHANDLER") + idl '("TRUE" "FALSE") + pike '("UNDEFINED")) ;; Not a keyword, but practically works as one. + +(c-lang-defconst c-primary-expr-kwds + "Keywords besides constants and operators that start primary expressions." + t nil + c++ '("operator" "this") + objc '("super" "self") + java '("this") + pike '("this")) ;; Not really a keyword, but practically works as one. + +(c-lang-defconst c-expr-kwds + ;; Keywords that can occur anywhere in expressions. Built from + ;; `c-primary-expr-kwds' and all keyword operators in `c-operators'. + t (delete-duplicates + (append (c-lang-const c-primary-expr-kwds) + (c-filter-ops (c-lang-const c-operator-list) + t + "\\`\\(\\w\\|\\s_\\)+\\'")) + :test 'string-equal)) + +(c-lang-defconst c-lambda-kwds + "Keywords that start lambda constructs, i.e. function definitions in +expressions." + t nil + pike '("lambda")) + +(c-lang-defconst c-inexpr-block-kwds + "Keywords that start constructs followed by statement blocks which can +be used in expressions \(the gcc extension for this in C and C++ is +handled separately by `c-recognize-paren-inexpr-blocks')." + t nil + pike '("catch" "gauge")) + +(c-lang-defconst c-inexpr-class-kwds + "Keywords that can start classes inside expressions." + t nil + java '("new") + pike '("class")) + +(c-lang-defconst c-inexpr-brace-list-kwds + "Keywords that can start brace list blocks inside expressions. +Note that Java specific rules are currently applied to tell this from +`c-inexpr-class-kwds'." + t nil + java '("new")) + +(c-lang-defconst c-opt-inexpr-brace-list-key + ;; Regexp matching the start of a brace list in an expression, or + ;; nil in languages that don't have such things. This should not + ;; match brace lists recognized through `c-special-brace-lists'. + t (and (c-lang-const c-inexpr-brace-list-kwds) + (c-make-keywords-re t (c-lang-const c-inexpr-brace-list-kwds)))) +(c-lang-defvar c-opt-inexpr-brace-list-key + (c-lang-const c-opt-inexpr-brace-list-key)) + +(c-lang-defconst c-decl-block-key + ;; Regexp matching keywords in any construct that contain another + ;; declaration level, i.e. that isn't followed by a function block + ;; or brace list. When the first submatch matches, it's an + ;; unambiguous construct, otherwise it's an ambiguous match that + ;; might also be the return type of a function declaration. + t (let* ((decl-kwds (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-other-block-decl-kwds) + (c-lang-const c-inexpr-class-kwds))) + (unambiguous (set-difference decl-kwds + (c-lang-const c-type-start-kwds) + :test 'string-equal)) + (ambiguous (intersection decl-kwds + (c-lang-const c-type-start-kwds) + :test 'string-equal))) + (if ambiguous + (concat (c-make-keywords-re t unambiguous) + "\\|" + (c-make-keywords-re t ambiguous)) + (c-make-keywords-re t unambiguous)))) +(c-lang-defvar c-decl-block-key (c-lang-const c-decl-block-key)) + +(c-lang-defconst c-bitfield-kwds + "Keywords that can introduce bitfields." + t nil + (c c++ objc) '("char" "int" "long" "signed" "unsigned")) + +(c-lang-defconst c-opt-bitfield-key + ;; Regexp matching the start of a bitfield (not uniquely), or nil in + ;; languages without bitfield support. + t nil + (c c++) (c-make-keywords-re t (c-lang-const c-bitfield-kwds))) +(c-lang-defvar c-opt-bitfield-key (c-lang-const c-opt-bitfield-key)) + +(c-lang-defconst c-other-kwds + "Keywords not accounted for by any other `*-kwds' language constant." + t nil + idl '("truncatable" + ;; In CORBA CIDL: (These are declaration keywords that never + ;; can start a declaration.) + "entity" "process" "service" "session" "storage")) + + +;;; Constants built from keywords. + +;; Note: No `*-kwds' language constants may be defined below this point. + +(eval-and-compile + (defconst c-kwds-lang-consts + ;; List of all the language constants that contain keyword lists. + (let (list) + (mapatoms (lambda (sym) + (when (and (boundp sym) + (string-match "-kwds\\'" (symbol-name sym))) + ;; Make the list of globally interned symbols + ;; instead of ones interned in `c-lang-constants'. + (setq list (cons (intern (symbol-name sym)) list)))) + c-lang-constants) + list))) + +(c-lang-defconst c-keywords + ;; All keywords as a list. + t (delete-duplicates + (c-lang-defconst-eval-immediately + `(append ,@(mapcar (lambda (kwds-lang-const) + `(c-lang-const ,kwds-lang-const)) + c-kwds-lang-consts) + nil)) + :test 'string-equal)) + +(c-lang-defconst c-keywords-regexp + ;; All keywords as an adorned regexp. + t (c-make-keywords-re t (c-lang-const c-keywords))) +(c-lang-defvar c-keywords-regexp (c-lang-const c-keywords-regexp)) + +(c-lang-defconst c-keyword-member-alist + ;; An alist with all the keywords in the cars. The cdr for each + ;; keyword is a list of the symbols for the `*-kwds' lists that + ;; contains it. + t (let ((kwd-list-alist + (c-lang-defconst-eval-immediately + `(list ,@(mapcar (lambda (kwds-lang-const) + `(cons ',kwds-lang-const + (c-lang-const ,kwds-lang-const))) + c-kwds-lang-consts)))) + lang-const kwd-list kwd + result-alist elem) + (while kwd-list-alist + (setq lang-const (caar kwd-list-alist) + kwd-list (cdar kwd-list-alist) + kwd-list-alist (cdr kwd-list-alist)) + (while kwd-list + (setq kwd (car kwd-list) + kwd-list (cdr kwd-list)) + (unless (setq elem (assoc kwd result-alist)) + (setq result-alist (cons (setq elem (list kwd)) result-alist))) + (unless (memq lang-const (cdr elem)) + (setcdr elem (cons lang-const (cdr elem)))))) + result-alist)) + +(c-lang-defvar c-keywords-obarray + ;; An obarray containing all keywords as symbols. The property list + ;; of each symbol has a non-nil entry for the specific `*-kwds' + ;; lists it's a member of. + ;; + ;; E.g. to see whether the string str contains a keyword on + ;; `c-class-decl-kwds', one can do like this: + ;; (get (intern-soft str c-keyword-obarray) 'c-class-decl-kwds) + ;; Which preferably is written using the associated functions in + ;; cc-engine: + ;; (c-keyword-member (c-keyword-sym str) 'c-class-decl-kwds) + + ;; The obarray is not stored directly as a language constant since + ;; the printed representation for obarrays used in .elc files isn't + ;; complete. + + (let* ((alist (c-lang-const c-keyword-member-alist)) + kwd lang-const-list + (obarray (make-vector (* (length alist) 2) 0))) + (while alist + (setq kwd (caar alist) + lang-const-list (cdar alist) + alist (cdr alist)) + (setplist (intern kwd obarray) + ;; Emacs has an odd bug that causes `mapcan' to fail + ;; with unintelligible errors. (XEmacs works.) + ;;(mapcan (lambda (lang-const) + ;; (list lang-const t)) + ;; lang-const-list) + (apply 'nconc (mapcar (lambda (lang-const) + (list lang-const t)) + lang-const-list)))) + obarray)) + +(c-lang-defconst c-regular-keywords-regexp + ;; Adorned regexp matching all keywords that should be fontified + ;; with the keywords face. I.e. that aren't types or constants. + t (c-make-keywords-re t + (set-difference (c-lang-const c-keywords) + (append (c-lang-const c-primitive-type-kwds) + (c-lang-const c-constant-kwds)) + :test 'string-equal))) +(c-lang-defvar c-regular-keywords-regexp + (c-lang-const c-regular-keywords-regexp)) + +(c-lang-defconst c-primary-expr-regexp + ;; Regexp matching the start of any primary expression, i.e. any + ;; literal, symbol, prefix operator, and '('. It doesn't need to + ;; exclude keywords; they are excluded afterwards unless the second + ;; submatch matches. If the first but not the second submatch + ;; matches then it is an ambiguous primary expression; it could also + ;; be a match of e.g. an infix operator. (The case with ambiguous + ;; keyword operators isn't handled.) + + t (let* ((prefix-ops + (c-filter-ops (c-lang-const c-operators) + '(prefix) + (lambda (op) + ;; Filter out the special case prefix + ;; operators that are close parens. + (not (string-match "\\s)" op))))) + + (nonkeyword-prefix-ops + (c-filter-ops prefix-ops + t + "\\`\\(\\s.\\|\\s(\\|\\s)\\)+\\'")) + + (in-or-postfix-ops + (c-filter-ops (c-lang-const c-operators) + '(postfix + postfix-if-paren + left-assoc + right-assoc + right-assoc-sequence) + t)) + + (unambiguous-prefix-ops (set-difference nonkeyword-prefix-ops + in-or-postfix-ops + :test 'string-equal)) + (ambiguous-prefix-ops (intersection nonkeyword-prefix-ops + in-or-postfix-ops + :test 'string-equal))) + + (concat + "\\(" + ;; Take out all symbol class operators from `prefix-ops' and make the + ;; first submatch from them together with `c-primary-expr-kwds'. + (c-make-keywords-re t + (append (c-lang-const c-primary-expr-kwds) + (set-difference prefix-ops nonkeyword-prefix-ops + :test 'string-equal))) + + "\\|" + ;; Match all ambiguous operators. + (c-make-keywords-re nil + (intersection nonkeyword-prefix-ops in-or-postfix-ops + :test 'string-equal)) + "\\)" + + "\\|" + ;; Now match all other symbols. + (c-lang-const c-symbol-start) + + "\\|" + ;; The chars that can start integer and floating point + ;; constants. + "\\.?[0-9]" + + "\\|" + ;; The nonambiguous operators from `prefix-ops'. + (c-make-keywords-re nil + (set-difference nonkeyword-prefix-ops in-or-postfix-ops + :test 'string-equal)) + + "\\|" + ;; Match string and character literals. + "\\s\"" + (if (memq 'gen-string-delim c-emacs-features) + "\\|\\s|" + "")))) +(c-lang-defvar c-primary-expr-regexp (c-lang-const c-primary-expr-regexp)) + + +;;; Additional constants for parser-level constructs. + +(c-lang-defconst c-decl-prefix-re + "Regexp matching something that might precede a declaration, cast or +label, such as the last token of a preceding statement or declaration. +This is used in the common situation where a declaration or cast +doesn't start with any specific token that can be searched for. + +The regexp should not match bob; that is done implicitly. It can't +require a match longer than one token. The end of the token is taken +to be at the end of the first submatch, which is assumed to always +match. It's undefined whether identifier syntax (see +`c-identifier-syntax-table') is in effect or not. This regexp is +assumed to be a superset of `c-label-prefix-re' if +`c-recognize-colon-labels' is set. + +Besides this, `c-decl-start-kwds' is used to find declarations. + +Note: This variable together with `c-decl-start-re' and +`c-decl-start-kwds' is only used to detect \"likely\" +declaration/cast/label starts. I.e. they might produce more matches +but should not miss anything (or else it's necessary to use text +properties - see the next note). Wherever they match, the following +construct is analyzed to see if it indeed is a declaration, cast or +label. That analysis is not cheap, so it's important that not too +many false matches are triggered. + +Note: If a declaration/cast/label start can't be detected with this +variable, it's necessary to use the `c-type' text property with the +value `c-decl-end' on the last char of the last token preceding the +declaration. See the comment blurb at the start of cc-engine.el for +more info." + + ;; We match a sequence of characters to skip over things like \"};\" + ;; more quickly. We match ")" in C for K&R region declarations, and + ;; in all languages except Java for when a cpp macro definition + ;; begins with a declaration. + t "\\([\{\}\(\);,]+\\)" + java "\\([\{\}\(;,<]+\\)" + ;; Match "<" in C++ to get the first argument in a template arglist. + ;; In that case there's an additional check in `c-find-decl-spots' + ;; that it got open paren syntax. + c++ "\\([\{\}\(\);,<]+\\)" + ;; Additionally match the protection directives in Objective-C. + ;; Note that this doesn't cope with the longer directives, which we + ;; would have to match from start to end since they don't end with + ;; any easily recognized characters. + objc (concat "\\([\{\}\(\);,]+\\|" + (c-make-keywords-re nil (c-lang-const c-protection-kwds)) + "\\)") + ;; Pike is like C but we also match "[" for multiple value + ;; assignments and type casts. + pike "\\([\{\}\(\)\[;,]+\\)") +(c-lang-defvar c-decl-prefix-re (c-lang-const c-decl-prefix-re) + 'dont-doc) + +(c-lang-defconst c-decl-start-re + "Regexp matching the start of any declaration, cast or label. +It's used on the token after the one `c-decl-prefix-re' matched. This +regexp should not try to match those constructs accurately as it's +only used as a sieve to avoid spending more time checking other +constructs." + t (c-lang-const c-identifier-start)) +(c-lang-defvar c-decl-start-re (c-lang-const c-decl-start-re)) + +(c-lang-defconst c-decl-prefix-or-start-re + ;; Regexp matching something that might precede or start a + ;; declaration, cast or label. + ;; + ;; If the first submatch matches, it's taken to match the end of a + ;; token that might precede such a construct, e.g. ';', '}' or '{'. + ;; It's built from `c-decl-prefix-re'. + ;; + ;; If the first submatch did not match, the match of the whole + ;; regexp is taken to be at the first token in the declaration. + ;; `c-decl-start-re' is not checked in this case. + ;; + ;; Design note: The reason the same regexp is used to match both + ;; tokens that precede declarations and start them is to avoid an + ;; extra regexp search from the previous declaration spot in + ;; `c-find-decl-spots'. Users of `c-find-decl-spots' also count on + ;; that it finds all declaration/cast/label starts in approximately + ;; linear order, so we can't do the searches in two separate passes. + t (if (c-lang-const c-decl-start-kwds) + (concat (c-lang-const c-decl-prefix-re) + "\\|" + (c-make-keywords-re t (c-lang-const c-decl-start-kwds))) + (c-lang-const c-decl-prefix-re))) +(c-lang-defvar c-decl-prefix-or-start-re + (c-lang-const c-decl-prefix-or-start-re) + 'dont-doc) + +(c-lang-defconst c-cast-parens + ;; List containing the paren characters that can open a cast, or nil in + ;; languages without casts. + t (c-filter-ops (c-lang-const c-operators) + '(prefix) + "\\`\\s\(\\'" + (lambda (op) (elt op 0)))) +(c-lang-defvar c-cast-parens (c-lang-const c-cast-parens)) + +(c-lang-defconst c-block-prefix-disallowed-chars + "List of syntactically relevant characters that never can occur before +the open brace in any construct that contains a brace block, e.g. in +the \"class Foo: public Bar\" part of: + + class Foo: public Bar {int x();} a, *b; + +If parens can occur, the chars inside those aren't filtered with this +list. + +'<' and '>' should be disallowed even if angle bracket arglists can +occur. That since the search function needs to stop at them anyway to +ensure they are given paren syntax. + +This is used to skip backward from the open brace to find the region +in which to look for a construct like \"class\", \"enum\", +\"namespace\" or whatever. That skipping should be as tight as +possible for good performance." + + ;; Default to all chars that only occurs in nonsymbol tokens outside + ;; identifiers. + t (set-difference + (c-lang-const c-nonsymbol-token-char-list) + (c-filter-ops (append (c-lang-const c-identifier-ops) + (list (cons nil + (c-lang-const c-after-id-concat-ops)))) + t + t + (lambda (op) + (let ((pos 0) res) + (while (string-match "\\(\\s.\\|\\s(\\|\\s)\\)" + op pos) + (setq res (cons (aref op (match-beginning 1)) res) + pos (match-end 0))) + res)))) + + ;; Allow cpp operatios (where applicable). + t (if (c-lang-const c-opt-cpp-prefix) + (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?#)) + (c-lang-const c-block-prefix-disallowed-chars)) + + ;; Allow ':' for inherit list starters. + (c++ objc idl) (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?:)) + + ;; Allow ',' for multiple inherits. + (c++ java) (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?,)) + + ;; Allow parentheses for anonymous inner classes in Java and class + ;; initializer lists in Pike. + (java pike) (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?\( ?\))) + + ;; Allow '"' for extern clauses (e.g. extern "C" {...}). + (c c++ objc) (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?\" ?'))) + +(c-lang-defconst c-block-prefix-charset + ;; `c-block-prefix-disallowed-chars' as an inverted charset suitable + ;; for `c-syntactic-skip-backward'. + t (c-make-bare-char-alt (c-lang-const c-block-prefix-disallowed-chars) t)) +(c-lang-defvar c-block-prefix-charset (c-lang-const c-block-prefix-charset)) + +(c-lang-defconst c-type-decl-prefix-key + "Regexp matching any declarator operator that might precede the +identifier in a declaration, e.g. the \"*\" in \"char *argv\". This +regexp should match \"(\" if parentheses are valid in declarators. +The end of the first submatch is taken as the end of the operator. +Identifier syntax is in effect when this is matched \(see +`c-identifier-syntax-table')." + t (if (c-lang-const c-type-modifier-kwds) + (concat (regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>") + ;; Default to a regexp that never matches. + "\\<\\>") + ;; Check that there's no "=" afterwards to avoid matching tokens + ;; like "*=". + (c objc) (concat "\\(" + "[*\(]" + "\\|" + (c-lang-const c-type-decl-prefix-key) + "\\)" + "\\([^=]\\|$\\)") + c++ (concat "\\(" + "[*\(&]" + "\\|" + (c-lang-const c-type-decl-prefix-key) + "\\|" + (concat "\\(" ; 3 + ;; If this matches there's special treatment in + ;; `c-font-lock-declarators' and + ;; `c-font-lock-declarations' that check for a + ;; complete name followed by ":: *". + (c-lang-const c-identifier-start) + "\\)") + "\\)" + "\\([^=]\\|$\\)") + pike "\\(\\*\\)\\([^=]\\|$\\)") +(c-lang-defvar c-type-decl-prefix-key (c-lang-const c-type-decl-prefix-key) + 'dont-doc) + +(c-lang-defconst c-type-decl-suffix-key + "Regexp matching the declarator operators that might follow after the +identifier in a declaration, e.g. the \"[\" in \"char argv[]\". This +regexp should match \")\" if parentheses are valid in declarators. If +it matches an open paren of some kind, the type declaration check +continues at the corresponding close paren, otherwise the end of the +first submatch is taken as the end of the operator. Identifier syntax +is in effect when this is matched (see `c-identifier-syntax-table')." + ;; Default to a regexp that matches `c-type-modifier-kwds' and a + ;; function argument list parenthesis. + t (if (c-lang-const c-type-modifier-kwds) + (concat "\\(\(\\|" + (regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>" + "\\)") + "\\(\(\\)") + (c c++ objc) (concat + "\\(" + "[\)\[\(]" + (if (c-lang-const c-type-modifier-kwds) + (concat + "\\|" + ;; "throw" in `c-type-modifier-kwds' is followed + ;; by a parenthesis list, but no extra measures + ;; are necessary to handle that. + (regexp-opt (c-lang-const c-type-modifier-kwds) t) + "\\>") + "") + "\\)") + (java idl) "\\([\[\(]\\)") +(c-lang-defvar c-type-decl-suffix-key (c-lang-const c-type-decl-suffix-key) + 'dont-doc) + +(c-lang-defconst c-after-suffixed-type-decl-key + "This regexp is matched after a declarator expression where +`c-type-decl-suffix-key' has matched. If it matches then the +construct is taken as a declaration. It's typically used to match the +beginning of a function body or whatever might occur after the +function header in a function declaration or definition. It's +undefined whether identifier syntax (see `c-identifier-syntax-table') +is in effect or not. + +Note that it's used in cases like after \"foo (bar)\" so it should +only match when it's certain that it's a declaration, e.g \"{\" but +not \",\" or \";\"." + t "{" + ;; If K&R style declarations should be recognized then one could + ;; consider to match the start of any symbol since we want to match + ;; the start of the first declaration in the "K&R region". That + ;; could however produce false matches on code like "FOO(bar) x" + ;; where FOO is a cpp macro, so it's better to leave it out and rely + ;; on the other heuristics in that case. + t (if (c-lang-const c-postfix-spec-kwds) + ;; Add on the keywords in `c-postfix-spec-kwds'. + (concat (c-lang-const c-after-suffixed-type-decl-key) + "\\|" + (c-make-keywords-re t (c-lang-const c-postfix-spec-kwds))) + (c-lang-const c-after-suffixed-type-decl-key)) + ;; Also match the colon that starts a base class initializer list in + ;; C++. That can be confused with a function call before the colon + ;; in a ? : operator, but we count on that `c-decl-prefix-re' won't + ;; match before such a thing (as a declaration-level construct; + ;; matches inside arglist contexts are already excluded). + c++ "[{:]") +(c-lang-defvar c-after-suffixed-type-decl-key + (c-lang-const c-after-suffixed-type-decl-key) + 'dont-doc) + +(c-lang-defconst c-after-suffixed-type-maybe-decl-key + ;; Regexp that in addition to `c-after-suffixed-type-decl-key' + ;; matches ";" and ",". + t (concat "\\(" (c-lang-const c-after-suffixed-type-decl-key) "\\)" + "\\|[;,]")) +(c-lang-defvar c-after-suffixed-type-maybe-decl-key + (c-lang-const c-after-suffixed-type-maybe-decl-key)) + +(c-lang-defconst c-opt-type-concat-key + "Regexp matching operators that concatenate types, e.g. the \"|\" in +\"int|string\" in Pike. The end of the first submatch is taken as the +end of the operator. nil in languages without such operators. It's +undefined whether identifier syntax (see `c-identifier-syntax-table') +is in effect or not." + t nil + pike "\\([|.&]\\)\\($\\|[^|.&]\\)") +(c-lang-defvar c-opt-type-concat-key (c-lang-const c-opt-type-concat-key) + 'dont-doc) + +(c-lang-defconst c-opt-type-suffix-key + "Regexp matching operators that might follow after a type, or nil in +languages that don't have such operators. The end of the first +submatch is taken as the end of the operator. This should not match +things like C++ template arglists if `c-recognize-<>-arglists' is set. +It's undefined whether identifier syntax (see `c-identifier-syntax-table') +is in effect or not." + t nil + (c c++ objc pike) "\\(\\.\\.\\.\\)" + java (concat "\\(\\[" (c-lang-const c-simple-ws) "*\\]\\|\\.\\.\\.\\)")) +(c-lang-defvar c-opt-type-suffix-key (c-lang-const c-opt-type-suffix-key)) + +(c-lang-defvar c-known-type-key + ;; Regexp matching the known type identifiers. This is initialized + ;; from the type keywords and `*-font-lock-extra-types'. The first + ;; submatch is the one that matches the type. Note that this regexp + ;; assumes that symbol constituents like '_' and '$' have word + ;; syntax. + (let* ((extra-types + (when (boundp (c-mode-symbol "font-lock-extra-types")) + (c-mode-var "font-lock-extra-types"))) + (regexp-strings + (mapcan (lambda (re) + (when (string-match "[][.*+?^$\\]" re) + (list re))) + extra-types)) + (plain-strings + (mapcan (lambda (re) + (unless (string-match "[][.*+?^$\\]" re) + (list re))) + extra-types))) + (concat "\\<\\(" + (c-concat-separated + (append (list (c-make-keywords-re nil + (append (c-lang-const c-primitive-type-kwds) + plain-strings))) + regexp-strings) + "\\|") + "\\)\\>"))) + +(c-lang-defconst c-special-brace-lists +"List of open- and close-chars that makes up a pike-style brace list, +i.e. for a ([ ]) list there should be a cons (?\\[ . ?\\]) in this +list." + t nil + pike '((?{ . ?}) (?\[ . ?\]) (?< . ?>))) +(c-lang-defvar c-special-brace-lists (c-lang-const c-special-brace-lists)) + +(c-lang-defconst c-recognize-knr-p + "Non-nil means K&R style argument declarations are valid." + t nil + c t) +(c-lang-defvar c-recognize-knr-p (c-lang-const c-recognize-knr-p)) + +(c-lang-defconst c-recognize-typeless-decls + "Non-nil means function declarations without return type should be +recognized. That can introduce an ambiguity with parenthesized macro +calls before a brace block. This setting does not affect declarations +that are preceded by a declaration starting keyword, so +e.g. `c-typeless-decl-kwds' may still be used when it's set to nil." + t nil + (c c++ objc) t) +(c-lang-defvar c-recognize-typeless-decls + (c-lang-const c-recognize-typeless-decls)) + +(c-lang-defconst c-recognize-<>-arglists + "Non-nil means C++ style template arglists should be handled. More +specifically, this means a comma separated list of types or +expressions surrounded by \"<\" and \">\". It's always preceded by an +identifier or one of the keywords on `c-<>-type-kwds' or +`c-<>-arglist-kwds'. If there's an identifier before then the whole +expression is considered to be a type." + t (or (consp (c-lang-const c-<>-type-kwds)) + (consp (c-lang-const c-<>-arglist-kwds))) + java t) ; 2008-10-19. This is crude. The syntax for java + ; generics is not yet coded in CC Mode. +(c-lang-defvar c-recognize-<>-arglists (c-lang-const c-recognize-<>-arglists)) + +(c-lang-defconst c-enums-contain-decls + "Non-nil means that an enum structure can contain declarations." + t nil + java t) +(c-lang-defvar c-enums-contain-decls (c-lang-const c-enums-contain-decls)) + +(c-lang-defconst c-recognize-paren-inits + "Non-nil means that parenthesis style initializers exist, +i.e. constructs like + +Foo bar (gnu); + +in addition to the more classic + +Foo bar = gnu;" + t nil + c++ t) +(c-lang-defvar c-recognize-paren-inits (c-lang-const c-recognize-paren-inits)) + +(c-lang-defconst c-recognize-paren-inexpr-blocks + "Non-nil to recognize gcc style in-expression blocks, +i.e. compound statements surrounded by parentheses inside expressions." + t nil + (c c++) t) +(c-lang-defvar c-recognize-paren-inexpr-blocks + (c-lang-const c-recognize-paren-inexpr-blocks)) + +(c-lang-defconst c-opt-<>-arglist-start + ;; Regexp matching the start of angle bracket arglists in languages + ;; where `c-recognize-<>-arglists' is set. Does not exclude + ;; keywords outside `c-<>-arglist-kwds'. The first submatch is + ;; assumed to surround the preceding symbol. The whole match is + ;; assumed to end directly after the opening "<". + t (if (c-lang-const c-recognize-<>-arglists) + (concat "\\(" + (c-lang-const c-symbol-key) + "\\)" + (c-lang-const c-syntactic-ws) + "<"))) +(c-lang-defvar c-opt-<>-arglist-start (c-lang-const c-opt-<>-arglist-start)) + +(c-lang-defconst c-opt-<>-arglist-start-in-paren + ;; Regexp that in addition to `c-opt-<>-arglist-start' matches close + ;; parens. The first submatch is assumed to surround + ;; `c-opt-<>-arglist-start'. + t (if (c-lang-const c-opt-<>-arglist-start) + (concat "\\(" + (c-lang-const c-opt-<>-arglist-start) + "\\)\\|\\s\)"))) +(c-lang-defvar c-opt-<>-arglist-start-in-paren + (c-lang-const c-opt-<>-arglist-start-in-paren)) + +(c-lang-defconst c-opt-postfix-decl-spec-key + ;; Regexp matching the beginning of a declaration specifier in the + ;; region between the header and the body of a declaration. + ;; + ;; TODO: This is currently not used uniformly; c++-mode and + ;; java-mode each have their own ways of using it. + t nil + c++ (concat ":?" + (c-lang-const c-simple-ws) "*" + "\\(virtual" (c-lang-const c-simple-ws) "+\\)?\\(" + (c-make-keywords-re nil (c-lang-const c-protection-kwds)) + "\\)" (c-lang-const c-simple-ws) "+" + "\\(" (c-lang-const c-symbol-key) "\\)") + java (c-make-keywords-re t (c-lang-const c-postfix-spec-kwds))) +(c-lang-defvar c-opt-postfix-decl-spec-key + (c-lang-const c-opt-postfix-decl-spec-key)) + +(c-lang-defconst c-recognize-colon-labels + "Non-nil if generic labels ending with \":\" should be recognized. +That includes labels in code and access keys in classes. This does +not apply to labels recognized by `c-label-kwds' and +`c-opt-extra-label-key'." + t nil + (c c++ objc java pike) t) +(c-lang-defvar c-recognize-colon-labels + (c-lang-const c-recognize-colon-labels)) + +(c-lang-defconst c-label-prefix-re + "Regexp like `c-decl-prefix-re' that matches any token that can precede +a generic colon label. Not used if `c-recognize-colon-labels' is +nil." + t "\\([{};]+\\)") +(c-lang-defvar c-label-prefix-re + (c-lang-const c-label-prefix-re)) + +(c-lang-defconst c-nonlabel-token-key + "Regexp matching things that can't occur in generic colon labels, +neither in a statement nor in a declaration context. The regexp is +tested at the beginning of every sexp in a suspected label, +i.e. before \":\". Only used if `c-recognize-colon-labels' is set." + t (concat + ;; All keywords except `c-label-kwds' and `c-protection-kwds'. + (c-make-keywords-re t + (set-difference (c-lang-const c-keywords) + (append (c-lang-const c-label-kwds) + (c-lang-const c-protection-kwds)) + :test 'string-equal))) + ;; Don't allow string literals, except in AWK. Character constants are OK. + (c objc java pike idl) (concat "\"\\|" + (c-lang-const c-nonlabel-token-key)) + ;; Also check for open parens in C++, to catch member init lists in + ;; constructors. We normally allow it so that macros with arguments + ;; work in labels. + c++ (concat "\\s\(\\|\"\\|" (c-lang-const c-nonlabel-token-key))) +(c-lang-defvar c-nonlabel-token-key (c-lang-const c-nonlabel-token-key)) + +(c-lang-defconst c-nonlabel-token-2-key + "Regexp matching things that can't occur two symbols before a colon in +a label construct. This catches C++'s inheritance construct \"class foo +: bar\". Only used if `c-recognize-colon-labels' is set." + t "\\<\\>" ; matches nothing + c++ (c-make-keywords-re t '("class"))) +(c-lang-defvar c-nonlabel-token-2-key (c-lang-const c-nonlabel-token-2-key)) + +(c-lang-defconst c-opt-extra-label-key + "Optional regexp matching labels. +Normally, labels are detected according to `c-nonlabel-token-key', +`c-decl-prefix-re' and `c-nonlabel-decl-prefix-re'. This regexp can +be used if there are additional labels that aren't recognized that +way." + t nil + objc (c-make-keywords-re t (c-lang-const c-protection-kwds))) +(c-lang-defvar c-opt-extra-label-key (c-lang-const c-opt-extra-label-key)) + +(c-lang-defconst c-opt-friend-key + ;; Regexp describing friend declarations classes, or nil in + ;; languages that don't have such things. + ;; + ;; TODO: Ought to use `c-prefix-spec-kwds-re' or similar, and the + ;; template skipping isn't done properly. This will disappear soon. + t nil + c++ (concat "friend" (c-lang-const c-simple-ws) "+" + "\\|" + (concat "template" + (c-lang-const c-simple-ws) "*" + "<.+>" + (c-lang-const c-simple-ws) "*" + "friend" + (c-lang-const c-simple-ws) "+"))) +(c-lang-defvar c-opt-friend-key (c-lang-const c-opt-friend-key)) + +(c-lang-defconst c-opt-method-key + ;; Special regexp to match the start of Objective-C methods. The + ;; first submatch is assumed to end after the + or - key. + t nil + objc (concat + ;; TODO: Ought to use a better method than anchoring on bol. + "^\\s *" + "\\([+-]\\)" + (c-lang-const c-simple-ws) "*" + (concat "\\(" ; Return type. + "([^\)]*)" + (c-lang-const c-simple-ws) "*" + "\\)?") + "\\(" (c-lang-const c-symbol-key) "\\)")) +(c-lang-defvar c-opt-method-key (c-lang-const c-opt-method-key)) + +(c-lang-defconst c-type-decl-end-used + ;; Must be set in buffers where the `c-type' text property might be + ;; used with the value `c-decl-end'. + ;; + ;; `c-decl-end' is used to mark the ends of labels and access keys + ;; to make interactive refontification work better. + t (or (c-lang-const c-recognize-colon-labels) + (and (c-lang-const c-label-kwds) t)) + ;; `c-decl-end' is used to mark the end of the @-style directives in + ;; Objective-C. + objc t) +(c-lang-defvar c-type-decl-end-used (c-lang-const c-type-decl-end-used)) + + +;;; Wrap up the `c-lang-defvar' system. + +;; Compile in the list of language variables that has been collected +;; with the `c-lang-defvar' and `c-lang-setvar' macros. Note that the +;; first element of each is nil. +(defconst c-lang-variable-inits (cc-eval-when-compile c-lang-variable-inits)) +(defconst c-emacs-variable-inits (cc-eval-when-compile c-emacs-variable-inits)) + +;; Make the `c-lang-setvar' variables buffer local in the current buffer. +;; These are typically standard emacs variables such as `comment-start'. +(defmacro c-make-emacs-variables-local () + `(progn + ,@(mapcar (lambda (init) + `(make-local-variable ',(car init))) + (cdr c-emacs-variable-inits)))) + +(defun c-make-init-lang-vars-fun (mode) + "Create a function that initializes all the language dependent variables +for the given mode. + +This function should be evaluated at compile time, so that the +function it returns is byte compiled with all the evaluated results +from the language constants. Use the `c-init-language-vars' macro to +accomplish that conveniently." + + (if (and (not load-in-progress) + (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + + ;; No need to byte compile this lambda since the byte compiler is + ;; smart enough to detect the `funcall' construct in the + ;; `c-init-language-vars' macro below and compile it all straight + ;; into the function that contains `c-init-language-vars'. + `(lambda () + + ;; This let sets up the context for `c-mode-var' and similar + ;; that could be in the result from `cl-macroexpand-all'. + (let ((c-buffer-is-cc-mode ',mode) + current-var source-eval) + (c-make-emacs-variables-local) + (condition-case err + + (if (eq c-version-sym ',c-version-sym) + (setq ,@(let ((c-buffer-is-cc-mode mode) + (c-lang-const-expansion 'immediate)) + ;; `c-lang-const' will expand to the evaluated + ;; constant immediately in `cl-macroexpand-all' + ;; below. + (mapcan + (lambda (init) + `(current-var ',(car init) + ,(car init) ,(cl-macroexpand-all + (elt init 1)))) + ;; Note: The following `append' copies the + ;; first argument. That list is small, so + ;; this doesn't matter too much. + (append (cdr c-emacs-variable-inits) + (cdr c-lang-variable-inits))))) + + ;; This diagnostic message isn't useful for end + ;; users, so it's disabled. + ;;(unless (get ',mode 'c-has-warned-lang-consts) + ;; (message ,(concat "%s compiled with CC Mode %s " + ;; "but loaded with %s - evaluating " + ;; "language constants from source") + ;; ',mode ,c-version c-version) + ;; (put ',mode 'c-has-warned-lang-consts t)) + + (setq source-eval t) + (let ((init ',(append (cdr c-emacs-variable-inits) + (cdr c-lang-variable-inits)))) + (while init + (setq current-var (caar init)) + (set (caar init) (eval (cadar init))) + (setq init (cdr init))))) + + (error + (if current-var + (message "Eval error in the `c-lang-defvar' or `c-lang-setvar' for `%s'%s: %S" + current-var + (if source-eval + (format "\ + (fallback source eval - %s compiled with CC Mode %s but loaded with %s)" + ',mode ,c-version c-version) + "") + err) + (signal (car err) (cdr err))))))) + + ;; Being evaluated from source. Always use the dynamic method to + ;; work well when `c-lang-defvar's in this file are reevaluated + ;; interactively. + `(lambda () + (require 'cc-langs) + (let ((c-buffer-is-cc-mode ',mode) + (init (append (cdr c-emacs-variable-inits) + (cdr c-lang-variable-inits))) + current-var) + (c-make-emacs-variables-local) + (condition-case err + + (while init + (setq current-var (caar init)) + (set (caar init) (eval (cadar init))) + (setq init (cdr init))) + + (error + (if current-var + (message + "Eval error in the `c-lang-defvar' or `c-lang-setver' for `%s' (source eval): %S" + current-var err) + (signal (car err) (cdr err))))))) + )) + +(defmacro c-init-language-vars (mode) + "Initialize all the language dependent variables for the given mode. +This macro is expanded at compile time to a form tailored for the mode +in question, so MODE must be a constant. Therefore MODE is not +evaluated and should not be quoted." + `(funcall ,(c-make-init-lang-vars-fun mode))) + + +(cc-provide 'cc-langs) + +;;; arch-tag: 1ab57482-cfc2-4c5b-b628-3539c3098822 + +;;; cc-langs.el ends here + diff --git a/site-lisp/cc-mode/5.32.3/cc-lobotomy.el b/site-lisp/cc-mode/5.32.3/cc-lobotomy.el new file mode 100644 index 0000000..ce1c2c5 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-lobotomy.el @@ -0,0 +1,160 @@ +;;; cc-lobotomy.el --- excise portions of cc-mode's brain... for speed + +;; Copyright (C) 1985,1987,1992-2003, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Author: 1995 Barry A. Warsaw +;; Maintainer: Unmaintained +;; Created: March 1995, split from cc-mode.el +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is not part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, see +;; . + +;;; Commentary: +;; +;; Every effort has been made to improve the performance of +;; cc-mode. However, due to the nature of the C, C++, and Objective-C +;; language definitions, a trade-off is often required between +;; accuracy of construct recognition and speed. I believe it is always +;; best to be correct, and that the mode is currently fast enough for +;; most normal usage. Others disagree. I have no intention of +;; including these hacks in the main distribution. When cc-mode +;; version 5 comes out, it will include a rewritten indentation engine +;; so that performance will be greatly improved automatically. This +;; was not included in this release of version 4 so that Emacs 18 +;; could still be supported. Note that this implies that cc-mode +;; version 5 will *not* work on Emacs 18! +;; +;; To use, see the variable cc-lobotomy-pith-list and the function +;; cc-lobotomize. The variable contains a good explanation of the +;; speed/accuracy trade-offs for each option. Set it to what you'd +;; like, and call cc-lobotomy in your c-mode-hook. +;; +;; This will redefine certain cc-mode functions and affect all cc-mode +;; buffers globally. +;; +;; This file is completely unsupported! Although it has been patched +;; superficially to keep pace with the rest of CC Mode, it hasn't been +;; tested for a long time. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-engine) +(cc-require 'cc-cmds) + + +(defvar cc-lobotomy-pith-list () + "*List of things to dumb-ify to speed up cc-mode. Note that each +incurs a penalty in correct identification of certain code constructs. +Possible values to put on this list: + + 'literal -- `c-in-literal' is lobotomized. This will significantly + speed up parsing over large lists of cpp macros, as seen + for instance in header files. The penalty is that you + cannot put the `#' character as the first non-whitespace + character on a line inside other multi-line literals + (i.e. comments or strings) + + 'class -- `c-narrow-out-enclosing-class' and `c-search-uplist for + classkey' are lobotomized. This speeds up some + indenting inside and around class and struct + definitions. The penalty is that elements inside of + classes and structs may not indent correctly. + + 'lists -- `c-inside-bracelist-p' is lobotomized. This speeds up + indenting inside and around brace lists (e.g. aggregate + initializers, enum lists, etc.). The penalty is that + elements inside these lists may not indent correctly.") + +(defun cc-lobotomize () + "Perform lobotomies on cc-mode as described in `cc-lobotomy-pith-list'." + (let (pithedp) + (if (memq 'literal cc-lobotomy-pith-list) + (progn + (fset 'c-in-literal 'cc-in-literal-lobotomized) + (setq pithedp t))) + (if (memq 'class cc-lobotomy-pith-list) + (progn + (fset 'c-narrow-out-enclosing-class + 'cc-narrow-out-enclosing-class-lobotomized) + (fset 'c-search-uplist-for-classkey + 'cc-search-uplist-for-classkey-lobotomized) + (setq pithedp t))) + (if (memq 'lists cc-lobotomy-pith-list) + (progn + (fset 'c-inside-bracelist-p 'cc-inside-bracelist-p-lobotomized) + (setq pithedp t))) + (if pithedp + (add-hook 'c-prepare-bug-report-hooks 'cc-lobo-bug-report-blurb)) + )) + + +;; This is a faster version of c-in-literal. It trades speed for one +;; approximation, namely that within other literals, the `#' character +;; cannot be the first non-whitespace on a line. This only happens if +;; detect-cpp is non-nil, which isn't very often. +(defun cc-in-literal-lobotomized (&optional lim detect-cpp) + ;; first check the cache + (if (and (vectorp c-in-literal-cache) + (= (point) (aref c-in-literal-cache 0))) + (aref c-in-literal-cache 1) + ;; quickly check for cpp macro. this breaks if the `#' character + ;; appears as the first non-whitespace on a line inside another + ;; literal. + (let* (state + (char-at-boi (char-after (c-point 'boi))) + (rtn (cond + ((and detect-cpp char-at-boi (= char-at-boi ?#)) + 'pound) + ((nth 3 (setq state (save-excursion + (parse-partial-sexp + (or lim (c-point 'bod)) + (point))))) + 'string) + ((nth 4 state) (if (nth 7 state) 'c++ 'c)) + (t nil)))) + ;; cache this result if the cache is enabled + (if (not c-in-literal-cache) + (setq c-in-literal-cache (vector (point) rtn))) + rtn))) + +(defun cc-narrow-out-enclosing-class-lobotomized (dummy1 dummy2) nil) + +(defun cc-search-uplist-for-classkey-lobotomized (dummy) nil) + +(defun cc-inside-bracelist-p-lobotomized (dummy1 dummy2) nil) + +(defun cc-lobo-bug-report-blurb () + (insert + "\nYou are using cc-lobotomy.el. You realize that by doing\n" + "so you have already made the decision to trade off accuracy\n" + "for speed? Don't set your hopes too high that your problem\n" + "will be fixed.\n\n")) + + +(cc-provide 'cc-lobotomy) +;;; cc-lobotomy.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-menus.el b/site-lisp/cc-mode/5.32.3/cc-menus.el new file mode 100644 index 0000000..384392e --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-menus.el @@ -0,0 +1,446 @@ +;;; cc-menus.el --- imenu support for CC Mode + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 22-Apr-1997 (split from cc-mode.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) + +;; The things referenced in imenu, which we don't require. +(cc-bytecomp-defvar imenu-case-fold-search) +(cc-bytecomp-defvar imenu-generic-expression) +(cc-bytecomp-defvar imenu-create-index-function) +(cc-bytecomp-defun imenu-progress-message) + + +;; imenu integration +(defvar cc-imenu-c-prototype-macro-regexp nil + "RE matching macro names used to conditionally specify function prototypes. + +For example: + + #ifdef __STDC__ + #define _P(x) x + #else + #define _P(x) /*nothing*/ + #endif + + int main _P( (int argc, char *argv[]) ) + +A sample value might look like: `\\(_P\\|_PROTO\\)'.") + +;; *Warning for cc-mode developers* +;; +;; `cc-imenu-objc-generic-expression' elements depend on +;; `cc-imenu-c++-generic-expression'. So if you change this +;; expression, you need to change following variables, +;; `cc-imenu-objc-generic-expression-*-index', +;; too. `cc-imenu-objc-function' uses these *-index variables, in +;; order to know where the each regexp *group \\(foobar\\)* elements +;; are started. +;; +;; *-index variables are initialized during `cc-imenu-objc-generic-expression' +;; being initialized. +;; + +(defvar cc-imenu-c++-generic-expression + `( + ;; Try to match ::operator definitions first. Otherwise `X::operator new ()' + ;; will be incorrectly recognised as function `new ()' because the regexps + ;; work by backtracking from the end of the definition. + (nil + ,(concat + "^\\<.*" + "[^" c-alnum "_:<>~]" ; match any non-identifier char + ; (note: this can be `\n') + "\\(" + "\\([" c-alnum "_:<>~]*::\\)?" ; match an operator + "operator\\>[ \t]*" + "\\(()\\|[^(]*\\)" ; special case for `()' operator + "\\)" + + "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list, + ; require something other than + ; a `;' after the (...) to + ; avoid prototypes. Can't + ; catch cases with () inside + ; the parentheses surrounding + ; the parameters. e.g.: + ; `int foo(int a=bar()) {...}' + ) 1) + ;; Special case to match a line like `main() {}' + ;; e.g. no return type, not even on the previous line. + (nil + ,(concat + "^" + "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name + "[ \t]*(" ; see above, BUT + "[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start + "[ \t]*[^ \t;(]" ; with an asterisk or parentheses + ) 1) + ;; General function name regexp + (nil + ,(concat + "^\\<" ; line MUST start with word char + "[^()]*" ; no parentheses before + "[^" c-alnum "_:<>~]" ; match any non-identifier char + "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name + "\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list + "\\([ \t\n]\\|\\\\\n\\)*" ; must not start + "\\([^ \t\n(*]" ; with an asterisk or parentheses + "[^()]*\\(([^()]*)[^()]*\\)*" ; Maybe function pointer arguments + "\\)?)" + "\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]" + ) 1) + ;; Special case for definitions using phony prototype macros like: + ;; `int main _PROTO( (int argc,char *argv[]) )'. + ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set. + ;; Only supported in c-code, so no `:<>~' chars in function name! + ,@(if cc-imenu-c-prototype-macro-regexp + `((nil + ,(concat + "^\\<.*" ; line MUST start with word char + "[^" c-alnum "_]" ; match any non-identifier char + "\\([" c-alpha "_][" c-alnum "_]*\\)" ; match function name + "[ \t]*" ; whitespace before macro name + cc-imenu-c-prototype-macro-regexp + "[ \t]*(" ; ws followed by first paren. + "[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above + ) 1))) + ;; Class definitions + ("Class" + ,(concat + "^" ; beginning of line is required + "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template <...>' + "\\(class\\|struct\\)[ \t]+" + "\\(" ; the string we want to get + "[" c-alnum "_]+" ; class name + "\\(<[^>]+>\\)?" ; possibly explicitly specialized + "\\)" + "\\([ \t\n]\\|\\\\\n\\)*[:{]" + ) 3)) + "Imenu generic expression for C++ mode. See `imenu-generic-expression'.") + +(defvar cc-imenu-c-generic-expression + cc-imenu-c++-generic-expression + "Imenu generic expression for C mode. See `imenu-generic-expression'.") + +(defvar cc-imenu-java-generic-expression + `((nil + ,(concat + "[" c-alpha "_][\]\[." c-alnum "_<> ]+[ \t\n\r]+" ; type spec + "\\([" c-alpha "_][" c-alnum "_]*\\)" ; method name + "[ \t\n\r]*" + ;; An argument list that is either empty or contains any number + ;; of arppguments. An argument is any number of annotations + + ;; followed by a type spec followed by a word. A word is an + ;; identifier. A type spec is an identifier, possibly followed + ;; by < typespec > possibly followed by []. + (concat "(" + "\\(" + "[ \t\n\r]*" + "\\(" + "@" + "[" c-alpha "_]" + "[" c-alnum "._]*" + "[ \t\n\r]+" + "\\)*" + "\\(" + "[" c-alpha "_]" + "[][" c-alnum "_.]*" + "\\(" + "<" + "[ \t\n\r]*" + "[\]\[.," c-alnum "_<> \t\n\r]*" + ">" + "\\)?" + "[\]\[ \t\n\r]+" + "\\)" + "[" c-alpha "_]" + "[" c-alnum "_]*" + "[ \t\n\r,]*" + "\\)*" + ")" + "[.," c-alnum " \t\n\r]*" + "{" + )) 1)) + "Imenu generic expression for Java mode. See `imenu-generic-expression'.") + +;; Internal variables +(defvar cc-imenu-objc-generic-expression-noreturn-index nil) +(defvar cc-imenu-objc-generic-expression-general-func-index nil) +(defvar cc-imenu-objc-generic-expression-proto-index nil) +(defvar cc-imenu-objc-generic-expression-objc-base-index nil) + +(defvar cc-imenu-objc-generic-expression + (concat + ;; + ;; For C + ;; + ;; > Special case to match a line like `main() {}' + ;; > e.g. no return type, not even on the previous line. + ;; Pick a token by (match-string 1) + (car (cdr (nth 1 cc-imenu-c++-generic-expression))) ; -> index += 2 + (prog2 (setq cc-imenu-objc-generic-expression-noreturn-index 1) "") + "\\|" + ;; > General function name regexp + ;; Pick a token by (match-string 3) + (car (cdr (nth 2 cc-imenu-c++-generic-expression))) ; -> index += 6 + (prog2 (setq cc-imenu-objc-generic-expression-general-func-index 3) "") + ;; > Special case for definitions using phony prototype macros like: + ;; > `int main _PROTO( (int argc,char *argv[]) )'. + ;; Pick a token by (match-string 8) + (if cc-imenu-c-prototype-macro-regexp + (concat + "\\|" + (car (cdr (nth 3 cc-imenu-c++-generic-expression))) ; -> index += 1 + (prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 10) "") + ) + (prog2 (setq cc-imenu-objc-generic-expression-objc-base-index 9) "") + "") ; -> index += 0 + (prog2 (setq cc-imenu-objc-generic-expression-proto-index 9) "") + ;; + ;; For Objective-C + ;; Pick a token by (match-string 8 or 9) + ;; + "\\|\\(" + "^[-+][:" c-alnum "()*_<>\n\t ]*[;{]" ; Methods + "\\|" + "^@interface[\t ]+[" c-alnum "_]+[\t ]*:" + "\\|" + "^@interface[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)" + "\\|" + ;; For NSObject, NSProxy and Object... They don't have super class. + "^@interface[\t ]+[" c-alnum "_]+[\t ]*.*$" + "\\|" + "^@implementation[\t ]+[" c-alnum "_]+[\t ]*([" c-alnum "_]+)" + "\\|" + "^@implementation[\t ]+[" c-alnum "_]+" + "\\|" + "^@protocol[\t ]+[" c-alnum "_]+" "\\)") + "Imenu generic expression for ObjC mode. See `imenu-generic-expression'.") + + +;; Imenu support for objective-c uses functions. +(defsubst cc-imenu-objc-method-to-selector (method) + "Return the objc selector style string of METHOD. +Example: +- perform: (SEL)aSelector withObject: object1 withObject: object2; /* METHOD */ +=> +-perform:withObject:withObject:withObject: /* selector */" + (let ((return "") ; String to be returned + (p 0) ; Current scanning position in METHOD + (pmax (length method)) ; + char ; Current scanning target + (betweenparen 0) ; CHAR is in parentheses. + argreq ; An argument is required. + inargvar) ; position of CHAR is in an argument variable. + (while (< p pmax) + (setq char (aref method p) + p (1+ p)) + (cond + ;; Is CHAR part of a objc token? + ((and (not inargvar) ; Ignore if CHAR is part of an argument variable. + (eq 0 betweenparen) ; Ignore if CHAR is in parentheses. + (or (and (<= ?a char) (<= char ?z)) + (and (<= ?A char) (<= char ?Z)) + (and (<= ?0 char) (<= char ?9)) + (= ?_ char))) + (if argreq + (setq inargvar t + argreq nil) + (setq return (concat return (char-to-string char))))) + ;; Or a white space? + ((and inargvar (or (eq ?\ char) (eq ?\n char)) + (setq inargvar nil))) + ;; Or a method separator? + ;; If a method separator, the next token will be an argument variable. + ((eq ?: char) + (setq argreq t + return (concat return (char-to-string char)))) + ;; Or an open parentheses? + ((eq ?\( char) + (setq betweenparen (1+ betweenparen))) + ;; Or a close parentheses? + ((eq ?\) char) + (setq betweenparen (1- betweenparen))))) + return)) + +(defun cc-imenu-objc-remove-white-space (str) + "Remove all spaces and tabs from STR." + (let ((return "") + (p 0) + (max (length str)) + char) + (while (< p max) + (setq char (aref str p)) + (setq p (1+ p)) + (if (or (= char ?\ ) (= char ?\t)) + () + (setq return (concat return (char-to-string char))))) + return)) + +(defun cc-imenu-objc-function () + "imenu supports for objc-mode." + (let (methodlist + clist + ;; + ;; OBJC, Cnoreturn, Cgeneralfunc, Cproto are constants. + ;; + ;; *Warning for developers* + ;; These constants depend on `cc-imenu-c++-generic-expression'. + ;; + (OBJC cc-imenu-objc-generic-expression-objc-base-index) + ;; Special case to match a line like `main() {}' + (Cnoreturn cc-imenu-objc-generic-expression-noreturn-index) + ;; General function name regexp + (Cgeneralfunc cc-imenu-objc-generic-expression-general-func-index) + ;; Special case for definitions using phony prototype macros like: + (Cproto cc-imenu-objc-generic-expression-proto-index) + langnum + ;; + (classcount 0) + toplist + str + str2 + (intflen (length "@interface")) + (implen (length "@implementation")) + (prtlen (length "@protocol")) + (func + ;; + ;; Does this emacs has buffer-substring-no-properties? + ;; + (if (fboundp 'buffer-substring-no-properties) + 'buffer-substring-no-properties + 'buffer-substring))) + (goto-char (point-max)) + ;; + (while (re-search-backward cc-imenu-objc-generic-expression nil t) + (setq langnum (if (match-beginning OBJC) + OBJC + (cond + ((match-beginning Cproto) Cproto) + ((match-beginning Cgeneralfunc) Cgeneralfunc) + ((match-beginning Cnoreturn) Cnoreturn)))) + (setq str (funcall func (match-beginning langnum) (match-end langnum))) + ;; + (cond + ;; + ;; C + ;; + ((not (eq langnum OBJC)) + (setq clist (cons (cons str (match-beginning langnum)) clist))) + ;; + ;; ObjC + ;; + ;; An instance Method + ((eq (aref str 0) ?-) + (setq str (concat "-" (cc-imenu-objc-method-to-selector str))) + (setq methodlist (cons (cons str + (match-beginning langnum)) + methodlist))) + ;; A factory Method + ((eq (aref str 0) ?+) + (setq str (concat "+" (cc-imenu-objc-method-to-selector str))) + (setq methodlist (cons (cons str + (match-beginning langnum)) + methodlist))) + ;; Interface or implementation or protocol + ((eq (aref str 0) ?@) + (setq classcount (1+ classcount)) + (cond + ((and (> (length str) implen) + (string= (substring str 0 implen) "@implementation")) + (setq str (substring str implen) + str2 "@implementation")) + ((string= (substring str 0 intflen) "@interface") + (setq str (substring str intflen) + str2 "@interface")) + ((string= (substring str 0 prtlen) "@protocol") + (setq str (substring str prtlen) + str2 "@protocol"))) + (setq str (cc-imenu-objc-remove-white-space str)) + (setq methodlist (cons (cons str2 + (match-beginning langnum)) + methodlist)) + (setq toplist (cons nil (cons (cons str + methodlist) toplist)) + methodlist nil)))) + ;; + (if (eq (car toplist) nil) + (setq toplist (cdr toplist))) + + ;; In this buffer, there is only one or zero @{interface|implementation|protocol}. + (if (< classcount 2) + (let ((classname (car (car toplist))) + (p (cdr (car (cdr (car toplist))))) + last) + (setq toplist (cons (cons classname p) (cdr (cdr (car toplist))))) + ;; Add C lang token + (if clist + (progn + (setq last toplist) + (while (cdr last) + (setq last (cdr last))) + (setcdr last clist)))) + ;; Add C lang tokens as a sub menu + (if clist + (setq toplist (cons (cons "C" clist) toplist)))) + ;; + toplist + )) + +;(defvar cc-imenu-pike-generic-expression +; ()) +; FIXME: Please contribute one! + +(defun cc-imenu-init (mode-generic-expression + &optional mode-create-index-function) + (setq imenu-generic-expression mode-generic-expression + imenu-case-fold-search nil) + (when mode-create-index-function + (setq imenu-create-index-function mode-create-index-function))) + + +(cc-provide 'cc-menus) + +;;; arch-tag: f6b60933-91f0-4145-ab44-70ca6d1b919b +;;; cc-menus.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-mode-5.32.3.tar b/site-lisp/cc-mode/5.32.3/cc-mode-5.32.3.tar new file mode 100644 index 0000000..26546d7 Binary files /dev/null and b/site-lisp/cc-mode/5.32.3/cc-mode-5.32.3.tar differ diff --git a/site-lisp/cc-mode/5.32.3/cc-mode.el b/site-lisp/cc-mode/5.32.3/cc-mode.el new file mode 100644 index 0000000..3a7b302 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-mode.el @@ -0,0 +1,1834 @@ +;;; cc-mode.el --- major mode for editing C and similar languages + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2003- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: a long, long, time ago. adapted from the original c-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; NOTE: Read the commentary below for the right way to submit bug reports! +;; NOTE: See the accompanying texinfo manual for details on using this mode! +;; Note: The version string is in cc-defs. + +;; This package provides GNU Emacs major modes for editing C, C++, +;; Objective-C, Java, CORBA's IDL, Pike and AWK code. As of the +;; latest Emacs and XEmacs releases, it is the default package for +;; editing these languages. This package is called "CC Mode", and +;; should be spelled exactly this way. + +;; CC Mode supports K&R and ANSI C, ANSI C++, Objective-C, Java, +;; CORBA's IDL, Pike and AWK with a consistent indentation model +;; across all modes. This indentation model is intuitive and very +;; flexible, so that almost any desired style of indentation can be +;; supported. Installation, usage, and programming details are +;; contained in an accompanying texinfo manual. + +;; CC Mode's immediate ancestors were, c++-mode.el, cplus-md.el, and +;; cplus-md1.el.. + +;; To submit bug reports, type "C-c C-b". These will be sent to +;; bug-gnu-emacs@gnu.org (mirrored as the Usenet newsgroup +;; gnu.emacs.bug) as well as bug-cc-mode@gnu.org, which directly +;; contacts the CC Mode maintainers. Questions can sent to +;; help-gnu-emacs@gnu.org (mirrored as gnu.emacs.help) and/or +;; bug-cc-mode@gnu.org. Please do not send bugs or questions to our +;; personal accounts; we reserve the right to ignore such email! + +;; Many, many thanks go out to all the folks on the beta test list. +;; Without their patience, testing, insight, code contributions, and +;; encouragement CC Mode would be a far inferior package. + +;; You can get the latest version of CC Mode, including PostScript +;; documentation and separate individual files from: +;; +;; http://cc-mode.sourceforge.net/ +;; +;; You can join a moderated CC Mode announcement-only mailing list by +;; visiting +;; +;; http://lists.sourceforge.net/mailman/listinfo/cc-mode-announce + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require-when-compile 'cc-langs) +(cc-require 'cc-vars) +(cc-require 'cc-engine) +(cc-require 'cc-styles) +(cc-require 'cc-cmds) +(cc-require 'cc-align) +(cc-require 'cc-menus) +(cc-require 'cc-guess) + +;; Silence the compiler. +(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs +(cc-bytecomp-defun set-keymap-parents) ; XEmacs +(cc-bytecomp-defun run-mode-hooks) ; Emacs 21.1 +(cc-bytecomp-obsolete-fun make-local-hook) ; Marked obsolete in Emacs 21.1. +(cc-bytecomp-defvar normal-erase-is-backspace) +(cc-bytecomp-defvar file-local-variables-alist) +(cc-bytecomp-defvar dir-local-variables-alist) + +;; We set these variables during mode init, yet we don't require +;; font-lock. +(cc-bytecomp-defvar font-lock-defaults) +(cc-bytecomp-defvar font-lock-syntactic-keywords) + +;; Menu support for both XEmacs and Emacs. If you don't have easymenu +;; with your version of Emacs, you are incompatible! +(cc-external-require 'easymenu) + +;; Autoload directive for emacsen that doesn't have an older CC Mode +;; version in the dist. +(autoload 'c-subword-mode "cc-subword" + "Mode enabling subword movement and editing keys." t) + +;; Load cc-fonts first after font-lock is loaded, since it isn't +;; necessary until font locking is requested. +(eval-after-load "font-lock" + '(require 'cc-fonts)) + + +;; Other modes and packages which depend on CC Mode should do the +;; following to make sure everything is loaded and available for their +;; use: +;; +;; (require 'cc-mode) +;; +;; And in the major mode function: +;; +;; (c-initialize-cc-mode t) +;; (c-init-language-vars some-mode) +;; (c-common-init 'some-mode) ; Or perhaps (c-basic-common-init 'some-mode) +;; +;; If you're not writing a derived mode using the language variable +;; system, then some-mode is one of the language modes directly +;; supported by CC Mode. You can then use (c-init-language-vars-for +;; 'some-mode) instead of `c-init-language-vars'. +;; `c-init-language-vars-for' is a function that avoids the rather +;; large expansion of `c-init-language-vars'. +;; +;; If you use `c-basic-common-init' then you might want to call +;; `c-font-lock-init' too to set up CC Mode's font lock support. +;; +;; See cc-langs.el for further info. A small example of a derived mode +;; is also available at . + +(defun c-leave-cc-mode-mode () + (setq c-buffer-is-cc-mode nil)) + +(defun c-init-language-vars-for (mode) + "Initialize the language variables for one of the language modes +directly supported by CC Mode. This can be used instead of the +`c-init-language-vars' macro if the language you want to use is one of +those, rather than a derived language defined through the language +variable system (see \"cc-langs.el\")." + (cond ((eq mode 'c-mode) (c-init-language-vars c-mode)) + ((eq mode 'c++-mode) (c-init-language-vars c++-mode)) + ((eq mode 'objc-mode) (c-init-language-vars objc-mode)) + ((eq mode 'java-mode) (c-init-language-vars java-mode)) + ((eq mode 'idl-mode) (c-init-language-vars idl-mode)) + ((eq mode 'pike-mode) (c-init-language-vars pike-mode)) + ((eq mode 'awk-mode) (c-init-language-vars awk-mode)) + (t (error "Unsupported mode %s" mode)))) + +;;;###autoload +(defun c-initialize-cc-mode (&optional new-style-init) + "Initialize CC Mode for use in the current buffer. +If the optional NEW-STYLE-INIT is nil or left out then all necessary +initialization to run CC Mode for the C language is done. Otherwise +only some basic setup is done, and a call to `c-init-language-vars' or +`c-init-language-vars-for' is necessary too (which gives more +control). See \"cc-mode.el\" for more info." + + (setq c-buffer-is-cc-mode t) + + (let ((initprop 'cc-mode-is-initialized) + c-initialization-ok) + (unless (get 'c-initialize-cc-mode initprop) + (unwind-protect + (progn + (put 'c-initialize-cc-mode initprop t) + (c-initialize-builtin-style) + (run-hooks 'c-initialization-hook) + ;; Fix obsolete variables. + (if (boundp 'c-comment-continuation-stars) + (setq c-block-comment-prefix c-comment-continuation-stars)) + (add-hook 'change-major-mode-hook 'c-leave-cc-mode-mode) + (setq c-initialization-ok t)) + ;; Will try initialization hooks again if they failed. + (put 'c-initialize-cc-mode initprop c-initialization-ok)))) + + (unless new-style-init + (c-init-language-vars-for 'c-mode))) + + +;;; Common routines. + +(defvar c-mode-base-map () + "Keymap shared by all CC Mode related modes.") + +(defun c-make-inherited-keymap () + (let ((map (make-sparse-keymap))) + ;; Necessary to use `cc-bytecomp-fboundp' below since this + ;; function is called from top-level forms that are evaluated + ;; while cc-bytecomp is active when one does M-x eval-buffer. + (cond + ;; XEmacs + ((cc-bytecomp-fboundp 'set-keymap-parents) + (set-keymap-parents map c-mode-base-map)) + ;; Emacs + ((cc-bytecomp-fboundp 'set-keymap-parent) + (set-keymap-parent map c-mode-base-map)) + ;; incompatible + (t (error "CC Mode is incompatible with this version of Emacs"))) + map)) + +(defun c-define-abbrev-table (name defs) + ;; Compatibility wrapper for `define-abbrev' which passes a non-nil + ;; sixth argument for SYSTEM-FLAG in emacsen that support it + ;; (currently only Emacs >= 21.2). + (let ((table (or (symbol-value name) + (progn (define-abbrev-table name nil) + (symbol-value name))))) + (while defs + (condition-case nil + (apply 'define-abbrev table (append (car defs) '(t))) + (wrong-number-of-arguments + (apply 'define-abbrev table (car defs)))) + (setq defs (cdr defs))))) +(put 'c-define-abbrev-table 'lisp-indent-function 1) + +(defun c-bind-special-erase-keys () + ;; Only used in Emacs to bind C-c C- and C-c C- + ;; to the proper keys depending on `normal-erase-is-backspace'. + (if normal-erase-is-backspace + (progn + (define-key c-mode-base-map (kbd "C-c C-") + 'c-hungry-delete-forward) + (define-key c-mode-base-map (kbd "C-c C-") + 'c-hungry-delete-backwards)) + (define-key c-mode-base-map (kbd "C-c C-") + 'c-hungry-delete-backwards) + (define-key c-mode-base-map (kbd "C-c C-") + 'c-hungry-delete-forward))) + +(if c-mode-base-map + nil + + (setq c-mode-base-map (make-sparse-keymap)) + + ;; Separate M-BS from C-M-h. The former should remain + ;; backward-kill-word. + (define-key c-mode-base-map [(control meta h)] 'c-mark-function) + (define-key c-mode-base-map "\e\C-q" 'c-indent-exp) + (substitute-key-definition 'backward-sentence + 'c-beginning-of-statement + c-mode-base-map global-map) + (substitute-key-definition 'forward-sentence + 'c-end-of-statement + c-mode-base-map global-map) + (substitute-key-definition 'indent-new-comment-line + 'c-indent-new-comment-line + c-mode-base-map global-map) + (substitute-key-definition 'indent-for-tab-command + 'c-indent-command + c-mode-base-map global-map) + (when (fboundp 'comment-indent-new-line) + ;; indent-new-comment-line has changed name to + ;; comment-indent-new-line in Emacs 21. + (substitute-key-definition 'comment-indent-new-line + 'c-indent-new-comment-line + c-mode-base-map global-map)) + + ;; RMS says don't make these the default. + ;; (April 2006): RMS has now approved these commands as defaults. + (unless (memq 'argumentative-bod-function c-emacs-features) + (define-key c-mode-base-map "\e\C-a" 'c-beginning-of-defun) + (define-key c-mode-base-map "\e\C-e" 'c-end-of-defun)) + + (define-key c-mode-base-map "\C-c\C-n" 'c-forward-conditional) + (define-key c-mode-base-map "\C-c\C-p" 'c-backward-conditional) + (define-key c-mode-base-map "\C-c\C-u" 'c-up-conditional) + + ;; It doesn't suffice to put `c-fill-paragraph' on + ;; `fill-paragraph-function' since `c-fill-paragraph' must be called + ;; before any fill prefix adaption is done. E.g. `filladapt-mode' + ;; replaces `fill-paragraph' and does the adaption before calling + ;; `fill-paragraph-function', and we have to mask comments etc + ;; before that. Also, `c-fill-paragraph' chains on to + ;; `fill-paragraph' and the value on `fill-parapgraph-function' to + ;; do the actual filling work. + (substitute-key-definition 'fill-paragraph 'c-fill-paragraph + c-mode-base-map global-map) + ;; In XEmacs the default fill function is called + ;; fill-paragraph-or-region. + (substitute-key-definition 'fill-paragraph-or-region 'c-fill-paragraph + c-mode-base-map global-map) + + ;; We bind the forward deletion key and (implicitly) C-d to + ;; `c-electric-delete-forward', and the backward deletion key to + ;; `c-electric-backspace'. The hungry variants are bound to the + ;; same keys but prefixed with C-c. This implies that C-c C-d is + ;; `c-hungry-delete-forward'. For consistency, we bind not only C-c + ;; to `c-hungry-delete-backwards' but also + ;; C-c C-, so that the Ctrl key can be held down during + ;; the whole sequence regardless of the direction. This in turn + ;; implies that we bind C-c C- to `c-hungry-delete-forward', + ;; for the same reason. + + ;; Bind the electric deletion functions to C-d and DEL. Emacs 21 + ;; automatically maps the [delete] and [backspace] keys to these two + ;; depending on window system and user preferences. (In earlier + ;; versions it's possible to do the same by using `function-key-map'.) + (define-key c-mode-base-map "\C-d" 'c-electric-delete-forward) + (define-key c-mode-base-map "\177" 'c-electric-backspace) + (define-key c-mode-base-map "\C-c\C-d" 'c-hungry-delete-forward) + (define-key c-mode-base-map [?\C-c ?\d] 'c-hungry-delete-backwards) + (define-key c-mode-base-map [?\C-c ?\C-\d] 'c-hungry-delete-backwards) + (define-key c-mode-base-map [?\C-c deletechar] 'c-hungry-delete-forward) ; C-c on a tty. + (define-key c-mode-base-map [?\C-c (control deletechar)] ; C-c C- on a tty. + 'c-hungry-delete-forward) + (when (boundp 'normal-erase-is-backspace) + ;; The automatic C-d and DEL mapping functionality doesn't extend + ;; to special combinations like C-c C-, so we have to hook + ;; into the `normal-erase-is-backspace' system to bind it directly + ;; as appropriate. + (add-hook 'normal-erase-is-backspace-hook 'c-bind-special-erase-keys) + (c-bind-special-erase-keys)) + + (when (fboundp 'delete-forward-p) + ;; In XEmacs we fix the forward and backward deletion behavior by + ;; binding the keysyms for the [delete] and [backspace] keys + ;; directly, and use `delete-forward-p' to decide what [delete] + ;; should do. That's done in the XEmacs specific + ;; `c-electric-delete' and `c-hungry-delete' functions. + (define-key c-mode-base-map [delete] 'c-electric-delete) + (define-key c-mode-base-map [backspace] 'c-electric-backspace) + (define-key c-mode-base-map (kbd "C-c ") 'c-hungry-delete) + (define-key c-mode-base-map (kbd "C-c C-") 'c-hungry-delete) + (define-key c-mode-base-map (kbd "C-c ") + 'c-hungry-delete-backwards) + (define-key c-mode-base-map (kbd "C-c C-") + 'c-hungry-delete-backwards)) + + (define-key c-mode-base-map "#" 'c-electric-pound) + (define-key c-mode-base-map "{" 'c-electric-brace) + (define-key c-mode-base-map "}" 'c-electric-brace) + (define-key c-mode-base-map "/" 'c-electric-slash) + (define-key c-mode-base-map "*" 'c-electric-star) + (define-key c-mode-base-map ";" 'c-electric-semi&comma) + (define-key c-mode-base-map "," 'c-electric-semi&comma) + (define-key c-mode-base-map ":" 'c-electric-colon) + (define-key c-mode-base-map "(" 'c-electric-paren) + (define-key c-mode-base-map ")" 'c-electric-paren) + + (define-key c-mode-base-map "\C-c\C-\\" 'c-backslash-region) + (define-key c-mode-base-map "\C-c\C-a" 'c-toggle-auto-newline) + (define-key c-mode-base-map "\C-c\C-b" 'c-submit-bug-report) + (define-key c-mode-base-map "\C-c\C-c" 'comment-region) + (define-key c-mode-base-map "\C-c\C-l" 'c-toggle-electric-state) + (define-key c-mode-base-map "\C-c\C-o" 'c-set-offset) + (define-key c-mode-base-map "\C-c\C-q" 'c-indent-defun) + (define-key c-mode-base-map "\C-c\C-s" 'c-show-syntactic-information) + ;; (define-key c-mode-base-map "\C-c\C-t" 'c-toggle-auto-hungry-state) Commented out by ACM, 2005-03-05. + (define-key c-mode-base-map "\C-c." 'c-set-style) + ;; conflicts with OOBR + ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) + ;; (define-key c-mode-base-map "\C-c\C-y" 'c-toggle-hungry-state) Commented out by ACM, 2005-11-22. + (define-key c-mode-base-map "\C-c\C-w" 'c-subword-mode) + ) + +;; We don't require the outline package, but we configure it a bit anyway. +(cc-bytecomp-defvar outline-level) + +(defun c-mode-menu (modestr) + "Return a menu spec suitable for `easy-menu-define' that is exactly +like the C mode menu except that the menu bar item name is MODESTR +instead of \"C\". + +This function is provided for compatibility only; derived modes should +preferably use the `c-mode-menu' language constant directly." + (cons modestr (c-lang-const c-mode-menu c))) + +;; Ugly hack to pull in the definition of `c-populate-syntax-table' +;; from cc-langs to make it available at runtime. It's either this or +;; moving the definition for it to cc-defs, but that would mean to +;; break up the syntax table setup over two files. +(defalias 'c-populate-syntax-table + (cc-eval-when-compile + (let ((f (symbol-function 'c-populate-syntax-table))) + (if (byte-code-function-p f) f (byte-compile f))))) + +;; CAUTION: Try to avoid installing things on +;; `before-change-functions'. The macro `combine-after-change-calls' +;; is used and it doesn't work if there are things on that hook. That +;; can cause font lock functions to run in inconvenient places during +;; temporary changes in some font lock support modes, causing extra +;; unnecessary work and font lock glitches due to interactions between +;; various text properties. +;; +;; (2007-02-12): The macro `combine-after-change-calls' ISN'T used any +;; more. + +(defun c-unfind-enclosing-token (pos) + ;; If POS is wholly inside a token, remove that id from + ;; `c-found-types', should it be present. Return t if we were in an + ;; id, else nil. + (save-excursion + (let ((tok-beg (progn (goto-char pos) + (and (c-beginning-of-current-token) (point)))) + (tok-end (progn (goto-char pos) + (and (c-end-of-current-token) (point))))) + (when (and tok-beg tok-end) + (c-unfind-type (buffer-substring-no-properties tok-beg tok-end)) + t)))) + +(defun c-unfind-coalesced-tokens (beg end) + ;; unless the non-empty region (beg end) is entirely WS and there's at + ;; least one character of WS just before or after this region, remove + ;; the tokens which touch the region from `c-found-types' should they + ;; be present. + (or (c-partial-ws-p beg end) + (save-excursion + (progn + (goto-char beg) + (or (eq beg (point-min)) + (c-skip-ws-backward (1- beg)) + (/= (point) beg) + (= (c-backward-token-2) 1) + (c-unfind-type (buffer-substring-no-properties + (point) beg))) + (goto-char end) + (or (eq end (point-max)) + (c-skip-ws-forward (1+ end)) + (/= (point) end) + (progn (forward-char) (c-end-of-current-token) nil) + (c-unfind-type (buffer-substring-no-properties + end (point)))))))) + +;; c-maybe-stale-found-type records a place near the region being +;; changed where an element of `found-types' might become stale. It +;; is set in c-before-change and is either nil, or has the form: +;; +;; (c-decl-id-start "foo" 97 107 " (* ooka) " "o"), where +;; +;; o - `c-decl-id-start' is the c-type text property value at buffer +;; pos 96. +;; +;; o - 97 107 is the region potentially containing the stale type - +;; this is delimited by a non-nil c-type text property at 96 and +;; either another one or a ";", "{", or "}" at 107. +;; +;; o - " (* ooka) " is the (before change) buffer portion containing +;; the suspect type (here "ooka"). +;; +;; o - "o" is the buffer contents which is about to be deleted. This +;; would be the empty string for an insertion. +(defvar c-maybe-stale-found-type nil) +(make-variable-buffer-local 'c-maybe-stale-found-type) + +(defvar c-just-done-before-change nil) +(make-variable-buffer-local 'c-just-done-before-change) +;; This variable is set to t by `c-before-change' and to nil by +;; `c-after-change'. It is used to detect a spurious invocation of +;; `before-change-functions' directly following on from a correct one. This +;; happens in some Emacsen, for example when `basic-save-buffer' does (insert +;; ?\n) when `require-final-newline' is non-nil. + +(defun c-basic-common-init (mode default-style) + "Do the necessary initialization for the syntax handling routines +and the line breaking/filling code. Intended to be used by other +packages that embed CC Mode. + +MODE is the CC Mode flavor to set up, e.g. 'c-mode or 'java-mode. +DEFAULT-STYLE tells which indentation style to install. It has the +same format as `c-default-style'. + +Note that `c-init-language-vars' must be called before this function. +This function cannot do that since `c-init-language-vars' is a macro +that requires a literal mode spec at compile time." + + (setq c-buffer-is-cc-mode mode) + + ;; these variables should always be buffer local; they do not affect + ;; indentation style. + (make-local-variable 'parse-sexp-ignore-comments) + (make-local-variable 'indent-line-function) + (make-local-variable 'indent-region-function) + (make-local-variable 'normal-auto-fill-function) + (make-local-variable 'comment-start) + (make-local-variable 'comment-end) + (make-local-variable 'comment-start-skip) + (make-local-variable 'comment-multi-line) + (make-local-variable 'comment-line-break-function) + (make-local-variable 'paragraph-start) + (make-local-variable 'paragraph-separate) + (make-local-variable 'paragraph-ignore-fill-prefix) + (make-local-variable 'adaptive-fill-mode) + (make-local-variable 'adaptive-fill-regexp) + (make-local-variable 'fill-paragraph-handle-comment) + + ;; now set their values + (setq parse-sexp-ignore-comments t + indent-line-function 'c-indent-line + indent-region-function 'c-indent-region + normal-auto-fill-function 'c-do-auto-fill + comment-multi-line t + comment-line-break-function 'c-indent-new-comment-line) + + ;; For the benefit of adaptive file, which otherwise mis-fills. + (setq fill-paragraph-handle-comment nil) + + ;; Install `c-fill-paragraph' on `fill-paragraph-function' so that a + ;; direct call to `fill-paragraph' behaves better. This still + ;; doesn't work with filladapt but it's better than nothing. + (make-local-variable 'fill-paragraph-function) + (setq fill-paragraph-function 'c-fill-paragraph) + + ;; Initialise the cache of brace pairs, and opening braces/brackets/parens. + (c-state-cache-init) + + (when (or c-recognize-<>-arglists + (c-major-mode-is 'awk-mode) + (c-major-mode-is '(java-mode c-mode c++-mode objc-mode))) + ;; We'll use the syntax-table text property to change the syntax + ;; of some chars for this language, so do the necessary setup for + ;; that. + ;; + ;; Note to other package developers: It's ok to turn this on in CC + ;; Mode buffers when CC Mode doesn't, but it's not ok to turn it + ;; off if CC Mode has turned it on. + + ;; Emacs. + (when (boundp 'parse-sexp-lookup-properties) + (make-local-variable 'parse-sexp-lookup-properties) + (setq parse-sexp-lookup-properties t)) + + ;; Same as above for XEmacs. + (when (boundp 'lookup-syntax-properties) + (make-local-variable 'lookup-syntax-properties) + (setq lookup-syntax-properties t))) + + ;; Use this in Emacs 21+ to avoid meddling with the rear-nonsticky + ;; property on each character. + (when (boundp 'text-property-default-nonsticky) + (make-local-variable 'text-property-default-nonsticky) + (mapc (lambda (tprop) + (unless (assq tprop text-property-default-nonsticky) + (setq text-property-default-nonsticky + (cons `(,tprop . t) text-property-default-nonsticky)))) + '(syntax-table category c-type))) + + ;; In Emacs 21 and later it's possible to turn off the ad-hoc + ;; heuristic that open parens in column 0 are defun starters. Since + ;; we have c-state-cache, that heuristic isn't useful and only causes + ;; trouble, so turn it off. +;; (when (memq 'col-0-paren c-emacs-features) +;; (make-local-variable 'open-paren-in-column-0-is-defun-start) +;; (setq open-paren-in-column-0-is-defun-start nil)) + + (c-clear-found-types) + + ;; now set the mode style based on default-style + (let ((style (cc-choose-style-for-mode mode default-style))) + ;; Override style variables if `c-old-style-variable-behavior' is + ;; set. Also override if we are using global style variables, + ;; have already initialized a style once, and are switching to a + ;; different style. (It's doubtful whether this is desirable, but + ;; the whole situation with nonlocal style variables is a bit + ;; awkward. It's at least the most compatible way with the old + ;; style init procedure.) + (c-set-style style (not (or c-old-style-variable-behavior + (and (not c-style-variables-are-local-p) + c-indentation-style + (not (string-equal c-indentation-style + style))))))) + (c-setup-paragraph-variables) + + ;; we have to do something special for c-offsets-alist so that the + ;; buffer local value has its own alist structure. + (setq c-offsets-alist (copy-alist c-offsets-alist)) + + ;; setup the comment indent variable in a Emacs version portable way + (make-local-variable 'comment-indent-function) + (setq comment-indent-function 'c-comment-indent) + +;; ;; Put submode indicators onto minor-mode-alist, but only once. +;; (or (assq 'c-submode-indicators minor-mode-alist) +;; (setq minor-mode-alist +;; (cons '(c-submode-indicators c-submode-indicators) +;; minor-mode-alist))) + (c-update-modeline) + + ;; Install the functions that ensure that various internal caches + ;; don't become invalid due to buffer changes. + (or (memq 'add-hook-local c-emacs-features) + (make-local-hook 'before-change-functions)) + (add-hook 'before-change-functions 'c-before-change nil t) + (setq c-just-done-before-change nil) + (or (memq 'add-hook-local c-emacs-features) + (make-local-hook 'after-change-functions)) + (add-hook 'after-change-functions 'c-after-change nil t) + (when (boundp 'font-lock-extend-after-change-region-function) + (set (make-local-variable 'font-lock-extend-after-change-region-function) + 'c-extend-after-change-region))) ; Currently (2009-05) used by all + ; lanaguages with #define (C, C++,; ObjC), and by AWK. + +(defun c-setup-doc-comment-style () + "Initialize the variables that depend on the value of `c-doc-comment-style'." + (when (and (featurep 'font-lock) + (symbol-value 'font-lock-mode)) + ;; Force font lock mode to reinitialize itself. + (font-lock-mode 0) + (font-lock-mode 1))) + +(defun c-common-init (&optional mode) + "Common initialization for all CC Mode modes. +In addition to the work done by `c-basic-common-init' and +`c-font-lock-init', this function sets up various other things as +customary in CC Mode modes but which aren't strictly necessary for CC +Mode to operate correctly. + +MODE is the symbol for the mode to initialize, like 'c-mode. See +`c-basic-common-init' for details. It's only optional to be +compatible with old code; callers should always specify it." + + (unless mode + ;; Called from an old third party package. The fallback is to + ;; initialize for C. + (c-init-language-vars-for 'c-mode)) + + (c-basic-common-init mode c-default-style) + (when mode + ;; Only initialize font locking if we aren't called from an old package. + (c-font-lock-init)) + + ;; Starting a mode is a sort of "change". So call the change functions... + (save-restriction + (widen) + (setq c-new-BEG (point-min)) + (setq c-new-END (point-max)) + (save-excursion + (mapc (lambda (fn) + (funcall fn (point-min) (point-max))) + c-get-state-before-change-functions) + (mapc (lambda (fn) + (funcall fn (point-min) (point-max) + (- (point-max) (point-min)))) + c-before-font-lock-functions))) + + (make-local-variable 'outline-regexp) + (make-local-variable 'outline-level) + (setq outline-regexp "[^#\n\^M]" + outline-level 'c-outline-level) + + (let ((rfn (assq mode c-require-final-newline))) + (when rfn + (make-local-variable 'require-final-newline) + (setq require-final-newline (cdr rfn))))) + +(defun c-count-cfss (lv-alist) + ;; LV-ALIST is an alist like `file-local-variables-alist'. Count how many + ;; elements with the key `c-file-style' there are in it. + (let ((elt-ptr lv-alist) elt (cownt 0)) + (while elt-ptr + (setq elt (car elt-ptr) + elt-ptr (cdr elt-ptr)) + (when (eq (car elt) 'c-file-style) + (setq cownt (1+ cownt)))) + cownt)) + +(defun c-before-hack-hook () + "Set the CC Mode style and \"offsets\" when in the buffer's local variables. +They are set only when, respectively, the pseudo variables +`c-file-style' and `c-file-offsets' are present in the list. + +This function is called from the hook `before-hack-local-variables-hook'." + (when c-buffer-is-cc-mode + (let ((mode-cons (assq 'mode file-local-variables-alist)) + (stile (cdr (assq 'c-file-style file-local-variables-alist))) + (offsets (cdr (assq 'c-file-offsets file-local-variables-alist)))) + (when mode-cons + (hack-one-local-variable (car mode-cons) (cdr mode-cons)) + (setq file-local-variables-alist + (delq mode-cons file-local-variables-alist))) + (when stile + (or (stringp stile) (error "c-file-style is not a string")) + (if (boundp 'dir-local-variables-alist) + ;; Determine whether `c-file-style' was set in the file's local + ;; variables or in a .dir-locals.el (a directory setting). + (let ((cfs-in-file-and-dir-count + (c-count-cfss file-local-variables-alist)) + (cfs-in-dir-count (c-count-cfss dir-local-variables-alist))) + (c-set-style stile + (= cfs-in-file-and-dir-count cfs-in-dir-count))) + (c-set-style stile))) + (when offsets + (mapc + (lambda (langentry) + (let ((langelem (car langentry)) + (offset (cdr langentry))) + (c-set-offset langelem offset))) + offsets))))) + +(defun c-remove-any-local-eval-or-mode-variables () + ;; If the buffer specifies `mode' or `eval' in its File Local Variable list + ;; or on the first line, remove all occurrences. See + ;; `c-postprocess-file-styles' for justification. There is no need to save + ;; point here, or even bother too much about the buffer contents. However, + ;; DON'T mess up the kill-ring. + ;; + ;; Most of the code here is derived from Emacs 21.3's `hack-local-variables' + ;; in files.el. + (goto-char (point-max)) + (search-backward "\n\^L" (max (- (point-max) 3000) (point-min)) 'move) + (let (lv-point (prefix "") (suffix "")) + (when (let ((case-fold-search t)) + (search-forward "Local Variables:" nil t)) + (setq lv-point (point)) + ;; The prefix is what comes before "local variables:" in its line. + ;; The suffix is what comes after "local variables:" in its line. + (skip-chars-forward " \t") + (or (eolp) + (setq suffix (buffer-substring (point) + (progn (end-of-line) (point))))) + (goto-char (match-beginning 0)) + (or (bolp) + (setq prefix + (buffer-substring (point) + (progn (beginning-of-line) (point))))) + + (while (search-forward-regexp + (concat "^[ \t]*" + (regexp-quote prefix) + "\\(mode\\|eval\\):.*" + (regexp-quote suffix) + "$") + nil t) + (forward-line 0) + (delete-region (point) (progn (forward-line) (point))))) + + ;; Delete the first line, if we've got one, in case it contains a mode spec. + (unless (and lv-point + (progn (goto-char lv-point) + (forward-line 0) + (bobp))) + (goto-char (point-min)) + (unless (eobp) + (delete-region (point) (progn (forward-line) (point))))))) + +(defun c-postprocess-file-styles () + "Function that post processes relevant file local variables in CC Mode. +Currently, this function simply applies any style and offset settings +found in the file's Local Variable list. It first applies any style +setting found in `c-file-style', then it applies any offset settings +it finds in `c-file-offsets'. + +Note that the style variables are always made local to the buffer." + + ;; apply file styles and offsets + (when c-buffer-is-cc-mode + (if (or c-file-style c-file-offsets) + (c-make-styles-buffer-local t)) + (when c-file-style + (or (stringp c-file-style) + (error "c-file-style is not a string")) + (c-set-style c-file-style ;t + )) + + (and c-file-offsets + (mapc + (lambda (langentry) + (let ((langelem (car langentry)) + (offset (cdr langentry))) + (c-set-offset langelem offset))) + c-file-offsets)) + ;; Problem: The file local variable block might have explicitly set a + ;; style variable. The `c-set-style' or `mapcar' call might have + ;; overwritten this. So we run `hack-local-variables' again to remedy + ;; this. There are no guarantees this will work properly, particularly as + ;; we have no control over what the other hook functions on + ;; `hack-local-variables-hook' would have done. We now (2006/2/1) remove + ;; any `eval' or `mode' expressions before we evaluate again (see below). + ;; ACM, 2005/11/2. + ;; + ;; Problem (bug reported by Gustav Broberg): if one of the variables is + ;; `mode', this will invoke c-mode (etc.) again, setting up the style etc. + ;; We prevent this by temporarily removing `mode' from the Local Variables + ;; section. + (if (or c-file-style c-file-offsets) + (let ((hack-local-variables-hook nil) (inhibit-read-only t)) + (c-tentative-buffer-changes + (c-remove-any-local-eval-or-mode-variables) + (hack-local-variables)) + nil)))) + +(if (boundp 'before-hack-local-variables-hook) + (add-hook 'before-hack-local-variables-hook 'c-before-hack-hook) + (add-hook 'hack-local-variables-hook 'c-postprocess-file-styles)) + +(defmacro c-run-mode-hooks (&rest hooks) + ;; Emacs 21.1 has introduced a system with delayed mode hooks that + ;; requires the use of the new function `run-mode-hooks'. + (if (cc-bytecomp-fboundp 'run-mode-hooks) + `(run-mode-hooks ,@hooks) + `(progn ,@(mapcar (lambda (hook) `(run-hooks ,hook)) hooks)))) + + +;;; Change hooks, linking with Font Lock. + +;; Buffer local variables defining the region to be fontified by a font lock +;; after-change function. They are set in c-after-change to +;; after-change-functions' BEG and END, and may be modified by functions in +;; `c-before-font-lock-functions'. +(defvar c-new-BEG 0) +(make-variable-buffer-local 'c-new-BEG) +(defvar c-new-END 0) +(make-variable-buffer-local 'c-new-END) + +;; Buffer local variables recording Beginning/End-of-Macro position before a +;; change, when a macro straddles, respectively, the BEG or END (or both) of +;; the change region. Otherwise these have the values BEG/END. +(defvar c-old-BOM 0) +(make-variable-buffer-local 'c-old-BOM) +(defvar c-old-EOM 0) +(make-variable-buffer-local 'c-old-EOM) + +(defun c-extend-region-for-CPP (beg end) + ;; Set c-old-BOM or c-old-EOM respectively to BEG, END, each extended to the + ;; beginning/end of any preprocessor construct they may be in. + ;; + ;; Point is undefined both before and after this function call; the buffer + ;; has already been widened, and match-data saved. The return value is + ;; meaningless. + ;; + ;; This function is in the C/C++/ObjC values of + ;; `c-get-state-before-change-functions' and is called exclusively as a + ;; before change function. + (goto-char beg) + (c-beginning-of-macro) + (setq c-old-BOM (point)) + + (goto-char end) + (when (c-beginning-of-macro) + (c-end-of-macro) + (or (eobp) (forward-char))) ; Over the terminating NL which may be marked + ; with a c-cpp-delimiter category property + (setq c-old-EOM (point))) + +(defun c-extend-font-lock-region-for-macros (begg endd &optional old-len) + ;; Extend the region (BEGG ENDD) to cover all (possibly changed) + ;; preprocessor macros; return the cons (new-BEG . new-END). OLD-LEN should + ;; be either the old length parameter when called from an + ;; after-change-function, or nil otherwise. This defun uses the variables + ;; c-old-BOM, c-new-BOM. + ;; + ;; Point is undefined on both entry and exit to this function. The buffer + ;; will have been widened on entry. + (let (limits new-beg new-end) + (goto-char c-old-BOM) ; already set to old start of macro or begg. + (setq new-beg + (min begg + (if (setq limits (c-state-literal-at (point))) + (cdr limits) ; go forward out of any string or comment. + (point)))) + + (goto-char endd) + (if (setq limits (c-state-literal-at (point))) + (goto-char (car limits))) ; go backward out of any string or comment. + (if (c-beginning-of-macro) + (c-end-of-macro)) + (setq new-end (max endd + (if old-len + (+ (- c-old-EOM old-len) (- endd begg)) + c-old-EOM) + (point))) + (cons new-beg new-end))) + +(defun c-neutralize-CPP-line (beg end) + ;; BEG and END bound a region, typically a preprocessor line. Put a + ;; "punctuation" syntax-table property on syntactically obtrusive + ;; characters, ones which would interact syntactically with stuff outside + ;; this region. + ;; + ;; These are unmatched string delimiters, or unmatched + ;; parens/brackets/braces. An unclosed comment is regarded as valid, NOT + ;; obtrusive. + (save-excursion + (let (s) + (while + (progn + (setq s (parse-partial-sexp beg end -1)) + (cond + ((< (nth 0 s) 0) ; found an unmated ),},] + (c-put-char-property (1- (point)) 'syntax-table '(1)) + t) + ((nth 3 s) ; In a string + (c-put-char-property (nth 8 s) 'syntax-table '(1)) + t) + ((> (nth 0 s) 0) ; In a (,{,[ + (c-put-char-property (nth 1 s) 'syntax-table '(1)) + t) + (t nil))))))) + +(defun c-neutralize-syntax-in-and-mark-CPP (begg endd old-len) + ;; (i) Extend the font lock region to cover all changed preprocessor + ;; regions; it sets the variables `c-new-BEG' and `c-new-END' to the new + ;; boundaries. + ;; + ;; (ii) "Neutralize" every preprocessor line wholly or partially in the + ;; extended changed region. "Restore" lines which were CPP lines before the + ;; change and are no longer so; these can be located from the Buffer local + ;; variables `c-old-BOM' and `c-old-EOM'. + ;; + ;; (iii) Mark every CPP construct by placing a `category' property value + ;; `c-cpp-delimiter' at its start and end. The marked characters are the + ;; opening # and usually the terminating EOL, but sometimes the character + ;; before a comment/string delimiter. + ;; + ;; That is, set syntax-table properties on characters that would otherwise + ;; interact syntactically with those outside the CPP line(s). + ;; + ;; This function is called from an after-change function, BEGG ENDD and + ;; OLD-LEN being the standard parameters. It prepares the buffer for font + ;; locking, hence must get called before `font-lock-after-change-function'. + ;; + ;; Point is undefined both before and after this function call, the buffer + ;; has been widened, and match-data saved. The return value is ignored. + ;; + ;; This function is in the C/C++/ObjC value of `c-before-font-lock-functions'. + ;; + ;; Note: SPEED _MATTERS_ IN THIS FUNCTION!!! + ;; + ;; This function might make hidden buffer changes. + (c-save-buffer-state (new-bounds) + ;; First determine the region, (c-new-BEG c-new-END), which will get font + ;; locked. It might need "neutralizing". This region may not start + ;; inside a string, comment, or macro. + (setq new-bounds (c-extend-font-lock-region-for-macros + c-new-BEG c-new-END old-len)) + (setq c-new-BEG (max (car new-bounds) (c-determine-limit 500 begg)) + c-new-END (min (cdr new-bounds) (c-determine-+ve-limit 500 endd))) + ;; Clear 'syntax-table properties "punctuation": + (c-clear-char-property-with-value c-new-BEG c-new-END 'syntax-table '(1)) + + ;; CPP "comment" markers: + (if (memq 'category-properties c-emacs-features) ; GNU Emacs. + (c-clear-char-property-with-value + c-new-BEG c-new-END 'category 'c-cpp-delimiter)) + + ;; Add needed properties to each CPP construct in the region. + (goto-char c-new-BEG) + (let ((pps-position c-new-BEG) pps-state mbeg) + (while (and (< (point) c-new-END) + (search-forward-regexp c-anchored-cpp-prefix c-new-END t)) + ;; If we've found a "#" inside a string/comment, ignore it. + (setq pps-state + (parse-partial-sexp pps-position (point) nil nil pps-state) + pps-position (point)) + (unless (or (nth 3 pps-state) ; in a string? + (nth 4 pps-state)) ; in a comment? + (goto-char (match-beginning 0)) + (setq mbeg (point)) + (if (> (c-syntactic-end-of-macro) mbeg) + (progn + (c-neutralize-CPP-line mbeg (point)) ; "punctuation" properties + (if (memq 'category-properties c-emacs-features) ; GNU Emacs. + (c-set-cpp-delimiters mbeg (point))) ; "comment" markers + ;(setq pps-position (point)) + ) + (forward-line)) ; no infinite loop with, e.g., "#//" + ))))) + +(defun c-before-change (beg end) + ;; Function to be put in `before-change-functions'. Primarily, this calls + ;; the language dependent `c-get-state-before-change-functions'. It is + ;; otherwise used only to remove stale entries from the `c-found-types' + ;; cache, and to record entries which a `c-after-change' function might + ;; confirm as stale. + ;; + ;; Note that this function must be FAST rather than accurate. Note + ;; also that it only has any effect when font locking is enabled. + ;; We exploit this by checking for font-lock-*-face instead of doing + ;; rigourous syntactic analysis. + + ;; If either change boundary is wholly inside an identifier, delete + ;; it/them from the cache. Don't worry about being inside a string + ;; or a comment - "wrongly" removing a symbol from `c-found-types' + ;; isn't critical. + (unless c-just-done-before-change ; guard against a spurious second + ; invocation of before-change-functions. + (setq c-just-done-before-change t) + (setq c-maybe-stale-found-type nil) + (save-restriction + (save-match-data + (widen) + (save-excursion + ;; Are we inserting/deleting stuff in the middle of an identifier? + (c-unfind-enclosing-token beg) + (c-unfind-enclosing-token end) + ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"? + (when (< beg end) + (c-unfind-coalesced-tokens beg end)) + ;; Are we (potentially) disrupting the syntactic context which + ;; makes a type a type? E.g. by inserting stuff after "foo" in + ;; "foo bar;", or before "foo" in "typedef foo *bar;"? + ;; + ;; We search for appropriate c-type properties "near" the change. + ;; First, find an appropriate boundary for this property search. + (let (lim + type type-pos + marked-id term-pos + (end1 + (or (and (eq (get-text-property end 'face) 'font-lock-comment-face) + (previous-single-property-change end 'face)) + end))) + (when (>= end1 beg) ; Don't hassle about changes entirely in comments. + ;; Find a limit for the search for a `c-type' property + (while + (and (/= (skip-chars-backward "^;{}") 0) + (> (point) (point-min)) + (memq (c-get-char-property (1- (point)) 'face) + '(font-lock-comment-face font-lock-string-face)))) + (setq lim (max (point-min) (1- (point)))) + + ;; Look for the latest `c-type' property before end1 + (when (and (> end1 (point-min)) + (setq type-pos + (if (get-text-property (1- end1) 'c-type) + end1 + (previous-single-property-change end1 'c-type nil lim)))) + (setq type (get-text-property (max (1- type-pos) lim) 'c-type)) + + (when (memq type '(c-decl-id-start c-decl-type-start)) + ;; Get the identifier, if any, that the property is on. + (goto-char (1- type-pos)) + (setq marked-id + (when (looking-at "\\(\\sw\\|\\s_\\)") + (c-beginning-of-current-token) + (buffer-substring-no-properties (point) type-pos))) + + (goto-char end1) + (skip-chars-forward "^;{}") ; FIXME!!! loop for comment, maybe + (setq lim (point)) + (setq term-pos + (or (c-next-single-property-change end 'c-type nil lim) lim)) + (setq c-maybe-stale-found-type + (list type marked-id + type-pos term-pos + (buffer-substring-no-properties type-pos term-pos) + (buffer-substring-no-properties beg end))))))) + + (if c-get-state-before-change-functions + (mapc (lambda (fn) + (funcall fn beg end)) + c-get-state-before-change-functions)) + ))))) + +(defvar c-in-after-change-fontification nil) +(make-variable-buffer-local 'c-in-after-change-fontification) +;; A flag to prevent region expanding stuff being done twice for after-change +;; fontification. + +(defun c-after-change (beg end old-len) + ;; Function put on `after-change-functions' to adjust various caches + ;; etc. Prefer speed to finesse here, since there will be an order + ;; of magnitude more calls to this function than any of the + ;; functions that use the caches. + ;; + ;; Note that care must be taken so that this is called before any + ;; font-lock callbacks since we might get calls to functions using + ;; these caches from inside them, and we must thus be sure that this + ;; has already been executed. + ;; + ;; This calls the language variable c-before-font-lock-functions, if non nil. + ;; This typically sets `syntax-table' properties. + + (setq c-just-done-before-change nil) + (c-save-buffer-state () + ;; When `combine-after-change-calls' is used we might get calls + ;; with regions outside the current narrowing. This has been + ;; observed in Emacs 20.7. + (save-restriction + (save-match-data ; c-recognize-<>-arglists changes match-data + (widen) + + (when (> end (point-max)) + ;; Some emacsen might return positions past the end. This has been + ;; observed in Emacs 20.7 when rereading a buffer changed on disk + ;; (haven't been able to minimize it, but Emacs 21.3 appears to + ;; work). + (setq end (point-max)) + (when (> beg end) + (setq beg end))) + + ;; C-y is capable of spuriously converting category properties + ;; c--as-paren-syntax into hard syntax-table properties. Remove + ;; these when it happens. + (when (memq 'category-properties c-emacs-features) + (c-clear-char-property-with-value beg end 'syntax-table + c-<-as-paren-syntax) + (c-clear-char-property-with-value beg end 'syntax-table + c->-as-paren-syntax)) + + (c-trim-found-types beg end old-len) ; maybe we don't need all of these. + (c-invalidate-sws-region-after beg end) + (c-invalidate-state-cache beg) + (c-invalidate-find-decl-cache beg) + + (when c-recognize-<>-arglists + (c-after-change-check-<>-operators beg end)) + + ;; (c-new-BEG c-new-END) will be the region to fontify. It may become + ;; larger than (beg end). + (setq c-new-BEG beg + c-new-END end) + (setq c-in-after-change-fontification t) + (save-excursion + (mapc (lambda (fn) + (funcall fn beg end old-len)) + c-before-font-lock-functions)))))) + +(defun c-set-fl-decl-start (pos) + ;; If the beginning of the line containing POS is in the middle of a "local" + ;; declaration (i.e. one which does not start outside of braces enclosing + ;; POS, such as a struct), return the beginning of that declaration. + ;; Otherwise return POS. Note that declarations, in this sense, can be + ;; nested. + ;; + ;; This function is called indirectly from font locking stuff - either from + ;; c-after-change (to prepare for after-change font-lockng) or from font + ;; lock context (etc.) fontification. + (let ((lit-limits (c-literal-limits)) + (new-pos pos) + bod-lim bo-decl) + (goto-char (c-point 'bol new-pos)) + (when lit-limits ; Comment or string. + (goto-char (car lit-limits))) + (setq bod-lim (c-determine-limit 500)) + + (while + ;; Go to a less nested declaration each time round this loop. + (and + (eq (car (c-beginning-of-decl-1 bod-lim)) 'same) + (progn (setq bo-decl (point)) + ;; Are we looking at a keyword such as "template" or + ;; "typedef" which can decorate a type, or the type itself? + (when (or (looking-at c-prefix-spec-kwds-re) + (c-forward-type t)) + ;; We've found another candidate position. + (setq new-pos (min new-pos bo-decl)) + (goto-char bo-decl)) + t) + ;; Try and go out a level to search again. + (progn + (c-backward-syntactic-ws bod-lim) + (and (> (point) bod-lim) + (or (memq (char-before) '(?\( ?\[)) + (and (eq (char-before) ?\<) + (eq (c-get-char-property + (1- (point)) 'syntax-table) + c-<-as-paren-syntax))))) + (not (bobp))) + (backward-char)) + new-pos)) ; back over (, [, <. + +(defun c-change-set-fl-decl-start (beg end old-len) + ;; Set c-new-BEG to the beginning of a "local" declaration if it('s BOL) is + ;; inside one. This is called from an after-change-function, but the + ;; parameters BEG END and OLD-LEN are ignored. See `c-set-fl-decl-start' + ;; for the detailed functionality. + (if font-lock-mode + (setq c-new-BEG (c-set-fl-decl-start c-new-BEG)))) + +(defun c-context-set-fl-decl-start (beg end) + ;; Return a cons (NEW-BEG . END), where NEW-BEG is the beginning of a + ;; "local" declaration (BOL at) NEW is inside or BEG. See + ;; `c-set-fl-decl-start' for the detailed functionality. + (cons (c-set-fl-decl-start beg) end)) + +(defvar c-standard-font-lock-fontify-region-function nil + "Standard value of `font-lock-fontify-region-function'") + +(defun c-font-lock-fontify-region (beg end &optional verbose) + ;; Effectively advice around `font-lock-fontify-region' which extends the + ;; region (BEG END), for example, to avoid context fontification chopping + ;; off the start of the context. Do not do anything if it's already been + ;; done (i.e. from an after-change fontification. An example (C++) where + ;; this used to happen is this: + ;; + ;; template + ;; + ;; + ;; void myfunc(T* p) {} + ;; + ;; Type a space in the first blank line, and the fontification of the next + ;; line was fouled up by context fontification. + (let ((new-beg beg) (new-end end) new-region case-fold-search) + (if c-in-after-change-fontification + (setq c-in-after-change-fontification nil) + (save-restriction + (widen) + (save-excursion + (mapc (lambda (fn) + (setq new-region (funcall fn new-beg new-end)) + (setq new-beg (car new-region) new-end (cdr new-region))) + c-before-context-fontification-functions)))) + (funcall c-standard-font-lock-fontify-region-function + new-beg new-end verbose))) + +(defun c-after-font-lock-init () + ;; Put on `font-lock-mode-hook'. This function ensures our after-change + ;; function will get excuted before the font-lock one. Amongst other + ;; things. + (remove-hook 'after-change-functions 'c-after-change t) + (add-hook 'after-change-functions 'c-after-change nil t) + (setq c-standard-font-lock-fontify-region-function + (default-value 'font-lock-fontify-region-function))) + +(defun c-font-lock-init () + "Set up the font-lock variables for using the font-lock support in CC Mode. +This does not load the font-lock package. Use after +`c-basic-common-init' and after cc-fonts has been loaded. +This function is called from `c-common-init', once per mode initialization." + + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults + `(,(if (c-major-mode-is 'awk-mode) + ;; awk-mode currently has only one font lock level. + 'awk-font-lock-keywords + (mapcar 'c-mode-symbol + '("font-lock-keywords" "font-lock-keywords-1" + "font-lock-keywords-2" "font-lock-keywords-3"))) + nil nil + ,c-identifier-syntax-modifications + c-beginning-of-syntax + (font-lock-mark-block-function + . c-mark-function))) + + (make-local-variable 'font-lock-fontify-region-function) + (setq font-lock-fontify-region-function 'c-font-lock-fontify-region) + + (or (memq 'add-hook-local c-emacs-features) + (make-local-hook 'font-lock-mode-hook)) + (add-hook 'font-lock-mode-hook 'c-after-font-lock-init nil t)) + +;; Emacs 22 and later. +(defun c-extend-after-change-region (beg end old-len) + "Extend the region to be fontified, if necessary." + ;; Note: the parameters are ignored here. + ;; + ;; Of the seven CC Mode languages, currently (2009-05) only C, C++, + ;; Objc (the languages with #define) and AWK Mode make non-null use of + ;; this function. + (cons c-new-BEG c-new-END)) + +;; Emacs < 22 and XEmacs +(defmacro c-advise-fl-for-region (function) + `(defadvice ,function (before get-awk-region activate) + ;; Make sure that any string/regexp is completely font-locked. + (when c-buffer-is-cc-mode + (save-excursion + (ad-set-arg 1 c-new-END) ; end + (ad-set-arg 0 c-new-BEG))))) ; beg + +(unless (boundp 'font-lock-extend-after-change-region-function) + (c-advise-fl-for-region font-lock-after-change-function) + (c-advise-fl-for-region jit-lock-after-change) + (c-advise-fl-for-region lazy-lock-defer-rest-after-change) + (c-advise-fl-for-region lazy-lock-defer-line-after-change)) + + +;; Support for C + +;;;###autoload +(defvar c-mode-syntax-table nil + "Syntax table used in c-mode buffers.") +(or c-mode-syntax-table + (setq c-mode-syntax-table + (funcall (c-lang-const c-make-mode-syntax-table c)))) + +(defvar c-mode-abbrev-table nil + "Abbreviation table used in c-mode buffers.") +(c-define-abbrev-table 'c-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0))) + +(defvar c-mode-map () + "Keymap used in c-mode buffers.") +(if c-mode-map + nil + (setq c-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for C + (define-key c-mode-map "\C-c\C-e" 'c-macro-expand) + ) + +(easy-menu-define c-c-menu c-mode-map "C Mode Commands" + (cons "C" (c-lang-const c-mode-menu c))) + +;; In XEmacs >= 21.5 modes should add their own entries to +;; `auto-mode-alist'. The comment form of autoload is used to avoid +;; doing this on load. That since `add-to-list' prepends the value +;; which could cause it to clobber user settings. Later emacsen have +;; an append option, but it's not safe to use. + +;; The extension ".C" is associated with C++ while the lowercase +;; variant goes with C. On case insensitive file systems, this means +;; that ".c" files also might open C++ mode if the C++ entry comes +;; first on `auto-mode-alist'. Thus we try to ensure that ".C" comes +;; after ".c", and since `add-to-list' adds the entry first we have to +;; add the ".C" entry first. +;;;###autoload (add-to-list 'auto-mode-alist '("\\.\\(cc\\|hh\\)\\'" . c++-mode)) +;;;###autoload (add-to-list 'auto-mode-alist '("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode)) +;;;###autoload (add-to-list 'auto-mode-alist '("\\.\\(CC?\\|HH?\\)\\'" . c++-mode)) + +;;;###autoload (add-to-list 'auto-mode-alist '("\\.[ch]\\'" . c-mode)) + +;; NB: The following two associate yacc and lex files to C Mode, which +;; is not really suitable for those formats. Anyway, afaik there's +;; currently no better mode for them, and besides this is legacy. +;;;###autoload (add-to-list 'auto-mode-alist '("\\.y\\(acc\\)?\\'" . c-mode)) +;;;###autoload (add-to-list 'auto-mode-alist '("\\.lex\\'" . c-mode)) + +;;;###autoload +(defun c-mode () + "Major mode for editing K&R and ANSI C code. +To submit a problem report, enter `\\[c-submit-bug-report]' from a +c-mode buffer. This automatically sets up a mail buffer with version +information already added. You just need to add a description of the +problem, including a reproducible test case, and send the message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `c-mode-hook'. + +Key bindings: +\\{c-mode-map}" + (interactive) + (kill-all-local-variables) + (c-initialize-cc-mode t) + (set-syntax-table c-mode-syntax-table) + (setq major-mode 'c-mode + mode-name "C" + local-abbrev-table c-mode-abbrev-table + abbrev-mode t) + (use-local-map c-mode-map) + (c-init-language-vars-for 'c-mode) + (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ; + (c-common-init 'c-mode) + (easy-menu-add c-c-menu) + (cc-imenu-init cc-imenu-c-generic-expression) + (c-run-mode-hooks 'c-mode-common-hook 'c-mode-hook) + (c-update-modeline)) + + +;; Support for C++ + +;;;###autoload +(defvar c++-mode-syntax-table nil + "Syntax table used in c++-mode buffers.") +(or c++-mode-syntax-table + (setq c++-mode-syntax-table + (funcall (c-lang-const c-make-mode-syntax-table c++)))) + +(defvar c++-mode-abbrev-table nil + "Abbreviation table used in c++-mode buffers.") +(c-define-abbrev-table 'c++-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0) + ("catch" "catch" c-electric-continued-statement 0))) + +(defvar c++-mode-map () + "Keymap used in c++-mode buffers.") +(if c++-mode-map + nil + (setq c++-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for C++ + (define-key c++-mode-map "\C-c\C-e" 'c-macro-expand) + (define-key c++-mode-map "\C-c:" 'c-scope-operator) + (define-key c++-mode-map "<" 'c-electric-lt-gt) + (define-key c++-mode-map ">" 'c-electric-lt-gt)) + +(easy-menu-define c-c++-menu c++-mode-map "C++ Mode Commands" + (cons "C++" (c-lang-const c-mode-menu c++))) + +;;;###autoload +(defun c++-mode () + "Major mode for editing C++ code. +To submit a problem report, enter `\\[c-submit-bug-report]' from a +c++-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `c++-mode-hook'. + +Key bindings: +\\{c++-mode-map}" + (interactive) + (kill-all-local-variables) + (c-initialize-cc-mode t) + (set-syntax-table c++-mode-syntax-table) + (setq major-mode 'c++-mode + mode-name "C++" + local-abbrev-table c++-mode-abbrev-table + abbrev-mode t) + (use-local-map c++-mode-map) + (c-init-language-vars-for 'c++-mode) + (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ; + (c-common-init 'c++-mode) + (easy-menu-add c-c++-menu) + (cc-imenu-init cc-imenu-c++-generic-expression) + (c-run-mode-hooks 'c-mode-common-hook 'c++-mode-hook) + (c-update-modeline)) + + +;; Support for Objective-C + +;;;###autoload +(defvar objc-mode-syntax-table nil + "Syntax table used in objc-mode buffers.") +(or objc-mode-syntax-table + (setq objc-mode-syntax-table + (funcall (c-lang-const c-make-mode-syntax-table objc)))) + +(defvar objc-mode-abbrev-table nil + "Abbreviation table used in objc-mode buffers.") +(c-define-abbrev-table 'objc-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0))) + +(defvar objc-mode-map () + "Keymap used in objc-mode buffers.") +(if objc-mode-map + nil + (setq objc-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for Objective-C + (define-key objc-mode-map "\C-c\C-e" 'c-macro-expand)) + +(easy-menu-define c-objc-menu objc-mode-map "ObjC Mode Commands" + (cons "ObjC" (c-lang-const c-mode-menu objc))) + +;;;###autoload (add-to-list 'auto-mode-alist '("\\.m\\'" . objc-mode)) + +;;;###autoload +(defun objc-mode () + "Major mode for editing Objective C code. +To submit a problem report, enter `\\[c-submit-bug-report]' from an +objc-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `objc-mode-hook'. + +Key bindings: +\\{objc-mode-map}" + (interactive) + (kill-all-local-variables) + (c-initialize-cc-mode t) + (set-syntax-table objc-mode-syntax-table) + (setq major-mode 'objc-mode + mode-name "ObjC" + local-abbrev-table objc-mode-abbrev-table + abbrev-mode t) + (use-local-map objc-mode-map) + (c-init-language-vars-for 'objc-mode) + (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ; + (c-common-init 'objc-mode) + (easy-menu-add c-objc-menu) + (cc-imenu-init nil 'cc-imenu-objc-function) + (c-run-mode-hooks 'c-mode-common-hook 'objc-mode-hook) + (c-update-modeline)) + + +;; Support for Java + +;;;###autoload +(defvar java-mode-syntax-table nil + "Syntax table used in java-mode buffers.") +(or java-mode-syntax-table + (setq java-mode-syntax-table + (funcall (c-lang-const c-make-mode-syntax-table java)))) + +(defvar java-mode-abbrev-table nil + "Abbreviation table used in java-mode buffers.") +(c-define-abbrev-table 'java-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0) + ("catch" "catch" c-electric-continued-statement 0) + ("finally" "finally" c-electric-continued-statement 0))) + +(defvar java-mode-map () + "Keymap used in java-mode buffers.") +(if java-mode-map + nil + (setq java-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for Java + ) + +;; Regexp trying to describe the beginning of a Java top-level +;; definition. This is not used by CC Mode, nor is it maintained +;; since it's practically impossible to write a regexp that reliably +;; matches such a construct. Other tools are necessary. +(defconst c-Java-defun-prompt-regexp + "^[ \t]*\\(\\(\\(public\\|protected\\|private\\|const\\|abstract\\|synchronized\\|final\\|static\\|threadsafe\\|transient\\|native\\|volatile\\)\\s-+\\)*\\(\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*[][_$.a-zA-Z0-9]+\\|[[a-zA-Z]\\)\\s-*\\)\\s-+\\)\\)?\\(\\([[a-zA-Z][][_$.a-zA-Z0-9]*\\s-+\\)\\s-*\\)?\\([_a-zA-Z][^][ \t:;.,{}()=]*\\|\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)\\)\\s-*\\(([^);{}]*)\\)?\\([] \t]*\\)\\(\\s-*\\\\s-*\\(\\([_$a-zA-Z][_$.a-zA-Z0-9]*\\)[, \t\n\r\f\v]*\\)+\\)?\\s-*") + +(easy-menu-define c-java-menu java-mode-map "Java Mode Commands" + (cons "Java" (c-lang-const c-mode-menu java))) + +;;;###autoload (add-to-list 'auto-mode-alist '("\\.java\\'" . java-mode)) + +;;;###autoload +(defun java-mode () + "Major mode for editing Java code. +To submit a problem report, enter `\\[c-submit-bug-report]' from a +java-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `java-mode-hook'. + +Key bindings: +\\{java-mode-map}" + (interactive) + (kill-all-local-variables) + (c-initialize-cc-mode t) + (set-syntax-table java-mode-syntax-table) + (setq major-mode 'java-mode + mode-name "Java" + local-abbrev-table java-mode-abbrev-table + abbrev-mode t) + (use-local-map java-mode-map) + (c-init-language-vars-for 'java-mode) + (c-common-init 'java-mode) + (easy-menu-add c-java-menu) + (cc-imenu-init cc-imenu-java-generic-expression) + (c-run-mode-hooks 'c-mode-common-hook 'java-mode-hook) + (c-update-modeline)) + + +;; Support for CORBA's IDL language + +;;;###autoload +(defvar idl-mode-syntax-table nil + "Syntax table used in idl-mode buffers.") +(or idl-mode-syntax-table + (setq idl-mode-syntax-table + (funcall (c-lang-const c-make-mode-syntax-table idl)))) + +(defvar idl-mode-abbrev-table nil + "Abbreviation table used in idl-mode buffers.") +(c-define-abbrev-table 'idl-mode-abbrev-table nil) + +(defvar idl-mode-map () + "Keymap used in idl-mode buffers.") +(if idl-mode-map + nil + (setq idl-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for IDL + ) + +(easy-menu-define c-idl-menu idl-mode-map "IDL Mode Commands" + (cons "IDL" (c-lang-const c-mode-menu idl))) + +;;;###autoload (add-to-list 'auto-mode-alist '("\\.idl\\'" . idl-mode)) + +;;;###autoload +(defun idl-mode () + "Major mode for editing CORBA's IDL, PSDL and CIDL code. +To submit a problem report, enter `\\[c-submit-bug-report]' from an +idl-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `idl-mode-hook'. + +Key bindings: +\\{idl-mode-map}" + (interactive) + (kill-all-local-variables) + (c-initialize-cc-mode t) + (set-syntax-table idl-mode-syntax-table) + (setq major-mode 'idl-mode + mode-name "IDL" + local-abbrev-table idl-mode-abbrev-table) + (use-local-map idl-mode-map) + (c-init-language-vars-for 'idl-mode) + (c-common-init 'idl-mode) + (easy-menu-add c-idl-menu) + ;;(cc-imenu-init cc-imenu-idl-generic-expression) ;TODO + (c-run-mode-hooks 'c-mode-common-hook 'idl-mode-hook) + (c-update-modeline)) + + +;; Support for Pike + +;;;###autoload +(defvar pike-mode-syntax-table nil + "Syntax table used in pike-mode buffers.") +(or pike-mode-syntax-table + (setq pike-mode-syntax-table + (funcall (c-lang-const c-make-mode-syntax-table pike)))) + +(defvar pike-mode-abbrev-table nil + "Abbreviation table used in pike-mode buffers.") +(c-define-abbrev-table 'pike-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0))) + +(defvar pike-mode-map () + "Keymap used in pike-mode buffers.") +(if pike-mode-map + nil + (setq pike-mode-map (c-make-inherited-keymap)) + ;; additional bindings + (define-key pike-mode-map "\C-c\C-e" 'c-macro-expand)) + +(easy-menu-define c-pike-menu pike-mode-map "Pike Mode Commands" + (cons "Pike" (c-lang-const c-mode-menu pike))) + +;;;###autoload (add-to-list 'auto-mode-alist '("\\.\\(u?lpc\\|pike\\|pmod\\(.in\\)?\\)\\'" . pike-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("pike" . pike-mode)) + +;;;###autoload +(defun pike-mode () + "Major mode for editing Pike code. +To submit a problem report, enter `\\[c-submit-bug-report]' from a +pike-mode buffer. This automatically sets up a mail buffer with +version information already added. You just need to add a description +of the problem, including a reproducible test case, and send the +message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `pike-mode-hook'. + +Key bindings: +\\{pike-mode-map}" + (interactive) + (kill-all-local-variables) + (c-initialize-cc-mode t) + (set-syntax-table pike-mode-syntax-table) + (setq major-mode 'pike-mode + mode-name "Pike" + local-abbrev-table pike-mode-abbrev-table + abbrev-mode t) + (use-local-map pike-mode-map) + (c-init-language-vars-for 'pike-mode) + (c-common-init 'pike-mode) + (easy-menu-add c-pike-menu) + ;;(cc-imenu-init cc-imenu-pike-generic-expression) ;TODO + (c-run-mode-hooks 'c-mode-common-hook 'pike-mode-hook) + (c-update-modeline)) + + +;; Support for AWK + +;;;###autoload (add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("awk" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("mawk" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode)) +;;;###autoload (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode)) + +;;; Autoload directives must be on the top level, so we construct an +;;; autoload form instead. +;;;###autoload (autoload 'awk-mode "cc-mode" "Major mode for editing AWK code." t) + +(defvar awk-mode-abbrev-table nil + "Abbreviation table used in awk-mode buffers.") +(c-define-abbrev-table 'awk-mode-abbrev-table + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0))) + +(defvar awk-mode-map () + "Keymap used in awk-mode buffers.") +(if awk-mode-map + nil + (setq awk-mode-map (c-make-inherited-keymap)) + ;; add bindings which are only useful for awk. + (define-key awk-mode-map "#" 'self-insert-command) + (define-key awk-mode-map "/" 'self-insert-command) + (define-key awk-mode-map "*" 'self-insert-command) + (define-key awk-mode-map "\C-c\C-n" 'undefined) ; #if doesn't exist in awk. + (define-key awk-mode-map "\C-c\C-p" 'undefined) + (define-key awk-mode-map "\C-c\C-u" 'undefined) + (define-key awk-mode-map "\M-a" 'c-beginning-of-statement) ; 2003/10/7 + (define-key awk-mode-map "\M-e" 'c-end-of-statement) ; 2003/10/7 + (define-key awk-mode-map "\C-\M-a" 'c-awk-beginning-of-defun) + (define-key awk-mode-map "\C-\M-e" 'c-awk-end-of-defun)) + +(easy-menu-define c-awk-menu awk-mode-map "AWK Mode Commands" + (cons "AWK" (c-lang-const c-mode-menu awk))) + +(defun awk-mode () + "Major mode for editing AWK code. +To submit a problem report, enter `\\[c-submit-bug-report]' from an +awk-mode buffer. This automatically sets up a mail buffer with version +information already added. You just need to add a description of the +problem, including a reproducible test case, and send the message. + +To see what version of CC Mode you are running, enter `\\[c-version]'. + +The hook `c-mode-common-hook' is run with no args at mode +initialization, then `awk-mode-hook'. + +Key bindings: +\\{awk-mode-map}" + (interactive) + (require 'cc-awk) ; Added 2003/6/10. + (kill-all-local-variables) + (c-initialize-cc-mode t) + (set-syntax-table awk-mode-syntax-table) + (setq major-mode 'awk-mode + mode-name "AWK" + local-abbrev-table awk-mode-abbrev-table + abbrev-mode t) + (use-local-map awk-mode-map) + (c-init-language-vars-for 'awk-mode) + (c-common-init 'awk-mode) + (c-awk-unstick-NL-prop) + + (c-run-mode-hooks 'c-mode-common-hook 'awk-mode-hook) + (c-update-modeline)) + + +;; bug reporting + +(defconst c-mode-help-address + "bug-cc-mode@gnu.org" + "Address(es) for CC Mode bug reports.") + +(defun c-version () + "Echo the current version of CC Mode in the minibuffer." + (interactive) + (message "Using CC Mode version %s" c-version) + (c-keep-region-active)) + +(defvar c-prepare-bug-report-hooks nil) + +;; Dynamic variables used by reporter. +(defvar reporter-prompt-for-summary-p) +(defvar reporter-dont-compact-list) + +(defun c-submit-bug-report () + "Submit via mail a bug report on CC Mode." + (interactive) + (require 'reporter) + ;; load in reporter + (let ((reporter-prompt-for-summary-p t) + (reporter-dont-compact-list '(c-offsets-alist)) + (style c-indentation-style) + (c-features c-emacs-features)) + (and + (if (y-or-n-p "Do you want to submit a report on CC Mode? ") + t (message "") nil) + (reporter-submit-bug-report + c-mode-help-address + (concat "CC Mode " c-version " (" mode-name ")") + (let ((vars (append + c-style-variables + '(c-buffer-is-cc-mode + c-tab-always-indent + c-syntactic-indentation + c-syntactic-indentation-in-macros + c-ignore-auto-fill + c-auto-align-backslashes + c-backspace-function + c-delete-function + c-electric-pound-behavior + c-default-style + c-enable-xemacs-performance-kludge-p + c-old-style-variable-behavior + defun-prompt-regexp + tab-width + comment-column + parse-sexp-ignore-comments + parse-sexp-lookup-properties + lookup-syntax-properties + ;; A brain-damaged XEmacs only variable that, if + ;; set to nil can cause all kinds of chaos. + signal-error-on-buffer-boundary + ;; Variables that affect line breaking and comments. + auto-fill-mode + auto-fill-function + filladapt-mode + comment-multi-line + comment-start-skip + fill-prefix + fill-column + paragraph-start + adaptive-fill-mode + adaptive-fill-regexp) + nil))) + (mapc (lambda (var) (unless (boundp var) + (setq vars (delq var vars)))) + '(signal-error-on-buffer-boundary + filladapt-mode + defun-prompt-regexp + font-lock-mode + font-lock-maximum-decoration + parse-sexp-lookup-properties + lookup-syntax-properties)) + vars) + (lambda () + (run-hooks 'c-prepare-bug-report-hooks) + (insert (format "Buffer Style: %s\nc-emacs-features: %s\n" + style c-features))))))) + + +(cc-provide 'cc-mode) + +;;; arch-tag: 7825e5c4-fd09-439f-a04d-4c13208ba3d7 +;;; cc-mode.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-mode.texi b/site-lisp/cc-mode/5.32.3/cc-mode.texi new file mode 100644 index 0000000..133dd14 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-mode.texi @@ -0,0 +1,7244 @@ +\input texinfo +@c Notes to self regarding line handling: +@c +@c Empty lines are often significant before @end directives; avoid them. +@c +@c Empty lines before and after @example directives are significant in +@c info output but not in TeX. Empty lines inside @example directives +@c are significant. + +@c Conventions for formatting examples: +@c o If the example contains empty lines then put the surrounding empty +@c lines inside the @example directives. Put them outside otherwise. +@c o Use @group inside the example only if it shows indentation where +@c the relation between lines inside is relevant. +@c o Format line number columns like this: +@c 1: foo +@c 2: bar +@c ^ one space +@c ^^ two columns, right alignment +@c o Check line lengths in TeX output; they can typically be no longer +@c than 70 chars, 60 if the paragraph is indented. + +@comment TBD: Document the finer details of statement anchoring? + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment %**start of header (This is for running Texinfo on a region) +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment How to make the various output formats: +@comment (Thanks to Robert Chassell for supplying this information.) +@comment Note that Texinfo 4.7 (or later) is needed. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@ignore +In each of the following pairs of commands, the first generates a +version with cross references pointing to the GNU Emacs manuals, +the second with them pointing to the XEmacs manuals. + ## Info output + makeinfo cc-mode.texi + makeinfo -DXEMACS cc-mode.texi + + ## DVI output + ## You may need to set up the environment variable TEXINPUTS so + ## that tex can find the file texinfo.tex - See the tex + ## manpage. + texi2dvi cc-mode.texi + texi2dvi -t "@set XEMACS " cc-mode.texi + + ## HTML output. (The --no-split parameter is optional) + makeinfo --html --no-split cc-mode.texi + makeinfo --html --no-split -DXEMACS cc-mode.texi + + ## Plain text output + makeinfo --fill-column=70 --no-split --paragraph-indent=0 \ + --no-headers --output=cc-mode.txt cc-mode.texi + makeinfo --fill-column=70 --no-split --paragraph-indent=0 \ + --no-headers --output=cc-mode.txt -DXEMACS cc-mode.texi + + ## DocBook output + makeinfo --docbook --no-split --paragraph-indent=0 \ + cc-mode.texi + makeinfo --docbook --no-split --paragraph-indent=0 \ + -DXEMACS cc-mode.texi + + ## XML output + makeinfo --xml --no-split --paragraph-indent=0 \ + cc-mode.texi + makeinfo --xml --no-split --paragraph-indent=0 \ + -DXEMACS cc-mode.texi + + #### (You must be in the same directory as the viewed file.) + + ## View DVI output + xdvi cc-mode.dvi & + + ## View HTML output + mozilla cc-mode.html +@end ignore + +@comment No overfull hbox marks in the dvi file. +@finalout + +@setfilename cc-mode.info +@settitle CC Mode Manual +@footnotestyle end + +@c The following four macros generate the filenames and titles of the +@c main (X)Emacs manual and the Elisp/Lispref manual. Leave the +@c Texinfo variable `XEMACS' unset to generate a GNU Emacs version, set it +@c to generate an XEmacs version, e.g. with +@c "makeinfo -DXEMACS cc-mode.texi". +@ifset XEMACS +@macro emacsman +xemacs +@end macro +@macro emacsmantitle +XEmacs User's Manual +@end macro +@macro lispref +lispref +@end macro +@macro lispreftitle +XEmacs Lisp Reference Manual +@end macro +@end ifset + +@ifclear XEMACS +@macro emacsman +emacs +@end macro +@macro emacsmantitle +GNU Emacs Manual +@end macro +@macro lispref +elisp +@end macro +@macro lispreftitle +GNU Emacs Lisp Reference Manual +@end macro +@end ifclear + + +@macro ccmode +CC Mode +@end macro + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment @setchapternewpage odd !! we don't want blank pages !! +@comment %**end of header (This is for running Texinfo on a region) +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment +@comment Texinfo manual for CC Mode +@comment Generated from the original README file by Krishna Padmasola +@comment +@comment +@comment Authors: +@comment Barry A. Warsaw +@comment Martin Stjernholm +@comment Alan Mackenzie +@comment +@comment Maintained by Martin Stjernholm and Alan Mackenzie +@comment +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@comment Define an index for syntactic symbols. +@ifnottex @c In texi2dvi, the @defindex would create an empty cc-mode.ss + @c For Info, unlike tex, @syncodeindex needs a matching @defindex. +@defindex ss +@end ifnottex + +@comment Combine key, syntactic symbol and concept indices into one. +@syncodeindex ss cp +@syncodeindex ky cp + +@copying +Copyright @copyright{} 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software +Foundation, Inc. + +This manual is free documentation; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3, or (at +your option) any later version. + +This manual 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, the +file @file{COPYING}, along with @ccmode{}. If not, see +@url{http://www.gnu.org/licenses/gpl.html}. +@end copying + +@comment Info directory entry for use by install-info. The indentation +@comment here is by request from the FSF folks. +@dircategory Emacs +@direntry +* CC Mode: (cc-mode). Emacs mode for editing C, C++, Objective-C, + Java, Pike, AWK, and CORBA IDL code. +@end direntry + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment TeX title page +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@titlepage +@sp 10 + +@center @titlefont{CC Mode 5.32} +@sp 2 +@center @subtitlefont{A GNU Emacs mode for editing C and C-like languages} +@sp 2 +@center Barry A. Warsaw, Martin Stjernholm, Alan Mackenzie + +@page +@vskip 0pt plus 1filll +@insertcopying + +This manual was generated from $Revision: 9d05b06f1838 $ of +cc-mode.texi. It can be downloaded from the URL formed by +substituting that 12 digit hexadecimal revision for '''' in +@*http://cc-mode.hg.sourceforge.net/hgweb/cc-mode/cc-mode/raw-file//cc-mode.texi. + +@end titlepage + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment The Top node contains the master menu for the Info file. +@comment This appears only in the Info file, not the printed manual. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@node Top, Introduction, (dir), (dir) +@comment node-name, next, previous, up + +@ifinfo +@top @ccmode{} + +@ccmode{} is a GNU Emacs mode for editing files containing C, C++, +Objective-C, Java, CORBA IDL (and the variants PSDL and CIDL), Pike +and AWK code. It provides syntax-based indentation, font locking, and +has several handy commands and some minor modes to make the editing +easier. It does not provide tools to look up and navigate between +functions, classes etc - there are other packages for that. +@end ifinfo + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@menu +* Introduction:: +* Overview:: +* Getting Started:: +* Commands:: +* Font Locking:: +* Config Basics:: +* Custom Filling and Breaking:: +* Custom Auto-newlines:: +* Clean-ups:: +* Indentation Engine Basics:: +* Customizing Indentation:: +* Custom Macros:: +* Odds and Ends:: +* Sample .emacs File:: +* Performance Issues:: +* Limitations and Known Bugs:: +* FAQ:: +* Updating CC Mode:: +* Mailing Lists and Bug Reports:: +* Command and Function Index:: +* Variable Index:: +* Concept and Key Index:: + +@detailmenu + --- The Detailed Node Listing --- + +Commands + +* Indentation Commands:: +* Comment Commands:: +* Movement Commands:: +* Filling and Breaking:: +* Minor Modes:: +* Electric Keys:: +* Auto-newlines:: +* Hungry WS Deletion:: +* Subword Movement:: +* Other Commands:: + +Font Locking + +* Font Locking Preliminaries:: +* Faces:: +* Doc Comments:: +* AWK Mode Font Locking:: + +Configuration Basics + +* CC Hooks:: +* Style Variables:: +* Styles:: + +Styles + +* Built-in Styles:: +* Choosing a Style:: +* Adding Styles:: +* Guessing the Style:: +* File Styles:: + +Customizing Auto-newlines + +* Hanging Braces:: +* Hanging Colons:: +* Hanging Semicolons and Commas:: + +Hanging Braces + +* Custom Braces:: + +Indentation Engine Basics + +* Syntactic Analysis:: +* Syntactic Symbols:: +* Indentation Calculation:: + +Syntactic Symbols + +* Function Symbols:: +* Class Symbols:: +* Conditional Construct Symbols:: +* Switch Statement Symbols:: +* Brace List Symbols:: +* External Scope Symbols:: +* Paren List Symbols:: +* Literal Symbols:: +* Multiline Macro Symbols:: +* Objective-C Method Symbols:: +* Java Symbols:: +* Statement Block Symbols:: +* K&R Symbols:: + +Customizing Indentation + +* c-offsets-alist:: +* Interactive Customization:: +* Line-Up Functions:: +* Custom Line-Up:: +* Other Indentation:: + +Line-Up Functions + +* Brace/Paren Line-Up:: +* List Line-Up:: +* Operator Line-Up:: +* Comment Line-Up:: +* Misc Line-Up:: + +Customizing Macros + +* Macro Backslashes:: +* Macros with ;:: + +@end detailmenu +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Introduction, Overview, Top, Top +@comment node-name, next, previous, up +@chapter Introduction +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex BOCM +@cindex history +@cindex awk-mode.el +@cindex c-mode.el +@cindex c++-mode.el + +Welcome to @ccmode{}, a GNU Emacs mode for editing files containing C, +C++, Objective-C, Java, CORBA IDL (and the variants CORBA PSDL and +CIDL), Pike and AWK code. This incarnation of the mode is descended +from @file{c-mode.el} (also called ``Boring Old C Mode'' or BOCM +@t{:-)}, @file{c++-mode.el} version 2, which Barry Warsaw had been +maintaining since 1992, and @file{awk-mode.el}, a long neglected mode +in the (X)Emacs base. + +Late in 1997, Martin Stjernholm joined Barry on the @ccmode{} +Maintainers Team, and implemented the Pike support. In 2000 Martin +took over as the sole maintainer. In 2001 Alan Mackenzie joined the +team, implementing AWK support in version 5.30. @ccmode{} did not +originally contain the font lock support for its languages --- that +was added in version 5.30. + +This manual describes @ccmode{} +@comment The following line must appear on its own, so that the +version 5.32. +@comment Release.py script can update the version number automatically + +@ccmode{} supports the editing of K&R and ANSI C, C++, Objective-C, +Java, CORBA's Interface Definition Language, Pike@footnote{A C-like +scripting language with its roots in the LPC language used in some MUD +engines. See @uref{http://pike.ida.liu.se/}.} and AWK files. In this +way, you can easily set up consistent font locking and coding styles for +use in editing all of these languages, although AWK is not yet as +uniformly integrated as the other languages. + +@findex c-mode +@findex c++-mode +@findex objc-mode +@findex java-mode +@findex idl-mode +@findex pike-mode +@findex awk-mode +Note that the name of this package is ``@ccmode{}'', but there is no top +level @code{cc-mode} entry point. All of the variables, commands, and +functions in @ccmode{} are prefixed with @code{c-@var{thing}}, and +@code{c-mode}, @code{c++-mode}, @code{objc-mode}, @code{java-mode}, +@code{idl-mode}, @code{pike-mode}, and @code{awk-mode} entry points are +provided. This package is intended to be a replacement for +@file{c-mode.el}, @file{c++-mode.el} and @file{awk-mode.el}. + +A special word of thanks goes to Krishna Padmasola for his work in +converting the original @file{README} file to Texinfo format. I'd +also like to thank all the @ccmode{} victims who help enormously +during the early beta stages of @ccmode{}'s development. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Overview, Getting Started, Introduction, Top +@comment node-name, next, previous, up@cindex organization of the manual +@chapter Overview of the Manual +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@noindent +The manual starts with several introductory chapters (including this +one). + +@noindent +The next chunk of the manual describes the day to day @emph{use} of +@ccmode{} (as contrasted with how to customize it). + +@itemize @bullet +@item +The chapter ``Commands'' describes in detail how to use (nearly) all +of @ccmode{}'s features. There are extensive cross-references from +here to the corresponding sections later in the manual which tell you +how to customize these features. + +@item +``Font Locking'' describes how ``syntax highlighting'' is applied to +your buffers. It is mainly background information and can be skipped +over at a first reading. +@end itemize + +@noindent +The next chunk of the manual describes how to @emph{customize} +@ccmode{}. Typically, an overview of a topic is given at the chapter +level, then the sections and subsections describe the material in +increasing detail. + +@itemize @bullet +@item +The chapter ``Configuration Basics'' tells you @emph{how} to write +customizations - whether in hooks, in styles, in both, or in neither, +depending on your needs. It describes the @ccmode{} style system and +lists the standard styles that @ccmode{} supplies. + +@item +The next few chapters describe in detail how to customize the various +features of @ccmode{}. + +@item +Finally, there is a sample @file{.emacs} fragment, which might help you +in creating your own customization. +@end itemize + +@noindent +The manual ends with ``this and that'', things that don't fit cleanly +into any of the previous chunks. + +@itemize @bullet +@item +Two chapters discuss the performance of @ccmode{} and known +bugs/limitations. + +@item +The FAQ contains a list of common problems and questions. + +@item +The next two chapters tell you how to get in touch with the @ccmode{} +project - whether for updating @ccmode{} or submitting bug reports. +@end itemize + +@noindent +Finally, there are the customary indices. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Getting Started, Commands, Overview, Top +@comment node-name, next, previous, up +@chapter Getting Started +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +If you got this version of @ccmode{} with Emacs or XEmacs, it should +work just fine right out of the box. Note however that you might not +have the latest @ccmode{} release and might want to upgrade your copy +(see below). + +You should probably start by skimming through the entire chapter +@ref{Commands} to get an overview of @ccmode{}'s capabilities. + +After trying out some commands, you may dislike some aspects of +@ccmode{}'s default configuration. Here is an outline of how to +change some of the settings that newcomers to @ccmode{} most often +want to change: + +@table @asis +@item c-basic-offset +This Lisp variable holds an integer, the number of columns @ccmode{} +indents nested code. To set this value to 6, customize +@code{c-basic-offset} or put this into your @file{.emacs}: + +@example +(setq c-basic-offset 6) +@end example + +@item The (indentation) style +The basic ``shape'' of indentation created by @ccmode{}---by default, +this is @code{gnu} style (except for Java and AWK buffers). A list of +the available styles and their descriptions can be found in +@ref{Built-in Styles}. A complete specification of the @ccmode{} +style system, including how to create your own style, can be found in +the chapter @ref{Styles}. To set your style to @code{linux}, either +customize @code{c-default-style} or put this into your @file{.emacs}: + +@example +(setq c-default-style '((java-mode . "java") + (awk-mode . "awk") + (other . "linux"))) +@end example + +@item Electric Indentation +Normally, when you type ``punctuation'' characters such as @samp{;} or +@samp{@{}, @ccmode{} instantly reindents the current line. This can +be disconcerting until you get used to it. To disable @dfn{electric +indentation} in the current buffer, type @kbd{C-c C-l}. Type the same +thing to enable it again. To have electric indentation disabled by +default, put the following into your @file{.emacs} file@footnote{There +is no ``easy customization'' facility for making this change.}: + +@example +(setq-default c-electric-flag nil) +@end example + +@noindent +Details of this and other similar ``Minor Modes'' appear in the +section @ref{Minor Modes}. + +@item Making the @key{RET} key indent the new line +The standard Emacs binding for @key{RET} just adds a new line. If you +want it to reindent the new line as well, rebind the key. Note that +the action of rebinding would fail if the pertinent keymap didn't yet +exist---we thus need to delay the action until after @ccmode{} has +been loaded. Put the following code into your @file{.emacs}: + +@example +(defun my-make-CR-do-indent () + (define-key c-mode-base-map "\C-m" 'c-context-line-break)) +(add-hook 'c-initialization-hook 'my-make-CR-do-indent) +@end example + +@noindent +This example demonstrates the use of a very powerful @ccmode{} (and +Emacs) facility, the hook. The use of @ccmode{}'s hooks is described +in @ref{CC Hooks}. +@end table + +All these settings should occur in your @file{.emacs} @emph{before} +any @ccmode{} buffers get loaded---in particular, before any call of +@code{desktop-read}. + +As you get to know the mode better, you may want to make more +ambitious changes to your configuration. For this, you should start +reading the chapter @ref{Config Basics}. + +If you are upgrading an existing @ccmode{} installation, please see +the @file{README} file for installation details. In particular, if +you are going to be editing AWK files, @file{README} describes how to +configure your (X)Emacs so that @ccmode{} will supersede the obsolete +@code{awk-mode.el} which might have been supplied with your (X)Emacs. +@ccmode{} might not work with older versions of Emacs or XEmacs. See +the @ccmode{} release notes at @uref{http://cc-mode.sourceforge.net} +for the latest information on Emacs version and package compatibility +(@pxref{Updating CC Mode}). + +@deffn Command c-version +@findex version (c-) +You can find out what version of @ccmode{} you are using by visiting a C +file and entering @kbd{M-x c-version RET}. You should see this message in +the echo area: + +@example +Using CC Mode version 5.XX +@end example + +@noindent +where @samp{XX} is the minor release number. +@end deffn + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Commands, Font Locking, Getting Started, Top +@comment node-name, next, previous, up +@chapter Commands +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +This chapter specifies all of CC Mode's commands, and thus contains +nearly everything you need to know to @emph{use} @ccmode{} (as +contrasted with configuring it). @dfn{Commands} here means both +control key sequences and @dfn{electric keys}, these being characters +such as @samp{;} which, as well as inserting themselves into the +buffer, also do other things. + +You might well want to review +@ifset XEMACS +@ref{Lists,,,@emacsman{}, @emacsmantitle{}}, +@end ifset +@ifclear XEMACS +@ref{Moving by Parens,,,@emacsman{}, @emacsmantitle{}}, +@end ifclear +which describes commands for moving around brace and parenthesis +structures. + + +@menu +* Indentation Commands:: +* Comment Commands:: +* Movement Commands:: +* Filling and Breaking:: +* Minor Modes:: +* Electric Keys:: +* Auto-newlines:: +* Hungry WS Deletion:: +* Subword Movement:: +* Other Commands:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Indentation Commands, Comment Commands, Commands, Commands +@comment node-name, next, previous,up +@section Indentation Commands +@cindex indentation +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The following commands reindent C constructs. Note that when you +change your coding style, either interactively or through some other +means, your file does @emph{not} automatically get reindented. You +will need to execute one of the following commands to see the effects +of your changes. + +@cindex GNU indent program +Also, variables like @code{c-hanging-*} and @code{c-cleanup-list} +(@pxref{Custom Auto-newlines}) only affect how on-the-fly code is +formatted. Changing the ``hanginess'' of a brace and then +reindenting, will not move the brace to a different line. For this, +you're better off getting an external program like GNU @code{indent}, +which will rearrange brace location, amongst other things. + +Preprocessor directives are handled as syntactic whitespace from other +code, i.e. they can be interspersed anywhere without affecting the +indentation of the surrounding code, just like comments. + +The code inside macro definitions is, by default, still analyzed +syntactically so that you get relative indentation there just as you'd +get if the same code was outside a macro. However, since there is no +hint about the syntactic context, i.e. whether the macro expands to an +expression, to some statements, or perhaps to whole functions, the +syntactic recognition can be wrong. @ccmode{} manages to figure it +out correctly most of the time, though. + +Some macros, when invoked, ''have their own semicolon''. To get the +next line indented correctly, rather than as a continuation line, +@xref{Macros with ;}. + +Reindenting large sections of code can take a long time. When +@ccmode{} reindents a region of code, it is essentially equivalent to +hitting @key{TAB} on every line of the region. + +These commands indent code: + +@table @asis +@item @kbd{@key{TAB}} (@code{c-indent-command}) +@kindex TAB +@findex c-indent-command +@findex indent-command (c-) +This command indents the current line. That is all you need to know +about it for normal use. + +@code{c-indent-command} does different things, depending on the +setting of @code{c-syntactic-indentation} (@pxref{Indentation Engine +Basics}): + +@itemize @bullet +@item +When it's non-@code{nil} (which it normally is), the command indents +the line according to its syntactic context. With a prefix argument +(@kbd{C-u @key{TAB}}), it will re-indent the entire +expression@footnote{this is only useful for a line starting with a +comment opener or an opening brace, parenthesis, or string quote.} +that begins at the line's left margin. + +@item +When it's @code{nil}, the command indents the line by an extra +@code{c-basic-offset} columns. A prefix argument acts as a +multiplier. A bare prefix (@kbd{C-u @key{TAB}}) is equivalent to -1, +removing @code{c-basic-offset} columns from the indentation. +@end itemize + +The precise behavior is modified by several variables: With +@code{c-tab-always-indent}, you can make @key{TAB} insert whitespace +in some circumstances---@code{c-insert-tab-function} then defines +precisely what sort of ``whitespace'' this will be. Set the standard +Emacs variable @code{indent-tabs-mode} to @code{t} if you want real +@samp{tab} characters to be used in the indentation, to @code{nil} if +you want only spaces. @xref{Just Spaces,,, @emacsman{}, +@emacsmantitle{}}. + +@defopt c-tab-always-indent +@vindex tab-always-indent (c-) +@cindex literal +This variable modifies how @key{TAB} operates. +@itemize @bullet +@item +When it is @code{t} (the default), @key{TAB} simply indents the +current line. +@item +When it is @code{nil}, @key{TAB} (re)indents the line only if point is +to the left of the first non-whitespace character on the line. +Otherwise it inserts some whitespace (a tab or an equivalent number of +spaces - see below) at point. +@item +With some other value, the line is reindented. Additionally, if point +is within a string or comment, some whitespace is inserted. +@end itemize +@end defopt + +@defopt c-insert-tab-function +@vindex insert-tab-function (c-) +@findex tab-to-tab-stop +When ``some whitespace'' is inserted as described above, what actually +happens is that the function stored in @code{c-insert-tab-function} is +called. Normally, this is @code{insert-tab}, which inserts a real tab +character or the equivalent number of spaces (depending on +@code{indent-tabs-mode}). Some people, however, set +@code{c-insert-tab-function} to @code{tab-to-tab-stop} so as to get +hard tab stops when indenting. +@end defopt +@end table + +@noindent +The kind of indentation the next five commands do depends on the +setting of @code{c-syntactic-indentation} (@pxref{Indentation Engine +Basics}): +@itemize @bullet +@item +when it is non-@code{nil} (the default), the commands indent lines +according to their syntactic context; +@item +when it is @code{nil}, they just indent each line the same amount as +the previous non-blank line. The commands that indent a region aren't +very useful in this case. +@end itemize + +@table @asis +@item @kbd{C-j} (@code{newline-and-indent}) +@kindex C-j +@findex newline-and-indent +Inserts a newline and indents the new blank line, ready to start +typing. This is a standard (X)Emacs command. + +@item @kbd{C-M-q} (@code{c-indent-exp}) +@kindex C-M-q +@findex c-indent-exp +@findex indent-exp (c-) +Indents an entire balanced brace or parenthesis expression. Note that +point must be on the opening brace or parenthesis of the expression +you want to indent. + +@item @kbd{C-c C-q} (@code{c-indent-defun}) +@kindex C-c C-q +@findex c-indent-defun +@findex indent-defun (c-) +Indents the entire top-level function, class or macro definition +encompassing point. It leaves point unchanged. This function can't be +used to reindent a nested brace construct, such as a nested class or +function, or a Java method. The top-level construct being reindented +must be complete, i.e. it must have both a beginning brace and an ending +brace. + +@item @kbd{C-M-\} (@code{indent-region}) +@kindex C-M-\ +@findex indent-region +Indents an arbitrary region of code. This is a standard Emacs command, +tailored for C code in a @ccmode{} buffer. Note, of course, that point +and mark must delineate the region you want to indent. + +@item @kbd{C-M-h} (@code{c-mark-function}) +@kindex C-M-h +@findex c-mark-function +@findex mark-function (c-) +While not strictly an indentation command, this is useful for marking +the current top-level function or class definition as the current +region. As with @code{c-indent-defun}, this command operates on +top-level constructs, and can't be used to mark say, a Java method. +@end table + +These variables are also useful when indenting code: + +@defopt indent-tabs-mode +This is a standard Emacs variable that controls how line indentation +is composed. When it's non-@code{nil}, tabs can be used in a line's +indentation, otherwise only spaces are used. +@end defopt + +@defopt c-progress-interval +@vindex progress-interval (c-) +When indenting large regions of code, this variable controls how often a +progress message is displayed. Set this variable to @code{nil} to +inhibit the progress messages, or set it to an integer which is how +often (in seconds) progress messages are to be displayed. +@end defopt + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Comment Commands, Movement Commands, Indentation Commands, Commands +@comment node-name, next, previous, up +@section Comment Commands +@cindex comments (insertion of) +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@table @asis +@item @kbd{C-c C-c} (@code{comment-region}) +@kindex C-c C-c +@findex comment-region +This command comments out the lines that start in the region. With a +negative argument, it does the opposite - it deletes the comment +delimiters from these lines. @xref{Multi-Line Comments,,, emacs, GNU +Emacs Manual}, for fuller details. @code{comment-region} isn't +actually part of @ccmode{} - it is given a @ccmode{} binding for +convenience. + +@item @kbd{M-;} (@code{comment-dwim} or @code{indent-for-comment} @footnote{The name of this command varies between (X)Emacs versions.}) +@kindex M-; +@findex comment-dwim +@findex indent-for-comment +Insert a comment at the end of the current line, if none is there +already. Then reindent the comment according to @code{comment-column} +@ifclear XEMACS +(@pxref{Options for Comments,,, emacs, GNU Emacs Manual}) +@end ifclear +@ifset XEMACS +(@pxref{Comments,,, xemacs, XEmacs User's Manual}) +@end ifset +and the variables below. Finally, position the point after the +comment starter. @kbd{C-u M-;} kills any comment on the current line, +together with any whitespace before it. This is a standard Emacs +command, but @ccmode{} enhances it a bit with two variables: + +@defopt c-indent-comment-alist +@vindex indent-comment-alist (c-) +@vindex comment-column +This style variable allows you to vary the column that @kbd{M-;} puts +the comment at, depending on what sort of code is on the line, and +possibly the indentation of any similar comment on the preceding line. +It is an association list that maps different types of lines to +actions describing how they should be handled. If a certain line type +isn't present on the list then the line is indented to the column +specified by @code{comment-column}. + +See the documentation string for a full description of this +variable (use @kbd{C-h v c-indent-comment-alist}). +@end defopt + +@defopt c-indent-comments-syntactically-p +@vindex indent-comments-syntactically-p (c-) +Normally, when this style variable is @code{nil}, @kbd{M-;} will +indent comment-only lines according to @code{c-indent-comment-alist}, +just as it does with lines where other code precede the comments. +However, if you want it to act just like @key{TAB} for comment-only +lines you can get that by setting +@code{c-indent-comments-syntactically-p} to non-@code{nil}. + +If @code{c-indent-comments-syntactically-p} is non-@code{nil} then +@code{c-indent-comment-alist} won't be consulted at all for comment-only +lines. +@end defopt +@end table + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Movement Commands, Filling and Breaking, Comment Commands, Commands +@comment node-name, next, previous, up +@section Movement Commands +@cindex movement +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@ccmode{} contains some useful commands for moving around in C code. + +@table @asis +@item @kbd{C-M-a} (@code{c-beginning-of-defun}) +@itemx @kbd{C-M-e} (@code{c-end-of-defun}) +@findex c-beginning-of-defun +@findex c-end-of-defun +@vindex c-defun-tactic +@vindex defun-tactic (c-) + +Move to the beginning or end of the current or next function. Other +constructs (such as a structs or classes) which have a brace block +also count as ``functions'' here. To move over several functions, you +can give these commands a repeat count. + +The start of a function is at its header. The end of the function is +after its closing brace, or after the semicolon of a construct (such +as a @code{struct}) which doesn't end at the brace. These two +commands try to leave point at the beginning of a line near the actual +start or end of the function. This occasionally causes point not to +move at all. + +By default, these commands will recognize functions contained within a +@dfn{declaration scope} such as a C++ @code{class} or @code{namespace} +construct, should the point start inside it. If @ccmode fails to find +function beginnings or ends inside the current declaration scope, it +will search the enclosing scopes. If you want @ccmode to recognize +functions only at the top level@footnote{this was @ccmode{}'s +behavior prior to version 5.32.}, set @code{c-defun-tactic} to +@code{t}. + +These functions are analogous to the Emacs built-in commands +@code{beginning-of-defun} and @code{end-of-defun}, except they +eliminate the constraint that the top-level opening brace of the defun +must be in column zero. See @ref{Defuns,,,@emacsman{}, +@emacsmantitle{}}, for more information. + +@item @kbd{C-M-a} (AWK Mode) (@code{c-awk-beginning-of-defun}) +@itemx @kbd{C-M-e} (AWK Mode) (@code{c-awk-end-of-defun}) +@kindex C-M-a (AWK Mode) +@kindex C-M-e (AWK Mode) +@findex c-awk-beginning-of-defun +@findex awk-beginning-of-defun (c-) +@findex c-awk-end-of-defun +@findex awk-end-of-defun (c-) +Move to the beginning or end of the current or next AWK defun. These +commands can take prefix-arguments, their functionality being entirely +equivalent to @code{beginning-of-defun} and @code{end-of-defun}. + +AWK Mode @dfn{defuns} are either pattern/action pairs (either of which +might be implicit) or user defined functions. Having the @samp{@{} and +@samp{@}} (if there are any) in column zero, as is suggested for some +modes, is neither necessary nor helpful in AWK mode. + +@item @kbd{M-a} (@code{c-beginning-of-statement}) +@itemx @kbd{M-e} (@code{c-end-of-statement}) +@kindex M-a +@kindex M-e +@findex c-beginning-of-statement +@findex c-end-of-statement +@findex beginning-of-statement (c-) +@findex end-of-statement (c-) +Move to the beginning or end of the innermost C statement. If point +is already there, move to the next beginning or end of a statement, +even if that means moving into a block. (Use @kbd{C-M-b} or +@kbd{C-M-f} to move over a balanced block.) A prefix argument @var{n} +means move over @var{n} statements. + +If point is within or next to a comment or a string which spans more +than one line, these commands move by sentences instead of statements. + +When called from a program, these functions take three optional +arguments: the repetition count, a buffer position limit which is the +farthest back to search for the syntactic context, and a flag saying +whether to do sentence motion in or near comments and multiline +strings. + +@item @kbd{C-c C-u} (@code{c-up-conditional}) +@kindex C-c C-u +@findex c-up-conditional +@findex up-conditional (c-) +Move back to the containing preprocessor conditional, leaving the mark +behind. A prefix argument acts as a repeat count. With a negative +argument, move forward to the end of the containing preprocessor +conditional. + +@samp{#elif} is treated like @samp{#else} followed by @samp{#if}, so the +function stops at them when going backward, but not when going +forward. + +This key sequence is not bound in AWK Mode, which doesn't have +preprocessor statements. + +@item @kbd{M-x c-up-conditional-with-else} +@findex c-up-conditional-with-else +@findex up-conditional-with-else (c-) +A variety of @code{c-up-conditional} that also stops at @samp{#else} +lines. Normally those lines are ignored. + +@item @kbd{M-x c-down-conditional} +@findex c-down-conditional +@findex down-conditional (c-) +Move forward into the next nested preprocessor conditional, leaving +the mark behind. A prefix argument acts as a repeat count. With a +negative argument, move backward into the previous nested preprocessor +conditional. + +@samp{#elif} is treated like @samp{#else} followed by @samp{#if}, so the +function stops at them when going forward, but not when going backward. + +@item @kbd{M-x c-down-conditional-with-else} +@findex c-down-conditional-with-else +@findex down-conditional-with-else (c-) +A variety of @code{c-down-conditional} that also stops at @samp{#else} +lines. Normally those lines are ignored. + +@item @kbd{C-c C-p} (@code{c-backward-conditional}) +@itemx @kbd{C-c C-n} (@code{c-forward-conditional}) +@kindex C-c C-p +@kindex C-c C-n +@findex c-backward-conditional +@findex c-forward-conditional +@findex backward-conditional (c-) +@findex forward-conditional (c-) +Move backward or forward across a preprocessor conditional, leaving +the mark behind. A prefix argument acts as a repeat count. With a +negative argument, move in the opposite direction. + +These key sequences are not bound in AWK Mode, which doesn't have +preprocessor statements. + +@item @kbd{M-x c-backward-into-nomenclature} +@itemx @kbd{M-x c-forward-into-nomenclature} +@findex c-backward-into-nomenclature +@findex c-forward-into-nomenclature +@findex backward-into-nomenclature (c-) +@findex forward-into-nomenclature (c-) +A popular programming style, especially for object-oriented languages +such as C++ is to write symbols in a mixed case format, where the +first letter of each word is capitalized, and not separated by +underscores. E.g. @samp{SymbolsWithMixedCaseAndNoUnderlines}. + +These commands move backward or forward to the beginning of the next +capitalized word. With prefix argument @var{n}, move @var{n} times. +If @var{n} is negative, move in the opposite direction. + +Note that these two commands have been superseded by +@code{c-subword-mode}, which you should use instead. @xref{Subword +Movement}. They might be removed from a future release of @ccmode{}. +@end table + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Filling and Breaking, Minor Modes, Movement Commands, Commands +@comment node-name, next, previous, up +@section Filling and Line Breaking Commands +@cindex text filling +@cindex line breaking +@cindex comment handling +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Since there's a lot of normal text in comments and string literals, +@ccmode{} provides features to edit these like in text mode. The goal +is to do it seamlessly, i.e. you can use auto fill mode, sentence and +paragraph movement, paragraph filling, adaptive filling etc. wherever +there's a piece of normal text without having to think much about it. +@ccmode{} keeps the indentation, fixes suitable comment line prefixes, +and so on. + +You can configure the exact way comments get filled and broken, and +where Emacs does auto-filling (see @pxref{Custom Filling and +Breaking}). Typically, the style system (@pxref{Styles}) will have +set this up for you, so you probably won't have to bother. + +@findex auto-fill-mode +@cindex Auto Fill mode +@cindex paragraph filling +Line breaks are by default handled (almost) the same regardless of +whether they are made by auto fill mode (@pxref{Auto Fill,,, +@emacsman{}, @emacsmantitle{}}), by paragraph filling (e.g. with +@kbd{M-q}), or explicitly with @kbd{M-j} or similar methods. In +string literals, the new line gets the same indentation as the +previous nonempty line.@footnote{You can change this default by +setting the @code{string} syntactic symbol (@pxref{Syntactic Symbols} +and @pxref{Customizing Indentation})}. + +@table @asis +@item @kbd{M-q} (@code{c-fill-paragraph}) +@kindex M-q +@findex c-fill-paragraph +@findex fill-paragraph (c-) +@cindex Javadoc markup +@cindex Pike autodoc markup +This command fills multiline string literals and both block +and line style comments. In Java buffers, the Javadoc markup words +are recognized as paragraph starters. The line oriented Pike autodoc +markup words are recognized in the same way in Pike mode. + +The formatting of the starters (@code{/*}) and enders (@code{*/}) of +block comments are kept as they were before the filling. I.e., if +either the starter or ender were on a line of its own, then it stays +on its own line; conversely, if the delimiter has comment text on its +line, it keeps at least one word of that text with it on the line. + +This command is the replacement for @code{fill-paragraph} in @ccmode{} +buffers. + +@item @kbd{M-j} (@code{c-indent-new-comment-line}) +@kindex M-j +@findex c-indent-new-comment-line +@findex indent-new-comment-line (c-) +This breaks the current line at point and indents the new line. If +point was in a comment, the new line gets the proper comment line +prefix. If point was inside a macro, a backslash is inserted before +the line break. It is the replacement for +@code{indent-new-comment-line}. + +@item @kbd{M-x c-context-line-break} +@findex c-context-line-break +@findex context-line-break (c-) +Insert a line break suitable to the context: If the point is inside a +comment, the new line gets the suitable indentation and comment line +prefix like @code{c-indent-new-comment-line}. In normal code it's +indented like @code{newline-and-indent} would do. In macros it acts +like @code{newline-and-indent} but additionally inserts and optionally +aligns the line ending backslash so that the macro remains unbroken. +@xref{Custom Macros}, for details about the backslash alignment. In a +string, a backslash is inserted only if the string is within a +macro@footnote{In GCC, unescaped line breaks within strings are +valid.}. + +This function is not bound to a key by default, but it's intended to be +used on the @kbd{RET} key. If you like the behavior of +@code{newline-and-indent} on @kbd{RET}, you should consider switching to +this function. @xref{Sample .emacs File}. + +@item @kbd{M-x c-context-open-line} +@findex c-context-open-line +@findex context-open-line (c-) +This is to @kbd{C-o} (@kbd{M-x open-line}) as +@code{c-context-line-break} is to @kbd{RET}. I.e. it works just like +@code{c-context-line-break} but leaves the point before the inserted +line break. +@end table + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Minor Modes, Electric Keys, Filling and Breaking, Commands +@comment node-name, next, previous, up +@section Minor Modes +@cindex Minor Modes +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@ccmode{} contains several minor-mode-like features that you might +find useful while writing new code or editing old code: + +@table @asis +@item electric mode +When this is enabled, certain visible characters cause reformatting as +they are typed. This is normally helpful, but can be a nuisance when +editing chaotically formatted code. It can also be disconcerting, +especially for users who are new to @ccmode{}. +@item auto-newline mode +This automatically inserts newlines where you'd probably want to type +them yourself, e.g. after typing @samp{@}}s. Its action is suppressed +when electric mode is disabled. +@item hungry-delete mode +This lets you delete a contiguous block of whitespace with a single +key - for example, the newline and indentation just inserted by +auto-newline when you want to back up and write a comment after the +last statement. +@item subword mode +This mode makes basic word movement commands like @kbd{M-f} +(@code{forward-word}) and @kbd{M-b} (@code{backward-word}) treat the +parts of sillycapsed symbols as different words. +E.g. @samp{NSGraphicsContext} is treated as three words @samp{NS}, +@samp{Graphics}, and @samp{Context}. +@item syntactic-indentation mode +When this is enabled (which it normally is), indentation commands such +as @kbd{C-j} indent lines of code according to their syntactic +structure. Otherwise, a line is simply indented to the same level as +the previous one and @kbd{@key{TAB}} adjusts the indentation in steps +of `c-basic-offset'. +@end table + +Full details on how these minor modes work are at @ref{Electric Keys}, +@ref{Auto-newlines}, @ref{Hungry WS Deletion}, @ref{Subword Movement}, +and @ref{Indentation Engine Basics}. + +You can toggle each of these minor modes on and off, and you can +configure @ccmode{} so that it starts up with your favorite +combination of them (@pxref{Sample .emacs File}). By default, when +you initialize a buffer, electric mode and syntactic-indentation mode +are enabled but the other two modes are disabled. + +@ccmode{} displays the current state of the first four of these minor +modes on the mode line by appending letters to the major mode's name, +one letter for each enabled minor mode - @samp{l} for electric mode, +@samp{a} for auto-newline mode, @samp{h} for hungry delete mode, and +@samp{w} for subword mode. If all these modes were enabled, you'd see +@samp{C/lahw}@footnote{The @samp{C} would be replaced with the name of +the language in question for the other languages @ccmode{} supports.}. + +Here are the commands to toggle these modes: + +@table @asis +@item @kbd{C-c C-l} (@code{c-toggle-electric-state}) +@kindex C-c C-l +@findex c-toggle-electric-state +@findex toggle-electric-state (c-) +Toggle electric minor mode. When the command turns the mode off, it +also suppresses auto-newline mode. + +@item @kbd{C-c C-a} (@code{c-toggle-auto-newline}) +@kindex C-c C-a +@findex c-toggle-auto-newline +@findex toggle-auto-newline (c-) +Toggle auto-newline minor mode. When the command turns the mode on, +it also enables electric minor mode. + +@item @kbd{M-x c-toggle-hungry-state}@footnote{Prior to @ccmode{} 5.31, this command was bound to @kbd{C-c C-d}.} +@findex c-toggle-hungry-state +@findex toggle-hungry-state (c-) +Toggle hungry-delete minor mode. + +@item @kbd{M-x c-toggle-auto-hungry-state}@footnote{Prior to @ccmode{} 5.31, this command was bound to @kbd{C-c C-t}.} +@findex c-toggle-auto-hungry-state +@findex toggle-auto-hungry-state (c-) +Toggle both auto-newline and hungry delete minor modes. + +@item @kbd{C-c C-w} (@code{M-x c-subword-mode}) +@kindex C-c C-w +@findex c-subword-mode +@findex subword-mode (c-) +Toggle subword mode. + +@item @kbd{M-x c-toggle-syntactic-indentation} +@findex c-toggle-syntactic-indentation +@findex toggle-syntactic-indentation (c-) +Toggle syntactic-indentation mode. +@end table + +Common to all the toggle functions above is that if they are called +programmatically, they take an optional numerical argument. A +positive value will turn on the minor mode (or both of them in the +case of @code{c-toggle-auto-hungry-state}) and a negative value will +turn it (or them) off. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Electric Keys, Auto-newlines, Minor Modes, Commands +@comment node-name, next, previous, up +@section Electric Keys and Keywords +@cindex electric characters +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Most punctuation keys provide @dfn{electric} behavior - as well as +inserting themselves they perform some other action, such as +reindenting the line. This reindentation saves you from having to +reindent a line manually after typing, say, a @samp{@}}. A few +keywords, such as @code{else}, also trigger electric action. + +You can inhibit the electric behavior described here by disabling +electric minor mode (@pxref{Minor Modes}). + +Common to all these keys is that they only behave electrically when +used in normal code (as contrasted with getting typed in a string +literal or comment). Those which cause re-indentation do so only when +@code{c-syntactic-indentation} has a non-@code{nil} value (which it +does by default). + +These keys and keywords are: +@c ACM, 2004/8/24: c-electric-pound doesn't check c-s-i: this is more +@c like a bug in the code than a bug in this document. It'll get +@c fixed in the code sometime. + +@table @kbd +@item # +@kindex # +@findex c-electric-pound +@findex electric-pound (c-) +@vindex c-electric-pound-behavior +@vindex electric-pound-behavior (c-) +Pound (bound to @code{c-electric-pound}) is electric when typed as the +first non-whitespace character on a line and not within a macro +definition. In this case, the variable @code{c-electric-pound-behavior} +is consulted for the electric behavior. This variable takes a list +value, although the only element currently defined is @code{alignleft}, +which tells this command to force the @samp{#} character into column +zero. This is useful for entering preprocessor macro definitions. + +Pound is not electric in AWK buffers, where @samp{#} starts a comment, +and is bound to @code{self-insert-command} like any typical printable +character. +@c ACM, 2004/8/24: Change this (and the code) to do AWK comment +@c reindentation. + +@item * +@kindex * +@itemx / +@kindex / +@findex c-electric-star +@findex electric-star (c-) +@findex c-electric-slash +@findex electric-slash (c-) +A star (bound to @code{c-electric-star}) or a slash +(@code{c-electric-slash}) causes reindentation when you type it as the +second component of a C style block comment opener (@samp{/*}) or a +C++ line comment opener (@samp{//}) respectively, but only if the +comment opener is the first thing on the line (i.e. there's only +whitespace before it). + +Additionally, you can configure @ccmode{} so that typing a slash at +the start of a line within a block comment will terminate the +comment. You don't need to have electric minor mode enabled to get +this behavior. @xref{Clean-ups}. + +In AWK mode, @samp{*} and @samp{/} do not delimit comments and are not +electric. + +@item < +@kindex < +@itemx > +@kindex > +@findex c-electric-lt-gt +@findex electric-lt-gt (c-) +A less-than or greater-than sign (bound to @code{c-electric-lt-gt}) is +electric in two circumstances: when it is an angle bracket in a C++ +@samp{template} declaration (and similar constructs in other +languages) and when it is the second of two @kbd{<} or @kbd{>} +characters in a C++ style stream operator. In either case, the line +is reindented. Angle brackets in C @samp{#include} directives are not +electric. + +@item ( +@kindex ( +@itemx ) +@kindex ) +@findex c-electric-paren +@findex electric-paren (c-) +The normal parenthesis characters @samp{(} and @samp{)} (bound to +@code{c-electric-paren}) reindent the current line. This is useful +for getting the closing parenthesis of an argument list aligned +automatically. + +You can also configure @ccmode{} to insert a space automatically +between a function name and the @samp{(} you've just typed, and to +remove it automatically after typing @samp{)}, should the argument +list be empty. You don't need to have electric minor mode enabled to +get these actions. @xref{Clean-ups}. + +@item @{ +@kindex @{ +@itemx @} +@kindex @} +@findex c-electric-brace +@findex electric-brace (c-) +Typing a brace (bound to @code{c-electric-brace}) reindents the +current line. Also, one or more newlines might be inserted if +auto-newline minor mode is enabled. @xref{Auto-newlines}. +Additionally, you can configure @ccmode{} to compact excess whitespace +inserted by auto-newline mode in certain circumstances. +@xref{Clean-ups}. + +@item : +@kindex : +@findex c-electric-colon +@findex electric-colon (c-) +Typing a colon (bound to @code{c-electric-colon}) reindents the +current line. Additionally, one or more newlines might be inserted if +auto-newline minor mode is enabled. @xref{Auto-newlines}. If you +type a second colon immediately after such an auto-newline, by default +the whitespace between the two colons is removed, leaving a C++ scope +operator. @xref{Clean-ups}. + +If you prefer, you can insert @samp{::} in a single operation, +avoiding all these spurious reindentations, newlines, and clean-ups. +@xref{Other Commands}. + +@item ; +@kindex ; +@itemx , +@kindex , +@findex c-electric-semi&comma +@findex electric-semi&comma (c-) +Typing a semicolon or comma (bound to @code{c-electric-semi&comma}) +reindents the current line. Also, a newline might be inserted if +auto-newline minor mode is enabled. @xref{Auto-newlines}. +Additionally, you can configure @ccmode{} so that when auto-newline +has inserted whitespace after a @samp{@}}, it will be removed again +when you type a semicolon or comma just after it. @xref{Clean-ups}. + +@end table + +@deffn Command c-electric-continued-statement +@findex electric-continued-statement (c-) + +Certain keywords are electric, causing reindentation when they are +preceded only by whitespace on the line. The keywords are those that +continue an earlier statement instead of starting a new one: +@code{else}, @code{while}, @code{catch} (only in C++ and Java) and +@code{finally} (only in Java). + +An example: + +@example +@group +for (i = 0; i < 17; i++) + if (a[i]) + res += a[i]->offset; +else +@end group +@end example + +Here, the @code{else} should be indented like the preceding @code{if}, +since it continues that statement. @ccmode{} will automatically +reindent it after the @code{else} has been typed in full, since only +then is it possible to decide whether it's a new statement or a +continuation of the preceding @code{if}. + +@vindex abbrev-mode +@findex abbrev-mode +@cindex Abbrev mode +@ccmode{} uses Abbrev mode (@pxref{Abbrevs,,, @emacsman{}, @emacsmantitle{}}) +to accomplish this. It's therefore turned on by default in all language +modes except IDL mode, since CORBA IDL doesn't have any statements. +@end deffn + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Auto-newlines, Hungry WS Deletion, Electric Keys, Commands +@comment node-name, next, previous, up +@section Auto-newline Insertion +@cindex auto-newline +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +When you have @dfn{Auto-newline minor mode} enabled (@pxref{Minor +Modes}), @ccmode{} inserts newlines for you automatically (in certain +syntactic contexts) when you type a left or right brace, a colon, a +semicolon, or a comma. Sometimes a newline appears before the +character you type, sometimes after it, sometimes both. + +Auto-newline only triggers when the following conditions hold: + +@itemize @bullet +@item +Auto-newline minor mode is enabled, as evidenced by the indicator +@samp{a} after the mode name on the mode line (e.g. @samp{C/a} or +@samp{C/la}). + +@item +The character was typed at the end of a line, or with only whitespace +after it, and possibly a @samp{\} escaping the newline. + +@item +The character is not on its own line already. (This applies only to +insertion of a newline @emph{before} the character.) + +@item +@cindex literal +@cindex syntactic whitespace +The character was not typed inside of a literal @footnote{A +@dfn{literal} is defined as any comment, string, or preprocessor macro +definition. These constructs are also known as @dfn{syntactic +whitespace} since they are usually ignored when scanning C code.}. + +@item +No numeric argument was supplied to the command (i.e. it was typed as +normal, with no @kbd{C-u} prefix). +@end itemize + +You can configure the precise circumstances in which newlines get +inserted (see @pxref{Custom Auto-newlines}). Typically, the style +system (@pxref{Styles}) will have set this up for you, so you probably +won't have to bother. + +Sometimes @ccmode{} inserts an auto-newline where you don't want one, +such as after a @samp{@}} when you're about to type a @samp{;}. +Hungry deletion can help here (@pxref{Hungry WS Deletion}), or you can +activate an appropriate @dfn{clean-up}, which will remove the excess +whitespace after you've typed the @samp{;}. See @ref{Clean-ups} for a +full description. See also @ref{Electric Keys} for a summary of +clean-ups listed by key. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Hungry WS Deletion, Subword Movement, Auto-newlines, Commands +@comment node-name, next, previous, up +@section Hungry Deletion of Whitespace +@cindex hungry-deletion +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +If you want to delete an entire block of whitespace at point, you can +use @dfn{hungry deletion}. This deletes all the contiguous whitespace +either before point or after point in a single operation. +``Whitespace'' here includes tabs and newlines, but not comments or +preprocessor commands. Hungry deletion can markedly cut down on the +number of times you have to hit deletion keys when, for example, +you've made a mistake on the preceding line and have already pressed +@kbd{C-j}. + +Hungry deletion is a simple feature that some people find extremely +useful. In fact, you might find yourself wanting it in @strong{all} +your editing modes! + +Loosely speaking, in what follows, @dfn{@key{DEL}} means ``the +backspace key'' and @dfn{@key{DELETE}} means ``the forward delete +key''. This is discussed in more detail below. + +There are two different ways you can use hungry deletion: + +@table @asis +@item Using @dfn{Hungry Delete Mode} with @kbd{@key{DEL}} and @kbd{C-d} +Here you toggle Hungry Delete minor mode with @kbd{M-x +c-toggle-hungry-state}@footnote{Prior to @ccmode{} 5.31, this command +was bound to @kbd{C-c C-d}. @kbd{C-c C-d} is now the default binding +for @code{c-hungry-delete-forward}.} (@pxref{Minor Modes}.) This +makes @kbd{@key{DEL}} and @kbd{C-d} do backwards and forward hungry +deletion. + +@table @asis +@item @kbd{@key{DEL}} (@code{c-electric-backspace}) +@kindex DEL +@findex c-electric-backspace +@findex electric-backspace (c-) +This command is run by default when you hit the @kbd{DEL} key. When +hungry delete mode is enabled, it deletes any amount of whitespace in +the backwards direction. Otherwise, or when used with a prefix +argument or in a literal (@pxref{Auto-newlines}), the command just +deletes backwards in the usual way. (More precisely, it calls the +function contained in the variable @code{c-backspace-function}, +passing it the prefix argument, if any.) + +@item @code{c-backspace-function} +@vindex c-backspace-function +@vindex backspace-function (c-) +@findex backward-delete-char-untabify +Hook that gets called by @code{c-electric-backspace} when it doesn't +do an ``electric'' deletion of the preceding whitespace. The default +value is @code{backward-delete-char-untabify} +(@pxref{Deletion,,,@lispref{}, @lispreftitle{}}, the function which +deletes a single character. + +@item @kbd{C-d} (@code{c-electric-delete-forward}) +@kindex C-d +@findex c-electric-delete-forward +@findex electric-delete-forward (c-) +This function, which is bound to @kbd{C-d} by default, works just like +@code{c-electric-backspace} but in the forward direction. When it +doesn't do an ``electric'' deletion of the following whitespace, it +just does @code{delete-char}, more or less. (Strictly speaking, it +calls the function in @code{c-delete-function} with the prefix +argument.) + +@item @code{c-delete-function} +@vindex c-delete-function +@vindex delete-function (c-) +@findex delete-char +Hook that gets called by @code{c-electric-delete-forward} when it +doesn't do an ``electric'' deletion of the following whitespace. The +default value is @code{delete-char}. +@end table + +@item Using Distinct Bindings +The other (newer and recommended) way to use hungry deletion is to +perform @code{c-hungry-delete-backwards} and +@code{c-hungry-delete-forward} directly through their key sequences +rather than using the minor mode toggling. + +@table @asis +@item @kbd{C-c C-@key{DEL}}, or @kbd{C-c @key{DEL}} (@code{c-hungry-delete-backwards})@footnote{This command was formerly known as @code{c-hungry-backspace}.} +@kindex C-c C- +@kindex C-c +@kindex C-c C-DEL +@kindex C-c DEL +@findex c-hungry-delete-backwards +@findex hungry-delete-backwards (c-) +Delete any amount of whitespace in the backwards direction (regardless +whether hungry-delete mode is enabled or not). This command is bound +to both @kbd{C-c C-@key{DEL}} and @kbd{C-c @key{DEL}}, since the more +natural one, @kbd{C-c C-@key{DEL}}, is sometimes difficult to type at +a character terminal. + +@item @kbd{C-c C-d}, @kbd{C-c C-@key{DELETE}}, or @kbd{C-c @key{DELETE}} (@code{c-hungry-delete-forward}) +@kindex C-c C-d +@kindex C-c C- +@kindex C-c +@findex c-hungry-delete-forward +@findex hungry-delete-forward (c-) +Delete any amount of whitespace in the forward direction (regardless +whether hungry-delete mode is enabled or not). This command is bound +to both @kbd{C-c C-@key{DELETE}} and @kbd{C-c @key{DELETE}} for the +same reason as for @key{DEL} above. +@end table +@end table + +@kindex +@kindex + +When we talk about @kbd{@key{DEL}}, and @kbd{@key{DELETE}} above, we +actually do so without connecting them to the physical keys commonly +known as @key{Backspace} and @key{Delete}. The default bindings to +those two keys depends on the flavor of (X)Emacs you are using. + +@findex c-electric-delete +@findex electric-delete (c-) +@findex c-hungry-delete +@findex hungry-delete (c-) +@vindex delete-key-deletes-forward +In XEmacs 20.3 and beyond, the @key{Backspace} key is bound to +@code{c-electric-backspace} and the @key{Delete} key is bound to +@code{c-electric-delete}. You control the direction it deletes in by +setting the variable @code{delete-key-deletes-forward}, a standard +XEmacs variable. +@c This variable is encapsulated by XEmacs's (defsubst delete-forward-p ...). +When this variable is non-@code{nil}, @code{c-electric-delete} will do +forward deletion with @code{c-electric-delete-forward}, otherwise it +does backward deletion with @code{c-electric-backspace}. Similarly, +@kbd{C-c @key{Delete}} and @kbd{C-c C-@key{Delete}} are bound to +@code{c-hungry-delete} which is controlled in the same way by +@code{delete-key-deletes-forward}. + +@findex normal-erase-is-backspace-mode + +Emacs 21 and later automatically binds @key{Backspace} and +@key{Delete} to @kbd{DEL} and @kbd{C-d} according to your environment, +and @ccmode{} extends those bindings to @kbd{C-c C-@key{Backspace}} +etc. If you need to change the bindings through +@code{normal-erase-is-backspace-mode} then @ccmode{} will also adapt +its extended bindings accordingly. + +In earlier (X)Emacs versions, @ccmode{} doesn't bind either +@key{Backspace} or @key{Delete} directly. Only the key codes +@kbd{DEL} and @kbd{C-d} are bound, and it's up to the default bindings +to map the physical keys to them. You might need to modify this +yourself if the defaults are unsuitable. + +Getting your @key{Backspace} and @key{Delete} keys properly set up can +sometimes be tricky. The information in @ref{DEL Does Not +Delete,,,emacs, GNU Emacs Manual}, might be helpful if you're having +trouble with this in GNU Emacs. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Subword Movement, Other Commands, Hungry WS Deletion, Commands +@comment node-name, next, previous, up +@section Subword Movement and Editing +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex nomenclature +@cindex subword +In spite of the GNU Coding Standards, it is popular to name a symbol +by mixing uppercase and lowercase letters, e.g. @samp{GtkWidget}, +@samp{EmacsFrameClass}, or @samp{NSGraphicsContext}. Here we call +these mixed case symbols @dfn{nomenclatures}. Also, each capitalized +(or completely uppercase) part of a nomenclature is called a +@dfn{subword}. Here are some examples: + +@multitable {@samp{NSGraphicsContext}} {@samp{NS}, @samp{Graphics}, and @samp{Context}} +@headitem Nomenclature + @tab Subwords +@item @samp{GtkWindow} + @tab @samp{Gtk} and @samp{Window} +@item @samp{EmacsFrameClass} + @tab @samp{Emacs}, @samp{Frame}, and @samp{Class} +@item @samp{NSGraphicsContext} + @tab @samp{NS}, @samp{Graphics}, and @samp{Context} +@end multitable + +The subword minor mode replaces the basic word oriented movement and +editing commands with variants that recognize subwords in a +nomenclature and treat them as separate words: + +@findex c-forward-subword +@findex forward-subword (c-) +@findex c-backward-subword +@findex backward-subword (c-) +@findex c-mark-subword +@findex mark-subword (c-) +@findex c-kill-subword +@findex kill-subword (c-) +@findex c-backward-kill-subword +@findex backward-kill-subword (c-) +@findex c-transpose-subwords +@findex transpose-subwords (c-) +@findex c-capitalize-subword +@findex capitalize-subword (c-) +@findex c-upcase-subword +@findex upcase-subword (c-) +@findex c-downcase-subword +@findex downcase-subword (c-) +@multitable @columnfractions .20 .40 .40 +@headitem Key @tab Word oriented command @tab Subword oriented command +@item @kbd{M-f} @tab @code{forward-word} @tab @code{c-forward-subword} +@item @kbd{M-b} @tab @code{backward-word} @tab @code{c-backward-subword} +@item @kbd{M-@@} @tab @code{mark-word} @tab @code{c-mark-subword} +@item @kbd{M-d} @tab @code{kill-word} @tab @code{c-kill-subword} +@item @kbd{M-DEL} @tab @code{backward-kill-word} @tab @code{c-backward-kill-subword} +@item @kbd{M-t} @tab @code{transpose-words} @tab @code{c-transpose-subwords} +@item @kbd{M-c} @tab @code{capitalize-word} @tab @code{c-capitalize-subword} +@item @kbd{M-u} @tab @code{upcase-word} @tab @code{c-upcase-subword} +@item @kbd{M-l} @tab @code{downcase-word} @tab @code{c-downcase-subword} +@end multitable + +Note that if you have changed the key bindings for the word oriented +commands in your @file{.emacs} or a similar place, the keys you have +configured are also used for the corresponding subword oriented +commands. + +Type @kbd{C-c C-w} to toggle subword mode on and off. To make the +mode turn on automatically, put the following code in your +@file{.emacs}: + +@example +(add-hook 'c-mode-common-hook + (lambda () (c-subword-mode 1))) +@end example + +As a bonus, you can also use @code{c-subword-mode} in non-@ccmode{} +buffers by typing @kbd{M-x c-subword-mode}. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Other Commands, , Subword Movement, Commands +@comment node-name, next, previous, up +@section Other Commands +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Here are the various other commands that didn't fit anywhere else: + +@table @asis +@item @kbd{C-c .} (@code{c-set-style}) +@kindex C-c . +@findex c-set-style +@findex set-style (c-) +Switch to the specified style in the current buffer. Use like this: + +@example +@kbd{C-c . @var{style-name} @key{RET}} +@end example + +You can use the @key{TAB} in the normal way to do completion on the +style name. Note that all style names are case insensitive, even the +ones you define yourself. + +Setting a style in this way does @emph{not} automatically reindent your +file. For commands that you can use to view the effect of your changes, +see @ref{Indentation Commands} and @ref{Filling and Breaking}. + +For details of the @ccmode{} style system, see @ref{Styles}. +@item @kbd{C-c :} (@code{c-scope-operator}) +@kindex C-c : +@findex c-scope-operator +@findex scope-operator (c-) +In C++, it is also sometimes desirable to insert the double-colon scope +operator without performing the electric behavior of colon insertion. +@kbd{C-c :} does just this. + +@item @kbd{C-c C-\} (@code{c-backslash-region}) +@kindex C-c C-\ +@findex c-backslash-region +@findex backslash-region (c-) +This function inserts and aligns or deletes end-of-line backslashes in +the current region. These are typically used in multi-line macros. + +With no prefix argument, it inserts any missing backslashes and aligns +them according to the @code{c-backslash-column} and +@code{c-backslash-max-column} variables. With a prefix argument, it +deletes any backslashes. + +The function does not modify blank lines at the start of the region. If +the region ends at the start of a line, it always deletes the backslash +(if any) at the end of the previous line. + +To customize the precise workings of this command, @ref{Custom Macros}. +@end table + +@noindent +The recommended line breaking function, @code{c-context-line-break} +(@pxref{Filling and Breaking}), is especially nice if you edit +multiline macros frequently. When used inside a macro, it +automatically inserts and adjusts the mandatory backslash at the end +of the line to keep the macro together, and it leaves the point at the +right indentation column for the code. Thus you can write code inside +macros almost exactly as you can elsewhere, without having to bother +with the trailing backslashes. + +@table @asis +@item @kbd{C-c C-e} (@code{c-macro-expand}) +@kindex C-c C-e +@findex c-macro-expand +@findex macro-expand (c-) +This command expands C, C++, Objective C or Pike macros in the region, +using an appropriate external preprocessor program. Normally it +displays its output in a temporary buffer, but if you give it a prefix +arg (with @kbd{C-u C-c C-e}) it will overwrite the original region +with the expansion. + +The command does not work in any of the other modes, and the key +sequence is not bound in these other modes. + +@code{c-macro-expand} isn't actually part of @ccmode{}, even though it +is bound to a @ccmode{} key sequence. If you need help setting it up +or have other problems with it, you can either read its source code or +ask for help in the standard (X)Emacs forums. +@end table + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Font Locking, Config Basics, Commands, Top +@comment node-name, next, previous, up +@chapter Font Locking +@cindex font locking +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex Font Lock mode + +@ccmode{} provides font locking for its supported languages by +supplying patterns for use with Font Lock mode. This means that you +get distinct faces on the various syntactic parts such as comments, +strings, keywords and types, which is very helpful in telling them +apart at a glance and discovering syntactic errors. @xref{Font +Lock,,, emacs, GNU Emacs Manual}, for ways to enable font locking in +@ccmode{} buffers. + +@strong{Please note:} The font locking in AWK mode is currently not +integrated with the rest of @ccmode{}. Only the last section of this +chapter, @ref{AWK Mode Font Locking}, applies to AWK. The other +sections apply to the other languages. + +@menu +* Font Locking Preliminaries:: +* Faces:: +* Doc Comments:: +* AWK Mode Font Locking:: +@end menu + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Font Locking Preliminaries, Faces, Font Locking, Font Locking +@comment node-name, next, previous, up +@section Font Locking Preliminaries +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The font locking for most of the @ccmode{} languages were provided +directly by the Font Lock package prior to version 5.30 of @ccmode{}. +In the transition to @ccmode{} the patterns have been reworked +completely and are applied uniformly across all the languages except AWK +mode, just like the indentation rules (although each language still has +some peculiarities of its own, of course). Since the languages +previously had completely separate font locking patterns, this means +that it's a bit different in most languages now. + +The main goal for the font locking in @ccmode{} is accuracy, to provide +a dependable aid in recognizing the various constructs. Some, like +strings and comments, are easy to recognize while others, like +declarations and types, can be very tricky. @ccmode{} can go to great +lengths to recognize declarations and casts correctly, especially when +the types aren't recognized by standard patterns. This is a fairly +demanding analysis which can be slow on older hardware, and it can +therefore be disabled by choosing a lower decoration level with the +variable @code{font-lock-maximum-decoration} (@pxref{Font Lock,,, +emacs, GNU Emacs Manual}). + +@vindex font-lock-maximum-decoration + +The decoration levels are used as follows: + +@enumerate +@comment 1 +@item +Minimal font locking: Fontify only comments, strings and preprocessor +directives (in the languages that use cpp). + +@comment 2 +@item +Fast font locking: In addition to level 1, fontify keywords, simple +types and declarations that are easy to recognize. The variables +@code{*-font-lock-extra-types} (where @samp{*} is the name of the +language) are used to recognize types (see below). Documentation +comments like Javadoc are fontified according to +@code{c-doc-comment-style} (@pxref{Doc Comments}). + +Use this if you think the font locking is too slow. It's the closest +corresponding level to level 3 in the old font lock patterns. + +@comment 3 +@item +Accurate font locking: Like level 2 but uses a different approach that +can recognize types and declarations much more accurately. The +@code{*-font-lock-extra-types} variables are still used, but user +defined types are recognized correctly anyway in most cases. Therefore +those variables should be fairly restrictive and not contain patterns +that are uncertain. + +@cindex Lazy Lock mode +@cindex Just-in-time Lock mode + +This level is designed for fairly modern hardware and a font lock +support mode like Lazy Lock or Just-in-time Lock mode that only +fontifies the parts that are actually shown. Fontifying the whole +buffer at once can easily get bothersomely slow even on contemporary +hardware. +@c ACM, 2005/8/28: There should be a page in the (X)Emacs manual +@c describing these support modes. There wasn't in the +@c fourteenth edition of the Emacs manual (released with Emacs 21.3). +@c There might be one in the Emacs CVS for 22.1. +@end enumerate + +@cindex user defined types +@cindex types, user defined + +Since user defined types are hard to recognize you can provide +additional regexps to match those you use: + +@defopt c-font-lock-extra-types +@defoptx c++-font-lock-extra-types +@defoptx objc-font-lock-extra-types +@defoptx java-font-lock-extra-types +@defoptx idl-font-lock-extra-types +@defoptx pike-font-lock-extra-types +For each language there's a variable @code{*-font-lock-extra-types}, +where @samp{*} stands for the language in question. It contains a list +of regexps that matches identifiers that should be recognized as types, +e.g. @samp{\\sw+_t} to recognize all identifiers ending with @samp{_t} +as is customary in C code. Each regexp should not match more than a +single identifier. + +The default values contain regexps for many types in standard runtime +libraries that are otherwise difficult to recognize, and patterns for +standard type naming conventions like the @samp{_t} suffix in C and C++. +Java, Objective-C and Pike have as a convention to start class names +with capitals, so there are patterns for that in those languages. + +Despite the names of these variables, they are not only used for +fontification but in other places as well where @ccmode{} needs to +recognize types. +@end defopt + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Faces, Doc Comments, Font Locking Preliminaries, Font Locking +@comment node-name, next, previous, up +@section Faces +@cindex faces +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@ccmode{} attempts to use the standard faces for programming languages +in accordance with their intended purposes as far as possible. No extra +faces are currently provided, with the exception of a replacement face +@code{c-invalid-face} for emacsen that don't provide +@code{font-lock-warning-face}. + +@itemize @bullet +@item +@vindex font-lock-comment-face +Normal comments are fontified in @code{font-lock-comment-face}. + +@item +@vindex font-lock-doc-face +@vindex font-lock-doc-string-face +@vindex font-lock-comment-face +Comments that are recognized as documentation (@pxref{Doc Comments}) +get @code{font-lock-doc-face} (Emacs) or +@code{font-lock-doc-string-face} (XEmacs) if those faces exist. If +they don't then @code{font-lock-comment-face} is used. + +@item +@vindex font-lock-string-face +String and character literals are fontified in +@code{font-lock-string-face}. + +@item +@vindex font-lock-keyword-face +Keywords are fontified with @code{font-lock-keyword-face}. + +@item +@vindex font-lock-function-name-face +@code{font-lock-function-name-face} is used for function names in +declarations and definitions, and classes in those contexts. It's also +used for preprocessor defines with arguments. + +@item +@vindex font-lock-variable-name-face +Variables in declarations and definitions, and other identifiers in such +variable contexts, get @code{font-lock-variable-name-face}. It's also +used for preprocessor defines without arguments. + +@item +@vindex font-lock-constant-face +@vindex font-lock-reference-face +Builtin constants are fontified in @code{font-lock-constant-face} if it +exists, @code{font-lock-reference-face} otherwise. As opposed to the +preceding two faces, this is used on the names in expressions, and it's +not used in declarations, even if there happen to be a @samp{const} in +them somewhere. + +@item +@vindex font-lock-type-face +@code{font-lock-type-face} is put on types (both predefined and user +defined) and classes in type contexts. + +@item +@vindex font-lock-constant-face +@vindex font-lock-reference-face +Label identifiers get @code{font-lock-constant-face} if it exists, +@code{font-lock-reference-face} otherwise. + +@item +Name qualifiers and identifiers for scope constructs are fontified like +labels. + +@item +Special markup inside documentation comments are also fontified like +labels. + +@item +@vindex font-lock-preprocessor-face +@vindex font-lock-builtin-face +@vindex font-lock-reference-face +Preprocessor directives get @code{font-lock-preprocessor-face} if it +exists (i.e. XEmacs). In Emacs they get @code{font-lock-builtin-face} +or @code{font-lock-reference-face}, for lack of a closer equivalent. + +@item +@vindex font-lock-warning-face +@vindex c-invalid-face +@vindex invalid-face (c-) +Some kinds of syntactic errors are fontified with +@code{font-lock-warning-face} in Emacs. In older XEmacs versions +there's no corresponding standard face, so there a special +@code{c-invalid-face} is used, which is defined to stand out sharply by +default. + +Note that it's not used for @samp{#error} or @samp{#warning} directives, +since those aren't syntactic errors in themselves. +@end itemize + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Doc Comments, AWK Mode Font Locking, Faces, Font Locking +@comment node-name, next, previous, up +@section Documentation Comments +@cindex documentation comments +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +There are various tools to supply documentation in the source as +specially structured comments, e.g. the standard Javadoc tool in Java. +@ccmode{} provides an extensible mechanism to fontify such comments and +the special markup inside them. + +@defopt c-doc-comment-style +@vindex doc-comment-style (c-) +This is a style variable that specifies which documentation comment +style to recognize, e.g. @code{javadoc} for Javadoc comments. + +The value may also be a list of styles, in which case all of them are +recognized simultaneously (presumably with markup cues that don't +conflict). + +The value may also be an association list to specify different comment +styles for different languages. The symbol for the major mode is then +looked up in the alist, and the value of that element is interpreted as +above if found. If it isn't found then the symbol `other' is looked up +and its value is used instead. + +The default value for @code{c-doc-comment-style} is +@w{@code{((java-mode . javadoc) (pike-mode . autodoc) (c-mode . gtkdoc))}}. + +Note that @ccmode{} uses this variable to set other variables that +handle fontification etc. That's done at mode initialization or when +you switch to a style which sets this variable. Thus, if you change it +in some other way, e.g. interactively in a CC Mode buffer, you will need +to do @kbd{M-x java-mode} (or whatever mode you're currently using) to +reinitialize. + +@findex c-setup-doc-comment-style +@findex setup-doc-comment-style (c-) +Note also that when @ccmode{} starts up, the other variables are +modified before the mode hooks are run. If you change this variable in +a mode hook, you'll have to call @code{c-setup-doc-comment-style} +afterwards to redo that work. +@end defopt + +@ccmode{} currently provides handing of the following doc comment +styles: + +@table @code +@item javadoc +@cindex Javadoc markup +Javadoc comments, the standard tool in Java. + +@item autodoc +@cindex Pike autodoc markup +For Pike autodoc markup, the standard in Pike. + +@item gtkdoc +@cindex GtkDoc markup +For GtkDoc markup, widely used in the Gnome community. +@end table + +The above is by no means complete. If you'd like to see support for +other doc comment styles, please let us know (@pxref{Mailing Lists and +Bug Reports}). + +You can also write your own doc comment fontification support to use +with @code{c-doc-comment-style}: Supply a variable or function +@code{*-font-lock-keywords} where @samp{*} is the name you want to use +in @code{c-doc-comment-style}. If it's a variable, it's prepended to +@code{font-lock-keywords}. If it's a function, it's called at mode +initialization and the result is prepended. For an example, see +@code{javadoc-font-lock-keywords} in @file{cc-fonts.el}. + +If you add support for another doc comment style, please consider +contributing it - send a note to @email{bug-cc-mode@@gnu.org}. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node AWK Mode Font Locking, , Doc Comments, Font Locking +@comment node-name, next, previous, up +@section AWK Mode Font Locking +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The general appearance of font-locking in AWK mode is much like in any +other programming mode. @xref{Faces For Font Lock,,,elisp, GNU Emacs +Lisp Reference Manual}. + +The following faces are, however, used in a non-standard fashion in +AWK mode: + +@table @asis +@item @code{font-lock-variable-name-face} +This face was intended for variable declarations. Since variables are +not declared in AWK, this face is used instead for AWK system +variables (such as @code{NF}) and ``Special File Names'' (such as +@code{"/dev/stderr"}). + +@item @code{font-lock-builtin-face} (Emacs)/@code{font-lock-preprocessor-face} (XEmacs) +This face is normally used for preprocessor directives in @ccmode{}. +There are no such things in AWK, so this face is used instead for +standard functions (such as @code{match}). + +@item @code{font-lock-string-face} +As well as being used for strings, including localizable strings, +(delimited by @samp{"} and @samp{_"}), this face is also used for AWK +regular expressions (delimited by @samp{/}). + +@item @code{font-lock-warning-face} (Emacs)/@code{c-invalid-face} (XEmacs) +This face highlights the following syntactically invalid AWK +constructs: + +@itemize @bullet +@item +An unterminated string or regular expression. Here the opening +delimiter (@samp{"} or @samp{/} or @samp{_"}) is displayed in +@code{font-lock-warning-face}. This is most noticeable when typing in a +new string/regular expression into a buffer, when the warning-face +serves as a continual reminder to terminate the construct. + +AWK mode fontifies unterminated strings/regular expressions +differently from other modes: Only the text up to the end of the line +is fontified as a string (escaped newlines being handled correctly), +rather than the text up to the next string quote. + +@item +A space between the function name and opening parenthesis when calling +a user function. The last character of the function name and the +opening parenthesis are highlighted. This font-locking rule will +spuriously highlight a valid concatenation expression where an +identifier precedes a parenthesized expression. Unfortunately. + +@item +Whitespace following the @samp{\} in what otherwise looks like an +escaped newline. The @samp{\} is highlighted. +@end itemize +@end table + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Config Basics, Custom Filling and Breaking, Font Locking, Top +@comment node-name, next, previous, up +@chapter Configuration Basics +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex Emacs Initialization File +@cindex Configuration +You configure @ccmode{} by setting Lisp variables and calling (and +perhaps writing) Lisp functions@footnote{DON'T PANIC!!! This isn't +difficult.}, which is usually done by adding code to an Emacs +initialization file. This file might be @file{site-start.el} or +@file{.emacs} or @file{init.el} or @file{default.el} or perhaps some +other file. @xref{Init File,,,@emacsman{}, @emacsmantitle{}}. For +the sake of conciseness, we just call this file ``your @file{.emacs}'' +throughout the rest of the manual. + +Several of these variables (currently 16), are known collectively as +@dfn{style variables}. @ccmode{} provides a special mechanism, known +as @dfn{styles} to make it easier to set these variables as a group, +to ``inherit'' settings from one style into another, and so on. Style +variables remain ordinary Lisp variables, whose values can be read and +changed independently of the style system. @xref{Style Variables}. + +There are several ways you can write the code, depending on the +precise effect you want---they are described further down on this page. +If you are new to @ccmode{}, we suggest you begin with the simplest +method, ``Top-level commands or the customization interface''. + +If you make conflicting settings in several of these ways, the way +that takes precedence is the one that appears latest in this list: +@itemize @asis +@item +@table @asis +@item Style +@itemx File Style@footnote{In earlier versions of @ccmode{}, a File Style setting took precedence over any other setting apart from a File Local Variable setting.} +@itemx Top-level command or ``customization interface'' +@itemx Hook +@itemx File Local Variable setting +@end table +@end itemize + +Here is a summary of the different ways of writing your configuration +settings: + +@table @asis +@item Top-level commands or the ``customization interface'' +Most simply, you can write @code{setq} and similar commands at the top +level of your @file{.emacs} file. When you load a @ccmode{} buffer, +it initializes its configuration from these global values (at least, +for those settings you have given values to), so it makes sense to +have these @code{setq} commands run @emph{before} @ccmode{} is first +initialized---in particular, before any call to @code{desktop-read} +(@pxref{Saving Emacs Sessions,,, emacs, GNU Emacs Manual}). For +example, you might set c-basic-offset thus: + +@example +(setq c-basic-offset 4) +@end example + +You can use the more user friendly Customization interface instead, +but this manual does not cover in detail how that works. To do this, +start by typing @kbd{M-x customize-group @key{RET} c @key{RET}}. +@xref{Easy Customization,,,@emacsman{}, @emacsmantitle{}}. +@c The following note really belongs in the Emacs manual. +Emacs normally writes the customizations at the end of your +@file{.emacs} file. If you use @code{desktop-read}, you should edit +your @file{.emacs} to place the call to @code{desktop-read} @emph{after} +the customizations. + +The first initialization of @ccmode{} puts a snapshot of the +configuration settings into the special style @code{user}. +@xref{Built-in Styles}. + +For basic use of Emacs, either of these ways of configuring is +adequate. However, the settings are then the same in all @ccmode{} +buffers and it can be clumsy to communicate them between programmers. +For more flexibility, you'll want to use one (or both) of @ccmode{}'s +more sophisticated facilities, hooks and styles. + +@item Hooks +An Emacs @dfn{hook} is a place to put Lisp functions that you want +Emacs to execute later in specific circumstances. +@xref{Hooks,,,@lispref{}, @lispreftitle{}}. @ccmode{} supplies a main +hook and a language-specific hook for each language it supports - any +functions you put onto these hooks get executed as the last part of a +buffer's initialization. Typically you put most of your customization +within the main hook, and use the language-specific hooks to vary the +customization settings between language modes. For example, if you +wanted different (non-standard) values of @code{c-basic-offset} in C +Mode and Java Mode buffers, you could do it like this: + +@example +@group +(defun my-c-mode-hook () + (setq c-basic-offset 3)) +(add-hook 'c-mode-hook 'my-c-mode-hook) + +(defun my-java-mode-hook () + (setq c-basic-offset 6)) +(add-hook 'java-mode-hook 'my-java-mode-hook) +@end group +@end example + +See @ref{CC Hooks} for more details on the use of @ccmode{} hooks. + +@item Styles +A @ccmode{} @dfn{style} is a coherent collection of customizations +with a name. At any time, exactly one style is active in each +@ccmode{} buffer, either the one you have selected or a default. +@ccmode{} is delivered with several existing styles. Additionally, +you can create your own styles, possibly based on these existing +styles. If you worked in a programming team called the ``Free +Group'', which had its own coding standards, you might well have this +in your @file{.emacs} file: + +@example +(setq c-default-style '((java-mode . "java") + (awk-mode . "awk") + (other . "free-group-style"))) +@end example + +See @ref{Styles} for fuller details on using @ccmode{} styles and how +to create them. + +@item File Local Variable setting +A @dfn{file local variable setting} is a setting which applies to an +individual source file. You put this in a @dfn{local variables list}, +a special block at the end of the source file (@pxref{Specifying File +Variables,,, @emacsman{}}). + +@item File Styles +A @dfn{file style} is a rarely used variant of the ``style'' mechanism +described above, which applies to an individual source file. +@xref{File Styles}. You use this by setting certain special variables +in a local variables list (@pxref{Specifying File Variables,,, +@emacsman{}}). + +@item Hooks with Styles +For ultimate flexibility, you can use hooks and styles together. For +example, if your team were developing a product which required a +Linux driver, you'd probably want to use the ``linux'' style for the +driver, and your own team's style for the rest of the code. You +could achieve this with code like this in your @file{.emacs}: + +@example +@group +(defun my-c-mode-hook () + (c-set-style + (if (and (buffer-file-name) + (string-match "/usr/src/linux" (buffer-file-name))) + "linux" + "free-group-style"))) +(add-hook 'c-mode-hook 'my-c-mode-hook) +@end group +@end example + +In a programming team, a hook is a also a good place for each member +to put his own personal preferences. For example, you might be the +only person in your team who likes Auto-newline minor mode. You could +have it enabled by default by placing the following in your +@file{.emacs}: + +@example +@group +(defun my-turn-on-auto-newline () + (c-toggle-auto-newline 1)) +(add-hook 'c-mode-common-hook 'my-turn-on-auto-newline) +@end group +@end example +@end table + +@menu +* CC Hooks:: +* Style Variables:: +* Styles:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node CC Hooks, Style Variables, Config Basics, Config Basics +@comment node-name, next, previous, up +@section Hooks +@cindex mode hooks +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@c The node name is "CC Hooks" rather than "Hooks" because of a bug in +@c some older versions of Info, e.g. the info.el in GNU Emacs 21.3. +@c If you go to "Config Basics" and hit on the xref to "CC +@c Hooks" the function Info-follow-reference searches for "*Note: CC +@c Hooks" from the beginning of the page. If this node were instead +@c named "Hooks", that search would spuriously find "*Note: +@c Hooks(elisp)" and go to the wrong node. + +@ccmode{} provides several hooks that you can use to customize the +mode for your coding style. The main hook is +@code{c-mode-common-hook}; typically, you'll put the bulk of your +customizations here. In addition, each language mode has its own +hook, allowing you to fine tune your settings individually for the +different @ccmode{} languages, and there is a package initialization +hook. Finally, there is @code{c-special-indent-hook}, which enables +you to solve anomalous indentation problems. It is described in +@ref{Other Indentation}, not here. All these hooks adhere to the +standard Emacs conventions. + +When you open a buffer, @ccmode{} first initializes it with the +currently active style (@pxref{Styles}). Then it calls +@code{c-mode-common-hook}, and finally it calls the language-specific +hook. Thus, any style settings done in these hooks will override +those set by @code{c-default-style}. + +@defvar c-initialization-hook +@vindex initialization-hook (c-) +Hook run only once per Emacs session, when @ccmode{} is initialized. +This is a good place to change key bindings (or add new ones) in any +of the @ccmode{} key maps. @xref{Sample .emacs File}. +@end defvar + +@defvar c-mode-common-hook +@vindex mode-common-hook (c-) +Common hook across all languages. It's run immediately before the +language specific hook. +@end defvar + +@defvar c-mode-hook +@defvarx c++-mode-hook +@defvarx objc-mode-hook +@defvarx java-mode-hook +@defvarx idl-mode-hook +@defvarx pike-mode-hook +@defvarx awk-mode-hook +The language specific mode hooks. The appropriate one is run as the +last thing when you enter that language mode. +@end defvar + +Although these hooks are variables defined in @ccmode{}, you can give +them values before @ccmode{}'s code is loaded---indeed, this is the +only way to use @code{c-initialization-hook}. Their values aren't +overwritten when @ccmode{} gets loaded. + +Here's a simplified example of what you can add to your @file{.emacs} +file to do things whenever any @ccmode{} language is edited. See the +Emacs manuals for more information on customizing Emacs via hooks. +@xref{Sample .emacs File}, for a more complete sample @file{.emacs} +file. + +@example +(defun my-c-mode-common-hook () + ;; my customizations for all of c-mode and related modes + (no-case-fold-search) + ) +(add-hook 'c-mode-common-hook 'my-c-mode-common-hook) +@end example + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Style Variables, Styles, CC Hooks, Config Basics +@comment node-name, next, previous, up +@section Style Variables +@cindex styles +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex style variables +The variables that @ccmode{}'s style system control are called +@dfn{style variables}. Note that style variables are ordinary Lisp +variables, which the style system initializes; you can change their +values at any time (e.g. in a hook function). The style system can +also set other variables, to some extent. @xref{Styles}. + +@dfn{Style variables} are handled specially in several ways: + +@itemize @bullet +@item +Style variables are by default buffer-local variables. However, they +can instead be made global by setting +@code{c-style-variables-are-local-p} to @code{nil} before @ccmode{} is +initialized. + +@item +@vindex c-old-style-variable-behavior +@vindex old-style-variable-behavior (c-) +The default global binding of any style variable (with two exceptions +- see below) is the special symbol @code{set-from-style}. When the +style system initializes a buffer-local copy of a style variable for a +@ccmode{} buffer, if its global binding is still that symbol then it +will be set from the current style. Otherwise it will retain its +global default@footnote{This is a big change from versions of +@ccmode{} earlier than 5.26, where such settings would get overridden +by the style system unless special precautions were taken. That was +changed since it was counterintuitive and confusing, especially to +novice users. If your configuration depends on the old overriding +behavior, you can set the variable +@code{c-old-style-variable-behavior} to non-@code{nil}.}. This +``otherwise'' happens, for example, when you've set the variable with +@code{setq} at the top level of your @file{.emacs} (@pxref{Config +Basics}). + +@item +The style variable @code{c-offsets-alist} (@pxref{c-offsets-alist}) is +an association list with an element for each syntactic symbol. It's +handled a little differently from the other style variables. It's +default global binding is the empty list @code{nil}, rather than +@code{set-from-style}. Before the style system is initialized, you +can add individual elements to @code{c-offsets-alist} by calling +@code{c-set-offset}(@pxref{c-offsets-alist}) just like you would set +other style variables with @code{setq}. Those elements will then +prevail when the style system later initializes a buffer-local copy of +@code{c-offsets-alist}. + +@item +The style variable @code{c-special-indent-hook} is also handled in a +special way. Styles can only add functions to this hook, not remove +them, so any global settings you put on it are always +preserved@footnote{This did not change in version 5.26.}. The value +you give this variable in a style definition can be either a function +or a list of functions. + +@item +The global bindings of the style variables get captured in the special +@code{user} style when the style system is first initialized. +@xref{Built-in Styles}, for details. +@end itemize + +The style variables are:@* +@code{c-indent-comment-alist}, +@code{c-indent-comments-syntactically-p} (@pxref{Indentation +Commands});@* +@code{c-doc-comment-style} (@pxref{Doc Comments});@* +@code{c-block-comment-prefix}, @code{c-comment-prefix-regexp} +(@pxref{Custom Filling and Breaking});@* +@code{c-hanging-braces-alist} (@pxref{Hanging Braces});@* +@code{c-hanging-colons-alist} (@pxref{Hanging Colons});@* +@code{c-hanging-semi&comma-criteria} (@pxref{Hanging Semicolons and +Commas});@* +@code{c-cleanup-list} (@pxref{Clean-ups});@* +@code{c-basic-offset} (@pxref{Customizing Indentation});@* +@code{c-offsets-alist} (@pxref{c-offsets-alist});@* +@code{c-comment-only-line-offset} (@pxref{Comment Line-Up});@* +@code{c-special-indent-hook}, @code{c-label-minimum-indentation} +(@pxref{Other Indentation});@* +@code{c-backslash-column}, @code{c-backslash-max-column} +(@pxref{Custom Macros}). + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Styles, , Style Variables, Config Basics +@comment node-name, next, previous, up +@section Styles +@cindex styles +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +By @dfn{style} we mean the layout of the code---things like how many +columns to indent a block of code, whether an opening brace gets +indented to the level of the code it encloses, or of the construct +that introduces it, or ``hangs'' at the end of a line. + +Most people only need to edit code formatted in just a few well-defined +and consistent styles. For example, their organization might impose a +``blessed'' style that all its programmers must conform to. Similarly, +people who work on GNU software will have to use the GNU coding style. +Some shops are more lenient, allowing a variety of coding styles, and as +programmers come and go, there could be a number of styles in use. For +this reason, @ccmode{} makes it convenient for you to set up logical +groupings of customizations called @dfn{styles}, associate a single name +for any particular style, and pretty easily start editing new or +existing code using these styles. + +As an alternative to writing a style definition yourself, you can have +@ccmode{} @dfn{guess} (at least part of) your style by looking at an +already formatted piece of your code, @ref{Guessing the Style}. + +@menu +* Built-in Styles:: +* Choosing a Style:: +* Adding Styles:: +* Guessing the Style:: +* File Styles:: +@end menu + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Built-in Styles, Choosing a Style, Styles, Styles +@comment node-name, next, previous, up +@subsection Built-in Styles +@cindex styles, built-in +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +If you're lucky, one of @ccmode{}'s built-in styles might be just +what you're looking for. These are: + +@table @code +@item gnu +@cindex GNU style +Coding style blessed by the Free Software Foundation +for C code in GNU programs. + +@item k&r +@cindex K&R style +The classic Kernighan and Ritchie style for C code. + +@item bsd +@cindex BSD style +Also known as ``Allman style'' after Eric Allman. + +@item whitesmith +@cindex Whitesmith style +Popularized by the examples that came with Whitesmiths C, an early +commercial C compiler. + +@item stroustrup +@cindex Stroustrup style +The classic Stroustrup style for C++ code. + +@item ellemtel +@cindex Ellemtel style +Popular C++ coding standards as defined by ``Programming in C++, Rules +and Recommendations,'' Erik Nyquist and Mats Henricson, +Ellemtel@footnote{This document is available at +@uref{http://www.doc.ic.ac.uk/lab/cplus/c++.rules/} among other +places.}. +@c N.B. This URL was still valid at 2005/8/28 (ACM). + +@item linux +@cindex Linux style +C coding standard for Linux (the kernel). + +@item python +@cindex Python style +C coding standard for Python extension modules@footnote{Python is a +high level scripting language with a C/C++ foreign function interface. +For more information, see @uref{http://www.python.org/}.}. + +@item java +@cindex Java style +The style for editing Java code. Note that the default +value for @code{c-default-style} installs this style when you enter +@code{java-mode}. + +@item awk +@cindex AWK style +The style for editing AWK code. Note that the default value for +@code{c-default-style} installs this style when you enter +@code{awk-mode}. + +@item user +@cindex User style +This is a special style created by you. It consists of the factory +defaults for all the style variables as modified by the customizations +you do either with the Customization interface or by writing +@code{setq}s and @code{c-set-offset}s at the top level of your +@file{.emacs} file (@pxref{Config Basics}). The style system creates +this style as part of its initialization and doesn't modify it +afterwards. +@end table + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Choosing a Style, Adding Styles, Built-in Styles, Styles +@comment node-name, next, previous, up +@subsection Choosing a Style +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +When you create a new buffer, its style will be set from +@code{c-default-style}. The factory default is the style @code{gnu}, +except in Java and AWK modes where it's @code{java} and @code{awk}. + +Remember that if you set a style variable with the Customization +interface or at the top level of your @file{.emacs} file before the +style system is initialized (@pxref{Config Basics}), this setting will +override the one that the style system would have given the variable. + +To set a buffer's style interactively, use the command @kbd{C-c .} +(@pxref{Other Commands}). To set it from a file's local variable +list, @ref{File Styles}. + +@defopt c-default-style +@vindex default-style (c-) +This variable specifies which style to install by default in new +buffers. It takes either a style name string, or an association list +of major mode symbols to style names: + +@enumerate +@item +When @code{c-default-style} is a string, it must be an existing style +name. This style is then used for all modes. + +@item +When @code{c-default-style} is an association list, the mode language +is looked up to find a style name string. + +@item +If @code{c-default-style} is an association list where the mode +language mode isn't found then the special symbol @samp{other} is +looked up. If it's found then the associated style is used. + +@item +If @samp{other} is not found then the @samp{gnu} style is used. +@end enumerate + +In all cases, the style described in @code{c-default-style} is installed +@emph{before} the language hooks are run, so you can always override +this setting by including an explicit call to @code{c-set-style} in your +language mode hook, or in @code{c-mode-common-hook}. + +The standard value of @code{c-default-style} is @w{@code{((java-mode +. "java") (awk-mode . "awk") (other . "gnu"))}}. +@end defopt + +@defvar c-indentation-style +@vindex indentation-style (c-) +This variable always contains the buffer's current style name, as a +string. +@end defvar + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Adding Styles, Guessing the Style, Choosing a Style, Styles +@comment node-name, next, previous, up +@subsection Adding and Amending Styles +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +If none of the built-in styles is appropriate, you'll probably want to +create a new @dfn{style definition}, possibly based on an existing +style. To do this, put the new style's settings into a list with the +following format - the list can then be passed as an argument to the +function @code{c-add-style}. You can see an example of a style +definition in @ref{Sample .emacs File}. + +@cindex style definition +@c @defvr {List} style definition +@table @asis +@item Structure of a Style Definition List +([@var{base-style}] [(@var{variable} . @var{value}) @dots{}]) + +Optional @var{base-style}, if present, must be a string which is the +name of the @dfn{base style} from which this style inherits. At most +one @var{base-style} is allowed in a style definition. If +@var{base-style} is not specified, the style inherits from the table +of factory default values@footnote{This table is stored internally in +the variable c-fallback-style.} instead. All styles eventually +inherit from this internal table. Style loops generate errors. The +list of pre-existing styles can be seen in @ref{Built-in Styles}. + +The dotted pairs (@var{variable} . @var{value}) each consist of a +variable and the value it is to be set to when the style is later +activated.@footnote{Note that if the variable has been given a value +by the Customization interface or a @code{setq} at the top level of +your @file{.emacs}, this value will override the one the style system +tries to give it. @xref{Config Basics}.} The variable can be either a +@ccmode{} style variable or an arbitrary Emacs variable. In the +latter case, it is @emph{not} made buffer-local by the @ccmode{} style +system. +@c @end defvr + +Two variables are treated specially in the dotted pair list: + +@table @code +@item c-offsets-alist +The value is in turn a list of dotted pairs of the form + +@example +(@r{@var{syntactic-symbol}} . @r{@var{offset}}) +@end example + +as described in @ref{c-offsets-alist}. These are passed to +@code{c-set-offset} so there is no need to set every syntactic symbol +in your style, only those that are different from the inherited style. + +@item c-special-indent-hook +The value is added to @code{c-special-indent-hook} using +@code{add-hook}, so any functions already on it are kept. If the value +is a list, each element of the list is added with @code{add-hook}. +@end table +@end table + +Styles are kept in the @code{c-style-alist} variable, but you +should never modify this variable directly. Instead, @ccmode{} +provides the function @code{c-add-style} for this purpose. + +@defun c-add-style stylename description &optional set-p +@findex add-style (c-) +Add or update a style called @var{stylename}, a string. +@var{description} is the new style definition in the form described +above. If @var{stylename} already exists in @code{c-style-alist} then +it is replaced by @var{description}. (Note, this replacement is +total. The old style is @emph{not} merged into the new one.) +Otherwise, a new style is added. + +If the optional @var{set-p} is non-@code{nil} then the new style is +applied to the current buffer as well. The use of this facility is +deprecated and it might be removed from @ccmode{} in a future release. +You should use @code{c-set-style} instead. + +The sample @file{.emacs} file provides a concrete example of how a new +style can be added and automatically set. @xref{Sample .emacs File}. +@end defun + +@defvar c-style-alist +@vindex style-alist (c-) +This is the variable that holds the definitions for the styles. It +should not be changed directly; use @code{c-add-style} instead. +@end defvar + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Guessing the Style, File Styles, Adding Styles, Styles +@comment node-name, next, previous, up +@subsection Guessing the Style +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Instead of specifying a style, you can get @ccmode{} to @dfn{guess} +your style by examining an already formatted code buffer. @ccmode{} +then determines the ''most frequent'' offset (@pxref{c-offsets-alist}) +for each of the syntactic symbols (@pxref{Indentation Engine Basics}) +encountered in the buffer, and the ''most frequent'' value of +c-basic-offset (@pxref{Customizing Indentation}), then merges the +current style with these ''guesses'' to form a new style. This +combined style is known as the @dfn{guessed style}. + +To do this, call @code{c-guess} (or one of the other 5 guessing +commands) on your sample buffer. The analysis of your code may take +some time. + +You can then set the guessed style in any @ccmode{} buffer with +@code{c-guess-install}. You can display the style with +@code{c-guess-view}, and preserve it by copying it into your +@file{.emacs} for future use, preferably after editing it. + +@table @asis +@item @kbd{M-x c-guess-no-install} +@itemx @kbd{M-x c-guess-buffer-no-install} +@itemx @kbd{M-x c-guess-region-no-install} +@findex c-guess-no-install +@findex c-guess-buffer-no-install +@findex c-guess-region-no-install +@findex guess-no-install (c-) +@findex guess-buffer-no-install (c-) +@findex guess-region-no-install (c-) +These commands analyze a part of the current buffer and guess the +style from it. + +The part of the buffer examined is either the region +(@code{c-guess-region-no-install}), the entire buffer +(@code{c-guess-buffer-no-install}), or the first +@code{c-guess-region-max} bytes (@code{c-guess-no-install}). + +Each of these commands can be given an optional prefix argument. This +instructs @ccmode{} to combine the new guesses with the current +guesses before forming the guessed style. +@end table + +@table @asis +@item @kbd{M-x c-guess} +@itemx @kbd{M-x c-guess-buffer} +@itemx @kbd{M-x c-guess-region} +@findex c-guess +@findex c-guess-buffer +@findex c-guess-region +@findex guess (c-) +@findex guess-buffer (c-) +@findex guess-region (c-) +These commands analyze a part of the current buffer, guess the style +from it, then install the guessed style on the buffer. The guessed +style is given a name based on the buffer's absolute file name, and +you can then set this style on any @ccmode{} buffer with @kbd{C-c .}. + +The part of the buffer examined is either the region +(@code{c-guess-region}), the entire buffer (@code{c-guess-buffer}), or +the first @code{c-guess-region-max} bytes (@code{c-guess}). + +Each of these commands can be given an optional prefix argument. This +instructs @ccmode{} to combine the new guesses with the current +guesses before forming the guessed style. +@end table + +@defopt c-guess-region-max +@vindex guess-region-max (c-) +This variable, default 50000, is the size in bytes of the buffer +portion examined by c-guess and c-guess-no-install. If set to +@code{nil}, the entire buffer is examined. +@end defopt + +@defopt c-guess-offset-threshold +@vindex guess-offset-threshold (c-) +This variable, default 10, is the maximum offset, either outwards or +inwards, which will be taken into account by the analysis process. +Any offset bigger than this will be ignored. For no limit, set this +variable to a large number. +@end defopt + +@table @asis +@item @kbd{M-x c-guess-install} +@findex c-guess-install +@findex guess-install (c-) + +Set the current buffer's style to the guessed style. This prompts you +to enter an optional new style name to give to the guessed style. By +default, this name is based on the buffer's absolute file name. You +can then use this style like any other. + +@item @kbd{M-x c-guess-view} +@findex c-guess-view +@findex guess-view (c-) +Display the most recently guessed style in a temporary buffer. This +display is in the form of a @code{c-add-style} form (@pxref{Adding +Styles}) which can be easily copied to your @file{.emacs}. You will +probably want to edit it first. + +The display of the guessed style contains these elements: + +@table @asis +@item Placeholder Name +You should replace this with a style name of your own. +@item Parent Style +The style current when the guessing began, from which the guessed +style inherits (@pxref{Config Basics}) the settings which weren't +guessed. +@item Guessed Offsets +These are the core result of the guessing process. Each of them is +marked by a comment. +@item Inherited Offsets +These are syntactic offsets which have been taken over from the parent +style. To avoid possible future conflicts, you should remove either +these offsets or the parent style name. +@end table +@end table + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node File Styles, , Guessing the Style, Styles +@comment node-name, next, previous, up +@subsection File Styles +@cindex styles, file local +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex file local variables + +The Emacs manual describes how you can customize certain variables on a +per-file basis by including a @dfn{file local variable} block at the end +of the file (@pxref{File Variables,, Local Variables in Files, @emacsman{}, +@emacsmantitle{}}). + +So far, you've only seen a functional interface for setting styles in +@ccmode{}, and this can't be used here. @ccmode{} fills the gap by +providing two variables for use in a file's local variable list. +Don't use them anywhere else! These allow you to customize the style +on a per-file basis: + +@defvar c-file-style +@vindex file-style (c-) +Set this variable to a style name string in the Local Variables list. +From now on, when you visit the file, @ccmode{} will automatically set +the file's style to this one using @code{c-set-style}. +@end defvar + +@defvar c-file-offsets +@vindex file-offsets (c-) +Set this variable (in the Local Variables list) to an association list +of the same format as @code{c-offsets-alist}. From now on, when you +visit the file, @ccmode{} will automatically institute these offsets +using @code{c-set-offset}. +@end defvar + +Note that file style settings (i.e. @code{c-file-style}) are applied +before file offset settings +(i.e. @code{c-file-offsets})@footnote{Also, if either of these are set +in a file's local variable section, all the style variable values are +made local to that buffer, even if +@code{c-style-variables-are-local-p} is @code{nil}. Since this +variable is virtually always non-@code{nil} anyhow, you're unlikely to +notice this effect.}. + +If you set any variable by the file local variables mechanism, that +setting takes priority over all other settings, even those in your +mode hooks (@pxref{CC Hooks}). Any individual setting of a variable +will override one made through @code{c-file-style} or +@code{c-file-offsets}. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Custom Filling and Breaking, Custom Auto-newlines, Config Basics, Top +@comment node-name, next, previous, up +@chapter Customizing Filling and Line Breaking +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Since there's a lot of normal text in comments and string literals, +@ccmode{} provides features to edit these like in text mode. It does +this by hooking in on the different line breaking functions and tuning +relevant variables as necessary. + +@vindex c-comment-prefix-regexp +@vindex comment-prefix-regexp (c-) +@cindex comment line prefix +@vindex comment-start +@vindex comment-end +@vindex comment-start-skip +@vindex paragraph-start +@vindex paragraph-separate +@vindex paragraph-ignore-fill-prefix +@vindex adaptive-fill-mode +@vindex adaptive-fill-regexp +@vindex adaptive-fill-first-line-regexp +To make Emacs recognize comments and treat text in them as normal +paragraphs, @ccmode{} makes several standard +variables@footnote{@code{comment-start}, @code{comment-end}, +@code{comment-start-skip}, @code{paragraph-start}, +@code{paragraph-separate}, @code{paragraph-ignore-fill-prefix}, +@code{adaptive-fill-mode}, @code{adaptive-fill-regexp}, and +@code{adaptive-fill-first-line-regexp}.} buffer-local and modifies them +according to the language syntax and the comment line prefix. + +@defopt c-comment-prefix-regexp +@vindex comment-prefix-regexp (c-) +This style variable contains the regexp used to recognize the +@dfn{comment line prefix}, which is the line decoration that starts +every line in a comment. The variable is either the comment line +prefix itself, or (more usually) an association list with different +values for different languages. The symbol for the major mode is +looked up in the alist to get the regexp for the language, and if it +isn't found then the special symbol @samp{other} is looked up instead. + +When a comment line gets divided by @kbd{M-j} or the like, @ccmode{} +inserts the comment line prefix from a neighboring line at the start +of the new line. The default value of c-comment-prefix-regexp is +@samp{//+\\|\\**}, which matches C++ style line comments like + +@example +// blah blah +@end example + +@noindent +with two or more slashes in front of them, and the second and +subsequent lines of C style block comments like + +@example +@group +/* + * blah blah + */ +@end group +@end example + +@noindent +with zero or more stars at the beginning of every line. If you change +this variable, please make sure it still matches the comment starter +(i.e. @code{//}) of line comments @emph{and} the line prefix inside +block comments. + +@findex c-setup-paragraph-variables +@findex setup-paragraph-variables (c-) +Also note that since @ccmode{} uses the value of +@code{c-comment-prefix-regexp} to set up several other variables at +mode initialization, there won't be any effect if you just change it +inside a @ccmode{} buffer. You need to call the command +@code{c-setup-paragraph-variables} too, to update those other +variables. That's also the case if you modify +@code{c-comment-prefix-regexp} in a mode hook, since @ccmode{} will +already have set up these variables before calling the hook. +@end defopt + +In comments, @ccmode{} uses @code{c-comment-prefix-regexp} to adapt +the line prefix from the other lines in the comment. + +@vindex adaptive-fill-mode +@cindex Adaptive Fill mode +@ccmode{} uses adaptive fill mode (@pxref{Adaptive Fill,,, emacs, GNU +Emacs Manual}) to make Emacs correctly keep the line prefix when +filling paragraphs. That also makes Emacs preserve the text +indentation @emph{inside} the comment line prefix. E.g. in the +following comment, both paragraphs will be filled with the left +margins of the texts kept intact: + +@example +@group +/* Make a balanced b-tree of the nodes in the incoming + * stream. But, to quote the famous words of Donald E. + * Knuth, + * + * Beware of bugs in the above code; I have only + * proved it correct, not tried it. + */ +@end group +@end example + +@findex c-setup-filladapt +@findex setup-filladapt (c-) +@findex filladapt-mode +@vindex filladapt-mode +@cindex Filladapt mode +It's also possible to use other adaptive filling packages, notably Kyle +E. Jones' Filladapt package@footnote{It's available from +@uref{http://www.wonderworks.com/}. As of version 2.12, it does however +lack a feature that makes it work suboptimally when +@code{c-comment-prefix-regexp} matches the empty string (which it does +by default). A patch for that is available from +@uref{http://cc-mode.sourceforge.net/,, the CC Mode web site}.}, +@c 2005/11/22: The above is still believed to be the case. +which handles things like bulleted lists nicely. There's a convenience +function @code{c-setup-filladapt} that tunes the relevant variables in +Filladapt for use in @ccmode{}. Call it from a mode hook, e.g. with +something like this in your @file{.emacs}: + +@example +(defun my-c-mode-common-hook () + (c-setup-filladapt) + (filladapt-mode 1)) +(add-hook 'c-mode-common-hook 'my-c-mode-common-hook) +@end example + +@defopt c-block-comment-prefix +@vindex block-comment-prefix (c-) +@vindex c-comment-continuation-stars +@vindex comment-continuation-stars (c-) +Normally the comment line prefix inserted for a new line inside a +comment is deduced from other lines in it. However there's one +situation when there's no hint about what the prefix should look like, +namely when a block comment is broken for the first time. This style +variable@footnote{In versions before 5.26, this variable was called +@code{c-comment-continuation-stars}. As a compatibility measure, +@ccmode{} still uses the value on that variable if it's set.} is used +then as the comment prefix. It defaults to @samp{* +}@footnote{Actually, this default setting of +@code{c-block-comment-prefix} typically gets overridden by the default +style @code{gnu}, which sets it to blank. You can see the line +splitting effect described here by setting a different style, +e.g. @code{k&r} @xref{Choosing a Style}.}, which makes a comment + +@example +/* Got O(n^2) here, which is a Bad Thing. */ +@end example + +@noindent +break into + +@example +@group +/* Got O(n^2) here, which + * is a Bad Thing. */ +@end group +@end example + +Note that it won't work to adjust the indentation by putting leading +spaces in @code{c-block-comment-prefix}, since @ccmode{} still uses the +normal indentation engine to indent the line. Thus, the right way to +fix the indentation is by customizing the @code{c} syntactic symbol. It +defaults to @code{c-lineup-C-comments}, which handles the indentation of +most common comment styles, see @ref{Line-Up Functions}. +@end defopt + +@defopt c-ignore-auto-fill +@vindex ignore-auto-fill (c-) +When auto fill mode is enabled, @ccmode{} can selectively ignore it +depending on the context the line break would occur in, e.g. to never +break a line automatically inside a string literal. This variable +takes a list of symbols for the different contexts where auto-filling +never should occur: + +@table @code +@item string +Inside a string or character literal. +@item c +Inside a C style block comment. +@item c++ +Inside a C++ style line comment. +@item cpp +Inside a preprocessor directive. +@item code +Anywhere else, i.e. in normal code. +@end table + +By default, @code{c-ignore-auto-fill} is set to @code{(string cpp +code)}, which means that when auto-fill mode is activated, +auto-filling only occurs in comments. In literals, it's often +desirable to have explicit control over newlines. In preprocessor +directives, the necessary @samp{\} escape character before the newline +is not automatically inserted, so an automatic line break would +produce invalid code. In normal code, line breaks are normally +dictated by some logical structure in the code rather than the last +whitespace character, so automatic line breaks there will produce poor +results in the current implementation. +@end defopt + +@vindex comment-multi-line +If inside a comment and @code{comment-multi-line} (@pxref{Auto Fill,,, +@emacsman{}, @emacsmantitle{}} is non-@code{nil}, the indentation and +line prefix are preserved. If inside a comment and +@code{comment-multi-line} is @code{nil}, a new comment of the same +type is started on the next line and indented as appropriate for +comments. + +Note that @ccmode{} sets @code{comment-multi-line} to @code{t} at +startup. The reason is that @kbd{M-j} could otherwise produce sequences +of single line block comments for texts that should logically be treated +as one comment, and the rest of the paragraph handling code +(e.g. @kbd{M-q} and @kbd{M-a}) can't cope with that, which would lead to +inconsistent behavior. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Custom Auto-newlines, Clean-ups, Custom Filling and Breaking, Top +@comment node-name, next, previous, up +@chapter Customizing Auto-newlines +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@ccmode{} determines whether to insert auto-newlines in two basically +different ways, depending on the character just typed: + +@table @asis +@item Braces and Colons +@ccmode{} first determines the syntactic context of the brace or colon +(@pxref{Syntactic Symbols}), then looks for a corresponding element in +an alist. This element specifies where to put newlines - this is any +combination of before and after the brace or colon. If no alist +element is found, newlines are inserted both before and after a brace, +but none are inserted around a colon. See @ref{Hanging Braces} and +@ref{Hanging Colons}. + +@item Semicolons and Commas +The variable @code{c-hanging-semi&comma-criteria} contains a list of +functions which determine whether to insert a newline after a newly +typed semicolon or comma. @xref{Hanging Semicolons and Commas}. +@end table + +The names of these configuration variables contain @samp{hanging} +because they let you @dfn{hang} the pertinent characters. A character +which introduces a C construct is said to @dfn{hang on the right} when +it appears at the end of a line after other code, being separated by a +line break from the construct it introduces, like the opening brace in: + +@example +@group +while (i < MAX) @{ + total += entry[i]; + entry [i++] = 0; +@} +@end group +@end example + +@noindent +A character @dfn{hangs on the left} when it appears at the start of +the line after the construct it closes off, like the above closing +brace. + +The next chapter, ``Clean-ups'', describes how to configure @ccmode{} +to remove these automatically added newlines in certain specific +circumstances. @xref{Clean-ups}. + +@menu +* Hanging Braces:: +* Hanging Colons:: +* Hanging Semicolons and Commas:: +@end menu + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Hanging Braces, Hanging Colons, Custom Auto-newlines, Custom Auto-newlines +@comment node-name, next, previous, up +@section Hanging Braces +@cindex hanging braces +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +To specify which kinds of braces you want auto-newlines put around, +you set the style variable @code{c-hanging-braces-alist}. Its +structure and semantics are described in this section. Details of how +to set it up, and its relationship to CC Mode's style system are given +in @ref{Style Variables}. + +Say you wanted an auto-newline after (but not before) the following +@samp{@{}: + +@example +if (foo < 17) @{ +@end example + +@noindent +First you need to find the @dfn{syntactic context} of the brace---type +a @key{RET} before the brace to get it on a line of its +own@footnote{Also insert a @samp{\} at the end of the previous line if +you're in AWK Mode.}, then type @kbd{C-c C-s}. That will tell you +something like: + +@example +((substatement-open 1061)) +@end example + +@noindent +So here you need to put the entry @code{(substatement-open . (after))} +into @code{c-hanging-braces-alist}. + +If you don't want any auto-newlines for a particular syntactic symbol, +put this into @code{c-hanging-braces-alist}: + +@example +(brace-entry-open) +@end example + +If some brace syntactic symbol is not in @code{c-hanging-brace-alist}, +its entry is taken by default as @code{(before after)}---insert a +newline both before and after the brace. In place of a +``before/after'' list you can specify a function in this alist---this +is useful when the auto newlines depend on the code around the brace. + +@defopt c-hanging-braces-alist +@vindex hanging-braces-alist (c-) + +This variable is an association list which maps syntactic symbols to +lists of places to insert a newline. @xref{Association +Lists,,,@lispref{}, @lispreftitle{}}. The key of each element is the +syntactic symbol, the associated value is either @code{nil}, a list, +or a function. + +@table @asis +@item The Key - the syntactic symbol +The syntactic symbols that are useful as keys in this list are +@code{brace-list-intro}, @code{statement-cont}, +@code{inexpr-class-open}, @code{inexpr-class-close}, and all the +@code{*-open} and @code{*-close} symbols. @xref{Syntactic Symbols}, +for a more detailed description of these syntactic symbols, except for +@code{inexpr-class-open} and @code{inexpr-class-close}, which aren't +actual syntactic symbols. Elements with any other value as a key get +ignored. + +The braces of anonymous inner classes in Java are given the special +symbols @code{inexpr-class-open} and @code{inexpr-class-close}, so that +they can be distinguished from the braces of normal classes@footnote{The +braces of anonymous classes produce a combination of +@code{inexpr-class}, and @code{class-open} or @code{class-close} in +normal indentation analysis.}. + +Note that the aggregate constructs in Pike mode, @samp{(@{}, @samp{@})}, +@samp{([}, @samp{])}, and @samp{(<}, @samp{>)}, do not count as brace +lists in this regard, even though they do for normal indentation +purposes. It's currently not possible to set automatic newlines on +these constructs. + +@item The associated value - the ``ACTION'' list or function +The value associated with each syntactic symbol in this association +list is called an @var{action}, which can be either a list or a +function which returns a list. @xref{Custom Braces}, for how to use +a function as a brace hanging @var{action}. + +The list @var{action} (or the list returned by @var{action} when it's +a function) contains some combination of the symbols @code{before} and +@code{after}, directing @ccmode{} where to put newlines in +relationship to the brace being inserted. Thus, if the list contains +only the symbol @code{after}, then the brace hangs on the right side +of the line, as in: + +@example +// here, open braces always `hang' +void spam( int i ) @{ + if( i == 7 ) @{ + dosomething(i); + @} +@} +@end example + +When the list contains both @code{after} and @code{before}, the braces +will appear on a line by themselves, as shown by the close braces in +the above example. The list can also be empty, in which case newlines +are added neither before nor after the brace. +@end table + +If a syntactic symbol is missing entirely from +@code{c-hanging-braces-alist}, it's treated in the same way as an +@var{action} with a list containing @code{before} and @code{after}, so +that braces by default end up on their own line. + +For example, the default value of @code{c-hanging-braces-alist} is: + +@example +((brace-list-open) + (brace-entry-open) + (statement-cont) + (substatement-open after) + (block-close . c-snug-do-while) + (extern-lang-open after) + (namespace-open after) + (module-open after) + (composition-open after) + (inexpr-class-open after) + (inexpr-class-close before)) +@end example + +@noindent which says that @code{brace-list-open}, +@code{brace-entry-open} and @code{statement-cont}@footnote{Brace lists +inside statements, such as initializers for static array variables +inside functions in C, are recognized as @code{statement-cont}. All +normal substatement blocks are recognized with other symbols.} braces +should both hang on the right side and allow subsequent text to follow +on the same line as the brace. Also, @code{substatement-open}, +@code{extern-lang-open}, and @code{inexpr-class-open} braces should hang +on the right side, but subsequent text should follow on the next line. +The opposite holds for @code{inexpr-class-close} braces; they won't +hang, but the following text continues on the same line. Here, in the +@code{block-close} entry, you also see an example of using a function as +an @var{action}. In all other cases, braces are put on a line by +themselves. +@end defopt + +@menu +* Custom Braces:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Custom Braces, , Hanging Braces, Hanging Braces +@comment node-name, next, previous, up +@subsection Custom Brace Hanging +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@vindex c-hanging-braces-alist +@vindex hanging-braces-alist (c-) +@cindex action functions +Syntactic symbols aren't the only place where you can customize +@ccmode{} with the lisp equivalent of callback functions. Remember +that @var{action}s are usually a list containing some combination of +the symbols @code{before} and @code{after} (@pxref{Hanging Braces}). +For more flexibility, you can instead specify brace ``hanginess'' by +giving a syntactic symbol an @dfn{action function} in +@code{c-hanging-braces-alist}; this function determines the +``hanginess'' of a brace, usually by looking at the code near it. + +@cindex customization, brace hanging +An action function is called with two arguments: the syntactic symbol +for the brace (e.g. @code{substatement-open}), and the buffer position +where the brace has been inserted. Point is undefined on entry to an +action function, but the function must preserve it (e.g. by using +@code{save-excursion}). The return value should be a list containing +some combination of @code{before} and @code{after}, including neither +of them (i.e. @code{nil}). + +@defvar c-syntactic-context +@vindex syntactic-context (c-) +During the call to the indentation or brace hanging @var{action} +function, this variable is bound to the full syntactic analysis list. +This might be, for example, @samp{((block-close 73))}. Don't ever +give @code{c-syntactic-context} a value yourself---this would disrupt +the proper functioning of @ccmode{}. + +This variable is also bound in three other circumstances: +(i)@tie{}when calling a c-hanging-semi&comma-criteria function +(@pxref{Hanging Semicolons and Commas}); (ii)@tie{}when calling a +line-up function (@pxref{Custom Line-Up}); (iii)@tie{}when calling a +c-special-indent-hook function (@pxref{Other Indentation}). +@end defvar + +As an example, @ccmode{} itself uses this feature to dynamically +determine the hanginess of braces which close ``do-while'' +constructs: + +@example +void do_list( int count, char** atleast_one_string ) +@{ + int i=0; + do @{ + handle_string( atleast_one_string[i] ); + i++; + @} while( i < count ); +@} +@end example + +@ccmode{} assigns the @code{block-close} syntactic symbol to the +brace that closes the @code{do} construct, and normally we'd like the +line that follows a @code{block-close} brace to begin on a separate +line. However, with ``do-while'' constructs, we want the +@code{while} clause to follow the closing brace. To do this, we +associate the @code{block-close} symbol with the @var{action} function +@code{c-snug-do-while}: + +@example +(defun c-snug-do-while (syntax pos) + "Dynamically calculate brace hanginess for do-while statements." + (save-excursion + (let (langelem) + (if (and (eq syntax 'block-close) + (setq langelem (assq 'block-close c-syntactic-context)) + (progn (goto-char (cdr langelem)) + (if (= (following-char) ?@{) + (forward-sexp -1)) + (looking-at "\\[^_]"))) + '(before) + '(before after))))) +@end example + +@findex c-snug-do-while +@findex snug-do-while (c-) +This function simply looks to see if the brace closes a ``do-while'' +clause and if so, returns the list @samp{(before)} indicating +that a newline should be inserted before the brace, but not after it. +In all other cases, it returns the list @samp{(before after)} so +that the brace appears on a line by itself. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Hanging Colons, Hanging Semicolons and Commas, Hanging Braces, Custom Auto-newlines +@comment node-name, next, previous, up +@section Hanging Colons +@cindex hanging colons +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex customization, colon hanging +@vindex c-hanging-colons-alist +@vindex hanging-colons-alist (c-) + +Using a mechanism similar to brace hanging (@pxref{Hanging Braces}), +colons can also be made to hang using the style variable +@code{c-hanging-colons-alist} - When a colon is typed, @ccmode +determines its syntactic context, looks this up in the alist +@code{c-changing-colons-alist} and inserts up to two newlines +accordingly. Here, however, If @ccmode fails to find an entry for a +syntactic symbol in the alist, no newlines are inserted around the +newly typed colon. + +@defopt c-hanging-colons-alist +@vindex hanging-colons-alist (c-) + +@table @asis +@item The Key - the syntactic symbol +The syntactic symbols appropriate as keys in this association list +are: @code{case-label}, @code{label}, @code{access-label}, +@code{member-init-intro}, and @code{inher-intro}. @xref{Syntactic +Symbols}. Elements with any other value as a key get ignored. + +@item The associate value - the ``ACTION'' list +The @var{action} here is simply a list containing a combination of the +symbols @code{before} and @code{after}. Unlike in +@code{c-hanging-braces-alist}, functions as @var{actions} are not +supported - there doesn't seem to be any need for them. +@end table +@end defopt + +In C++, double-colons are used as a scope operator but because these +colons always appear right next to each other, newlines before and after +them are controlled by a different mechanism, called @dfn{clean-ups} in +@ccmode{}. @xref{Clean-ups}, for details. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Hanging Semicolons and Commas, , Hanging Colons, Custom Auto-newlines +@comment node-name, next, previous, up +@section Hanging Semicolons and Commas +@cindex hanging semicolons +@cindex hanging commas +@cindex customization, semicolon newlines +@cindex customization, comma newlines +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@defopt c-hanging-semi&comma-criteria +@vindex hanging-semi&comma-criteria (c-) +This style variable takes a list of functions; these get called when +you type a semicolon or comma. The functions are called in order +without arguments. When these functions are entered, point is just +after the newly inserted @samp{;} or @samp{,} and they must preserve +point (e.g., by using @code{save-excursion}). During the call, the +variable @code{c-syntactic-context} is bound to the syntactic context +of the current line@footnote{This was first introduced in @ccmode{} +5.31.} @pxref{Custom Braces}. These functions don't insert newlines +themselves, rather they direct @ccmode{} whether or not to do so. +They should return one of the following values: + +@table @code +@item t +A newline is to be inserted after the @samp{;} or @samp{,}, and no +more functions from the list are to be called. +@item stop +No more functions from the list are to be called, and no newline is to +be inserted. +@item nil +No determination has been made, and the next function in the list is +to be called. +@end table + +Note that auto-newlines are never inserted @emph{before} a semicolon +or comma. If every function in the list is called without a +determination being made, then no newline is added. + +In AWK mode, this variable is set by default to @code{nil}. In the +other modes, the default value is a list containing a single function, +@code{c-semi&comma-inside-parenlist}. This inserts newlines after all +semicolons, apart from those separating @code{for}-clause statements. +@end defopt + +@defun c-semi&comma-no-newlines-before-nonblanks +@findex semi&comma-no-newlines-before-nonblanks (c-) +This is an example of a criteria function, provided by @ccmode{}. It +prevents newlines from being inserted after semicolons when there is a +non-blank following line. Otherwise, it makes no determination. To +use, add this function to the front of the +@code{c-hanging-semi&comma-criteria} list. + +@example +(defun c-semi&comma-no-newlines-before-nonblanks () + (save-excursion + (if (and (eq last-command-char ?\;) + (zerop (forward-line 1)) + (not (looking-at "^[ \t]*$"))) + 'stop + nil))) +@end example +@end defun + +@defun c-semi&comma-inside-parenlist +@findex semi&comma-inside-parenlist (c-) +@defunx c-semi&comma-no-newlines-for-oneline-inliners +@findex semi&comma-no-newlines-for-oneline-inliners (c-) +The function @code{c-semi&comma-inside-parenlist} is what prevents +newlines from being inserted inside the parenthesis list of @code{for} +statements. In addition to +@code{c-semi&comma-no-newlines-before-nonblanks} described above, +@ccmode{} also comes with the criteria function +@code{c-semi&comma-no-newlines-for-oneline-inliners}, which suppresses +newlines after semicolons inside one-line inline method definitions +(e.g. in C++ or Java). +@end defun + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Clean-ups, Indentation Engine Basics, Custom Auto-newlines, Top +@comment node-name, next, previous, up +@chapter Clean-ups +@cindex clean-ups +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@dfn{Clean-ups} are mechanisms which remove (or exceptionally, add) +whitespace in specific circumstances and are complementary to colon +and brace hanging. You enable a clean-up by adding its symbol into +@code{c-cleanup-list}, e.g. like this: + +@example +(add-to-list 'c-cleanup-list 'space-before-funcall) +@end example + +On the surface, it would seem that clean-ups overlap the functionality +provided by the @code{c-hanging-*-alist} variables. Clean-ups, +however, are used to adjust code ``after-the-fact'', i.e. to adjust +the whitespace in constructs later than when they were typed. + +Most of the clean-ups remove automatically inserted newlines, and are +only active when auto-newline minor mode is turned on. Others will +work all the time. Note that clean-ups are only performed when there +is nothing but whitespace appearing between the individual components +of the construct, and (apart from @code{comment-close-slash}) when the +construct does not occur within a literal (@pxref{Auto-newlines}). + +@defopt c-cleanup-list +@vindex cleanup-list (c-) +@cindex literal + +You configure @ccmode{}'s clean-ups by setting the style variable +@code{c-cleanup-list}, which is a list of clean-up symbols. By +default, @ccmode{} cleans up only the @code{scope-operator} construct, +which is necessary for proper C++ support. +@end defopt + +These are the clean-ups that are only active when electric and +auto-newline minor modes are enabled: + +@c TBD: Would like to use some sort of @deffoo here; @table indents a +@c bit too much in dvi output. +@table @code +@item brace-else-brace +Clean up @samp{@} else @{} constructs by placing the entire construct on +a single line. Clean up occurs when the open brace after the +@samp{else} is typed. So for example, this: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} + else + @{ +@end group +@end example + +@noindent +appears like this after the last open brace is typed: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} else @{ +@end group +@end example + +@item brace-elseif-brace +Similar to the @code{brace-else-brace} clean-up, but this cleans up +@samp{@} else if (...) @{} constructs. For example: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} + else if( i==3 ) + @{ +@end group +@end example + +@noindent +appears like this after the last open parenthesis is typed: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} else if( +@end group +@end example + +@noindent +and like this after the last open brace is typed: + +@example +@group +void spam(int i) +@{ + if( i==7 ) @{ + dosomething(); + @} else if( i==3 ) @{ +@end group +@end example + +@item brace-catch-brace +Analogous to @code{brace-elseif-brace}, but cleans up @samp{@} catch +(...) @{} in C++ and Java mode. + +@item empty-defun-braces +Clean up braces following a top-level function or class definition that +contains no body. Clean up occurs when the closing brace is typed. +Thus the following: + +@example +@group +class Spam +@{ +@} +@end group +@end example + +@noindent +is transformed into this when the close brace is typed: + +@example +@group +class Spam +@{@} +@end group +@end example + +@item defun-close-semi +Clean up the terminating semicolon on top-level function or class +definitions when they follow a close brace. Clean up occurs when the +semicolon is typed. So for example, the following: + +@example +@group +class Spam +@{ +... +@} +; +@end group +@end example + +@noindent +is transformed into this when the semicolon is typed: + +@example +@group +class Spam +@{ +... +@}; +@end group +@end example + +@item list-close-comma +Clean up commas following braces in array and aggregate initializers. +Clean up occurs when the comma is typed. The space before the comma +is zapped just like the space before the semicolon in +@code{defun-close-semi}. + +@item scope-operator +Clean up double colons which might designate a C++ scope operator split +across multiple lines@footnote{Certain C++ constructs introduce +ambiguous situations, so @code{scope-operator} clean-ups might not +always be correct. This usually only occurs when scoped identifiers +appear in switch label tags.}. Clean up occurs when the second colon is +typed. You will always want @code{scope-operator} in the +@code{c-cleanup-list} when you are editing C++ code. + +@item one-liner-defun +Clean up a single line of code enclosed by defun braces by removing +the whitespace before and after the code. The clean-up happens when +the closing brace is typed. If the variable +@code{c-max-one-liner-length} is set, the cleanup is only done if the +resulting line would be no longer than the value of that variable. + +For example, consider this AWK code: + +@example +@group +BEGIN @{ + FS = "\t" # use as a field separator +@} +@end group +@end example + +@noindent +It gets compacted to the following when the closing brace is typed: + +@example +@group +BEGIN @{FS = "\t"@} # use as a field separator +@end group +@end example + +@defopt c-max-one-liner-length +@vindex max-one-liner-length (c-) +The maximum length of the resulting line for which the clean-up +@code{one-liner-defun} will be triggered. This length is that of the entire +line, including any leading whitespace and any trailing comment. Its +default value is 80. If the value is zero or @code{nil}, no limit +applies. +@end defopt +@end table + +The following clean-ups are always active when they occur on +@code{c-cleanup-list}, regardless of whether Electric minor mode or +Auto-newline minor mode are enabled: + +@table @code +@item space-before-funcall +Insert a space between the function name and the opening parenthesis +of a function call. This produces function calls in the style +mandated by the GNU coding standards, e.g. @samp{signal@tie{}(SIGINT, +SIG_IGN)} and @samp{abort@tie{}()}. Clean up occurs when the opening +parenthesis is typed. This clean-up should never be active in AWK +Mode, since such a space is syntactically invalid for user defined +functions. + +@item compact-empty-funcall +Clean up any space between the function name and the opening parenthesis +of a function call that has no arguments. This is typically used +together with @code{space-before-funcall} if you prefer the GNU function +call style for functions with arguments but think it looks ugly when +it's only an empty parenthesis pair. I.e. you will get @samp{signal +(SIGINT, SIG_IGN)}, but @samp{abort()}. Clean up occurs when the +closing parenthesis is typed. + +@item comment-close-slash +When inside a block comment, terminate the comment when you type a slash +at the beginning of a line (i.e. immediately after the comment prefix). +This clean-up removes whitespace preceding the slash and if needed, +inserts a star to complete the token @samp{*/}. Type @kbd{C-q /} in this +situation if you just want a literal @samp{/} inserted. +@end table + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Indentation Engine Basics, Customizing Indentation, Clean-ups, Top +@comment node-name, next, previous, up +@chapter Indentation Engine Basics +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +This chapter will briefly cover how @ccmode{} indents lines of code. +It is helpful to understand the indentation model being used so that +you will know how to customize @ccmode{} for your personal coding +style. All the details are in @ref{Customizing Indentation}. + +@ccmode{} has an indentation engine that provides a flexible and +general mechanism for customizing indentation. When @ccmode{} indents +a line of code, it separates its calculations into two steps: + +@enumerate +@item +@cindex syntactic symbol +@cindex anchor position +It analyzes the line to determine its @dfn{syntactic symbol(s)} (the +kind of language construct it's looking at) and its @dfn{anchor +position} (the position earlier in the file that @ccmode{} will indent +the line relative to). The anchor position might be the location of +an opening brace in the previous line, for example. @xref{Syntactic +Analysis}. +@item +@cindex offsets +@cindex indentation offset specifications +It looks up the syntactic symbol(s) in the configuration to get the +corresponding @dfn{offset(s)}. The symbol @code{+}, which means +``indent this line one more level'' is a typical offset. @ccmode{} +then applies these offset(s) to the anchor position, giving the +indentation for the line. The different sorts of offsets are +described in @ref{c-offsets-alist}. +@end enumerate + +In exceptional circumstances, the syntax directed indentation +described here may be a nuisance rather than a help. You can disable +it by setting @code{c-syntactic-indentation} to @code{nil}. (To set +the variable interactively, @ref{Minor Modes}). + +@defopt c-syntactic-indentation +@vindex syntactic-indentation (c-) +When this is non-@code{nil} (which it is by default), the indentation +of code is done according to its syntactic structure. When it's +@code{nil}, every line is just indented to the same level as the +previous one, and @kbd{TAB} (@code{c-indent-command}) adjusts the +indentation in steps of @code{c-basic-offset}. The current style +(@pxref{Config Basics}) then has no effect on indentation, nor do any +of the variables associated with indentation, not even +@code{c-special-indent-hook}. +@end defopt + +@menu +* Syntactic Analysis:: +* Syntactic Symbols:: +* Indentation Calculation:: +@end menu + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Syntactic Analysis, Syntactic Symbols, Indentation Engine Basics, Indentation Engine Basics +@comment node-name, next, previous, up +@section Syntactic Analysis +@cindex syntactic analysis +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex syntactic element +@cindex syntactic context +The first thing @ccmode{} does when indenting a line of code, is to +analyze the line, determining the @dfn{syntactic context} of the +(first) construct on that line. It's a list of @dfn{syntactic +elements}, where each syntactic element in turn is a list@footnote{In +@ccmode 5.28 and earlier, a syntactic element was a dotted pair; the +cons was the syntactic symbol and the cdr was the anchor position. +For compatibility's sake, the parameter passed to a line-up function +still has this dotted pair form (@pxref{Custom Line-Up}).} Here is a +brief and typical example: + +@example +((defun-block-intro 1959)) +@end example + +@cindex syntactic symbol +@noindent +The first thing inside each syntactic element is always a +@dfn{syntactic symbol}. It describes the kind of construct that was +recognized, e.g. @code{statement}, @code{substatement}, +@code{class-open}, @code{class-close}, etc. @xref{Syntactic Symbols}, +for a complete list of currently recognized syntactic symbols and +their semantics. The remaining entries are various data associated +with the recognized construct - there might be zero or more. + +@cindex anchor position +Conceptually, a line of code is always indented relative to some +position higher up in the buffer (typically the indentation of the +previous line). That position is the @dfn{anchor position} in the +syntactic element. If there is an entry after the syntactic symbol in +the syntactic element list then it's either nil or that anchor position. + +Here is an example. Suppose we had the following code as the only thing +in a C++ buffer @footnote{The line numbers in this and future examples +don't actually appear in the buffer, of course!}: + +@example + 1: void swap( int& a, int& b ) + 2: @{ + 3: int tmp = a; + 4: a = b; + 5: b = tmp; + 6: @} +@end example + +@noindent +We can use @kbd{C-c C-s} (@code{c-show-syntactic-information}) to +report what the syntactic analysis is for the current line: + +@table @asis +@item @kbd{C-c C-s} (@code{c-show-syntactic-information}) +@kindex C-c C-s +@findex c-show-syntactic-information +@findex show-syntactic-information (c-) +This command calculates the syntactic analysis of the current line and +displays it in the minibuffer. The command also highlights the anchor +position(s). +@end table + + Running this command on line 4 of this example, we'd see in the echo +area@footnote{With a universal argument (i.e. @kbd{C-u C-c C-s}) the +analysis is inserted into the buffer as a comment on the current +line.}: + +@example +((statement 35)) +@end example + +@noindent +and the @samp{i} of @code{int} on line 3 would be highlighted. This +tells us that the line is a statement and it is indented relative to +buffer position 35, the highlighted position. If you were to move +point to line 3 and hit @kbd{C-c C-s}, you would see: + +@example +((defun-block-intro 29)) +@end example + +@noindent +This indicates that the @samp{int} line is the first statement in a top +level function block, and is indented relative to buffer position 29, +which is the brace just after the function header. + +Here's another example: + +@example + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end example + +@noindent +Hitting @kbd{C-c C-s} on line 4 gives us: + +@example +((substatement-open 46)) +@end example + +@cindex substatement +@cindex substatement block +@noindent +which tells us that this is a brace that @emph{opens} a substatement +block. @footnote{A @dfn{substatement} is the line after a +conditional statement, such as @code{if}, @code{else}, @code{while}, +@code{do}, @code{switch}, etc. A @dfn{substatement +block} is a brace block following one of these conditional statements.} + +@cindex comment-only line +Syntactic contexts can contain more than one element, and syntactic +elements need not have anchor positions. The most common example of +this is a @dfn{comment-only line}: + +@example + 1: void draw_list( List& drawables ) + 2: @{ + 3: // call the virtual draw() method on each element in list + 4: for( int i=0; i < drawables.count(), ++i ) + 5: @{ + 6: drawables[i].draw(); + 7: @} + 8: @} +@end example + +@noindent +Hitting @kbd{C-c C-s} on line 3 of this example gives: + +@example +((comment-intro) (defun-block-intro 46)) +@end example + +@noindent +and you can see that the syntactic context contains two syntactic +elements. Notice that the first element, @samp{(comment-intro)}, has no +anchor position. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Syntactic Symbols, Indentation Calculation, Syntactic Analysis, Indentation Engine Basics +@comment node-name, next, previous, up +@section Syntactic Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex syntactic symbols, brief list +@vindex c-offsets-alist +@vindex offsets-alist (c-) +This section is a complete list of the syntactic symbols which appear +in the @code{c-offsets-alist} style variable, along with brief +descriptions. The previous section (@pxref{Syntactic Analysis}) +states what syntactic symbols are and how the indentation engine uses +them. + +More detailed descriptions of these symbols, together with snippets of +source code to which they apply, appear in the examples in the +subsections below. Note that, in the interests of brevity, the anchor +position associated with most syntactic symbols is @emph{not} +specified. In cases of doubt, type @kbd{C-c C-s} on a pertinent +line---this highlights the anchor position. + +@ssindex -open symbols +@ssindex -close symbols +@ssindex -block-intro symbols +The syntactic symbols which indicate brace constructs follow a general +naming convention. When a line begins with an open or close brace, +its syntactic symbol will contain the suffix @code{-open} or +@code{-close} respectively. The first line within the brace block +construct will contain the suffix @code{-block-intro}. + +@ssindex -intro symbols +@ssindex -cont symbols +In constructs which can span several lines, a distinction is usually +made between the first line that introduces the construct and the +lines that continue it. The syntactic symbols that indicate these +lines will contain the suffixes @code{-intro} or @code{-cont} +respectively. + +The best way to understand how all this works is by looking at some +examples. Remember that you can see the syntax of any source code +line by using @kbd{C-c C-s}. + +@table @code +@item string +Inside a multiline string. @ref{Literal Symbols}. +@item c +Inside a multiline C style block comment. @ref{Literal Symbols}. +@item defun-open +Brace that opens a top-level function definition. @ref{Function +Symbols}. +@item defun-close +Brace that closes a top-level function definition. @ref{Function +Symbols}. +@item defun-block-intro +The first line in a top-level defun. @ref{Function Symbols}. +@item class-open +Brace that opens a class definition. @ref{Class Symbols}. +@item class-close +Brace that closes a class definition. @ref{Class Symbols}. +@item inline-open +Brace that opens an in-class inline method. @ref{Class Symbols}. +@item inline-close +Brace that closes an in-class inline method. @ref{Class Symbols}. +@item func-decl-cont +The region between a function definition's argument list and the +function opening brace (excluding K&R argument declarations). In C, +you cannot put anything but whitespace and comments in this region, +however in C++ and Java, @code{throws} declarations and other things +can appear here. @ref{Literal Symbols}. @c @emph{FIXME!!! Can it not +@c go somewhere better?} +@item knr-argdecl-intro +First line of a K&R C argument declaration. @ref{K&R Symbols}. +@item knr-argdecl +Subsequent lines in a K&R C argument declaration. @ref{K&R Symbols}. +@item topmost-intro +The first line in a ``topmost'' definition. @ref{Function Symbols}. +@item topmost-intro-cont +Topmost definition continuation lines. This is only used in the parts +that aren't covered by other symbols such as @code{func-decl-cont} and +@code{knr-argdecl}. @ref{Function Symbols}. +@item annotation-top-cont +Topmost definition continuation lines where all previous items are +annotations. @ref{Java Symbols}. +@item member-init-intro +First line in a member initialization list. @ref{Class Symbols}. +@item member-init-cont +Subsequent member initialization list lines. @ref{Class Symbols}. +@item inher-intro +First line of a multiple inheritance list. @ref{Class Symbols}. +@item inher-cont +Subsequent multiple inheritance lines. @ref{Class Symbols}. +@item block-open +Statement block open brace. @ref{Literal Symbols}. +@item block-close +Statement block close brace. @ref{Conditional Construct Symbols}. +@item brace-list-open +Open brace of an enum or static array list. @ref{Brace List Symbols}. +@item brace-list-close +Close brace of an enum or static array list. @ref{Brace List Symbols}. +@item brace-list-intro +First line in an enum or static array list. @ref{Brace List Symbols}. +@item brace-list-entry +Subsequent lines in an enum or static array list. @ref{Brace List +Symbols}. +@item brace-entry-open +Subsequent lines in an enum or static array list where the line begins +with an open brace. @ref{Brace List Symbols}. +@item statement +A statement. @ref{Function Symbols}. +@item statement-cont +A continuation of a statement. @ref{Function Symbols}. +@item annotation-var-cont +A continuation of a statement where all previous items are +annotations. @ref{Java Symbols}. +@item statement-block-intro +The first line in a new statement block. @ref{Conditional Construct +Symbols}. +@item statement-case-intro +The first line in a case block. @ref{Switch Statement Symbols}. +@item statement-case-open +The first line in a case block that starts with a brace. @ref{Switch +Statement Symbols}. +@item substatement +The first line after a conditional or loop construct. +@ref{Conditional Construct Symbols}. +@item substatement-open +The brace that opens a substatement block. @ref{Conditional Construct +Symbols}. +@item substatement-label +The first line after a conditional or loop construct if it's a label. +@ref{Conditional Construct Symbols}. +@item case-label +A label in a @code{switch} block. @ref{Switch Statement Symbols}. +@item access-label +C++ access control label. @ref{Class Symbols}. +@item label +Any other label. @ref{Literal Symbols}. +@item do-while-closure +The @code{while} line that ends a @code{do}-@code{while} construct. +@ref{Conditional Construct Symbols}. +@item else-clause +The @code{else} line of an @code{if}-@code{else} construct. +@ref{Conditional Construct Symbols}. +@item catch-clause +The @code{catch} or @code{finally} (in Java) line of a +@code{try}-@code{catch} construct. @ref{Conditional Construct +Symbols}. +@item comment-intro +A line containing only a comment introduction. @ref{Literal Symbols}. +@item arglist-intro +The first line in an argument list. @ref{Paren List Symbols}. +@item arglist-cont +Subsequent argument list lines when no arguments follow on the same +line as the arglist opening paren. @ref{Paren List Symbols}. +@item arglist-cont-nonempty +Subsequent argument list lines when at least one argument follows on +the same line as the arglist opening paren. @ref{Paren List Symbols}. +@item arglist-close +The solo close paren of an argument list. @ref{Paren List Symbols}. +@item stream-op +Lines continuing a stream operator (C++ only). @ref{Literal +Symbols}. @c @emph{FIXME!!! Can this not be moved somewhere better?} +@item inclass +The line is nested inside a class definition. @ref{Class Symbols}. +@item cpp-macro +The start of a preprocessor macro definition. @ref{Literal Symbols}. +@item cpp-define-intro +The first line inside a multiline preprocessor macro if +@code{c-syntactic-indentation-in-macros} is set. @ref{Multiline Macro +Symbols}. +@item cpp-macro-cont +All lines inside multiline preprocessor macros if +@code{c-syntactic-indentation-in-macros} is @code{nil}. +@ref{Multiline Macro Symbols}. +@item friend +A C++ friend declaration. @ref{Class Symbols}. +@item objc-method-intro +The first line of an Objective-C method definition. @ref{Objective-C +Method Symbols}. +@item objc-method-args-cont +Lines continuing an Objective-C method definition. @ref{Objective-C +Method Symbols}. +@item objc-method-call-cont +Lines continuing an Objective-C method call. @ref{Objective-C Method +Symbols}. +@item extern-lang-open +Brace that opens an @code{extern} block (e.g. @code{extern "C" +@{...@}}). @ref{External Scope Symbols}. +@item extern-lang-close +Brace that closes an @code{extern} block. @ref{External Scope +Symbols}. +@item inextern-lang +Analogous to @code{inclass} syntactic symbol, but used inside +@code{extern} blocks. @ref{External Scope Symbols}. +@item namespace-open +@itemx namespace-close +@itemx innamespace +These are analogous to the three @code{extern-lang} symbols above, but +are returned for C++ namespace blocks. @ref{External Scope Symbols}. +@item module-open +@itemx module-close +@itemx inmodule +Analogous to the above, but for CORBA IDL @code{module} blocks. +@ref{External Scope Symbols}. +@item composition-open +@itemx composition-close +@itemx incomposition +Analogous to the above, but for CORBA CIDL @code{composition} blocks. +@ref{External Scope Symbols}. +@item template-args-cont +C++ template argument list continuations. @ref{Class Symbols}. +@item inlambda +Analogous to @code{inclass} syntactic symbol, but used inside lambda +(i.e. anonymous) functions. Only used in Pike mode. @ref{Statement +Block Symbols}. +@item lambda-intro-cont +Lines continuing the header of a lambda function, i.e. between the +@code{lambda} keyword and the function body. Only used in Pike mode. +@ref{Statement Block Symbols}. +@item inexpr-statement +A statement block inside an expression. The gcc C and C++ extension +for this is recognized. It's also used for the special functions that +take a statement block as an argument in Pike. @ref{Statement Block +Symbols}. +@item inexpr-class +A class definition inside an expression. This is used for anonymous +classes in Java. It's also used for anonymous array initializers in +Java. @ref{Java Symbols}. +@end table + +@menu +* Function Symbols:: +* Class Symbols:: +* Conditional Construct Symbols:: +* Switch Statement Symbols:: +* Brace List Symbols:: +* External Scope Symbols:: +* Paren List Symbols:: +* Literal Symbols:: +* Multiline Macro Symbols:: +* Objective-C Method Symbols:: +* Java Symbols:: +* Statement Block Symbols:: +* K&R Symbols:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Function Symbols, Class Symbols, Syntactic Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Function Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +This example shows a typical function declaration. + +@example + 1: void + 2: swap( int& a, int& b ) + 3: @{ + 4: int tmp = a; + 5: a = b; + 6: b = tmp; + 7: int ignored = + 8: a + b; + 9: @} +@end example + +@ssindex topmost-intro +@ssindex topmost-intro-cont +@ssindex defun-open +@ssindex defun-close +@ssindex defun-block-intro +Line 1 shows a @code{topmost-intro} since it is the first line that +introduces a top-level construct. Line 2 is a continuation of the +top-level construct introduction so it has the syntax +@code{topmost-intro-cont}. Line 3 shows a @code{defun-open} since it is +the brace that opens a top-level function definition. Line 9 is the +corresponding +@code{defun-close} since it contains the brace that closes the top-level +function definition. Line 4 is a @code{defun-block-intro}, i.e. it is +the first line of a brace-block, enclosed in a +top-level function definition. + +@ssindex statement +@ssindex statement-cont +Lines 5, 6, and 7 are all given @code{statement} syntax since there +isn't much special about them. Note however that line 8 is given +@code{statement-cont} syntax since it continues the statement begun +on the previous line. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Class Symbols, Conditional Construct Symbols, Function Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Class related Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Here's an example which illustrates some C++ class syntactic symbols: + +@example + 1: class Bass + 2: : public Guitar, + 3: public Amplifiable + 4: @{ + 5: public: + 6: Bass() + 7: : eString( new BassString( 0.105 )), + 8: aString( new BassString( 0.085 )), + 9: dString( new BassString( 0.065 )), +10: gString( new BassString( 0.045 )) +11: @{ +12: eString.tune( 'E' ); +13: aString.tune( 'A' ); +14: dString.tune( 'D' ); +15: gString.tune( 'G' ); +16: @} +17: friend class Luthier; +18: @}; +@end example + +@ssindex class-open +@ssindex class-close +As in the previous example, line 1 has the @code{topmost-intro} syntax. +Here however, the brace that opens a C++ class definition on line 4 is +assigned the @code{class-open} syntax. Note that in C++, classes, +structs, and unions are essentially equivalent syntactically (and are +very similar semantically), so replacing the @code{class} keyword in the +example above with @code{struct} or @code{union} would still result in a +syntax of @code{class-open} for line 4 @footnote{This is the case even +for C and Objective-C. For consistency, structs in all supported +languages are syntactically equivalent to classes. Note however that +the keyword @code{class} is meaningless in C and Objective-C.}. +Similarly, line 18 is assigned @code{class-close} syntax. + +@ssindex inher-intro +@ssindex inher-cont +Line 2 introduces the inheritance list for the class so it is assigned +the @code{inher-intro} syntax, and line 3, which continues the +inheritance list is given @code{inher-cont} syntax. + +@ssindex access-label +@ssindex inclass +Hitting @kbd{C-c C-s} on line 5 shows the following analysis: + +@example +((inclass 58) (access-label 58)) +@end example + +@noindent +The primary syntactic symbol for this line is @code{access-label} as +this is a label keyword that specifies access protection in C++. However, +because this line is also a top-level construct inside a class +definition, the analysis actually shows two syntactic symbols. The +other syntactic symbol assigned to this line is @code{inclass}. +Similarly, line 6 is given both @code{inclass} and @code{topmost-intro} +syntax: + +@example +((inclass 58) (topmost-intro 60)) +@end example + +@ssindex member-init-intro +@ssindex member-init-cont +Line 7 introduces a C++ member initialization list and as such is given +@code{member-init-intro} syntax. Note that in this case it is +@emph{not} assigned @code{inclass} since this is not considered a +top-level construct. Lines 8 through 10 are all assigned +@code{member-init-cont} since they continue the member initialization +list started on line 7. + +@cindex in-class inline methods +@ssindex inline-open +@ssindex inline-close +Line 11's analysis is a bit more complicated: + +@example +((inclass 58) (inline-open)) +@end example + +This line is assigned a syntax of both @code{inline-open} and +@code{inclass} because it opens an @dfn{in-class} C++ inline method +definition. This is distinct from, but related to, the C++ notion of an +inline function in that its definition occurs inside an enclosing class +definition, which in C++ implies that the function should be inlined. +However, if the definition of the @code{Bass} constructor appeared +outside the class definition, the construct would be given the +@code{defun-open} syntax, even if the keyword @code{inline} appeared +before the method name, as in: + +@example + 1: class Bass + 2: : public Guitar, + 3: public Amplifiable + 4: @{ + 5: public: + 6: Bass(); + 7: @}; + 8: + 9: inline +10: Bass::Bass() +11: : eString( new BassString( 0.105 )), +12: aString( new BassString( 0.085 )), +13: dString( new BassString( 0.065 )), +14: gString( new BassString( 0.045 )) +15: @{ +16: eString.tune( 'E' ); +17: aString.tune( 'A' ); +18: dString.tune( 'D' ); +19: gString.tune( 'G' ); +20: @} +@end example + +@ssindex friend +Returning to the previous example, line 16 is given @code{inline-close} +syntax, while line 12 is given @code{defun-block-open} syntax, and lines +13 through 15 are all given @code{statement} syntax. Line 17 is +interesting in that its syntactic analysis list contains three +elements: + +@example +((inclass 58) (topmost-intro 380) (friend)) +@end example + +The @code{friend} and @code{inline-open} syntactic symbols are +modifiers that do not have anchor positions. + +@ssindex template-args-cont +Template definitions introduce yet another syntactic symbol: + +@example + 1: ThingManager framework_callbacks; +@end example + +Here, line 1 is analyzed as a @code{topmost-intro}, but lines 2 and 3 +are both analyzed as @code{template-args-cont} lines. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Conditional Construct Symbols, Switch Statement Symbols, Class Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Conditional Construct Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Here is a (totally contrived) example which illustrates how syntax is +assigned to various conditional constructs: + +@example + 1: void spam( int index ) + 2: @{ + 3: for( int i=0; i 0 ); +15: @} +@end example + +Only the lines that illustrate new syntactic symbols will be discussed. + +@ssindex substatement-open +@ssindex statement-block-intro +@ssindex block-close +Line 4 has a brace which opens a conditional's substatement block. It +is thus assigned @code{substatement-open} syntax, and since line 5 is +the first line in the substatement block, it is assigned +@code{statement-block-intro} syntax. Line 10 contains the brace +that closes the inner substatement block, and is therefore given the +syntax @code{block-close}@footnote{@code{block-open} is used only for +``free-standing'' blocks, and is somewhat rare (@pxref{Literal +Symbols} for an example.)}. Line 13 is treated the same way. + +@ssindex substatement +Lines 6 and 9 are also substatements of conditionals, but since they +don't start blocks they are given @code{substatement} syntax +instead of @code{substatement-open}. + +@ssindex substatement-label +Line 8 contains a label, which is normally given @code{label} syntax. +This one is however a bit special since it's between a conditional and +its substatement. It's analyzed as @code{substatement-label} to let you +handle this rather odd case differently from normal labels. + +@ssindex else-clause +@ssindex catch-clause +Line 7 start with an @code{else} that matches the @code{if} statement on +line 5. It is therefore given the @code{else-clause} syntax and is +anchored on the matching @code{if}. The @code{try}-@code{catch} +constructs in C++ and Java are treated this way too, except that +@code{catch} and (in Java) @code{finally}, are marked with +@code{catch-clause}. + +@ssindex do-while-closure +The @code{while} construct on line 14 that closes a @code{do} +conditional is given the special syntax @code{do-while-closure} if it +appears on a line by itself. Note that if the @code{while} appeared on +the same line as the preceding close brace, that line would still have +@code{block-close} syntax. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Switch Statement Symbols, Brace List Symbols, Conditional Construct Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Switch Statement Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Switch statements have their own set of syntactic symbols. Here's an +example: + +@example + 1: void spam( enum Ingredient i ) + 2: @{ + 3: switch( i ) @{ + 4: case Ham: + 5: be_a_pig(); + 6: break; + 7: case Salt: + 8: drink_some_water(); + 9: break; +10: default: +11: @{ +12: what_is_it(); +13: break; +14: @} +15: @} +14: @} +@end example + +@ssindex case-label +@ssindex statement-case-intro +@ssindex statement-case-open +Here, lines 4, 7, and 10 are all assigned @code{case-label} syntax, +while lines 5 and 8 are assigned @code{statement-case-intro}. Line 11 +is treated slightly differently since it contains a brace that opens a +block --- it is given @code{statement-case-open} syntax. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Brace List Symbols, External Scope Symbols, Switch Statement Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Brace List Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex brace lists +There are a set of syntactic symbols that are used to recognize +constructs inside of brace lists. A brace list is defined as an +@code{enum} or aggregate initializer list, such as might statically +initialize an array of structs. The three special aggregate constructs +in Pike, @code{(@{ @})}, @code{([ ])} and @code{(< >)}, are treated as +brace lists too. An example: + +@example + 1: static char* ingredients[] = + 2: @{ + 3: "Ham", + 4: "Salt", + 5: NULL + 6: @}; +@end example + +@ssindex brace-list-open +@ssindex brace-list-intro +@ssindex brace-list-close +@ssindex brace-list-entry +Following convention, line 2 in this example is assigned +@code{brace-list-open} syntax, and line 3 is assigned +@code{brace-list-intro} syntax. Likewise, line 6 is assigned +@code{brace-list-close} syntax. Lines 4 and 5 however, are assigned +@code{brace-list-entry} syntax, as would all subsequent lines in this +initializer list. + +@ssindex brace-entry-open +Your static initializer might be initializing nested structures, for +example: + +@example + 1: struct intpairs[] = + 2: @{ + 3: @{ 1, 2 @}, + 4: @{ + 5: 3, + 6: 4 + 7: @} + 8: @{ 1, + 9: 2 @}, +10: @{ 3, 4 @} +11: @}; +@end example + +Here, you've already seen the analysis of lines 1, 2, 3, and 11. On +line 4, things get interesting; this line is assigned +@code{brace-entry-open} syntactic symbol because it's a bracelist entry +line that starts with an open brace. Lines 5 and 6 (and line 9) are +pretty standard, and line 7 is a @code{brace-list-close} as you'd +expect. Once again, line 8 is assigned as @code{brace-entry-open} as is +line 10. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node External Scope Symbols, Paren List Symbols, Brace List Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection External Scope Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +External language definition blocks also have their own syntactic +symbols. In this example: + +@example + 1: extern "C" + 2: @{ + 3: int thing_one( int ); + 4: int thing_two( double ); + 5: @} +@end example + +@ssindex extern-lang-open +@ssindex extern-lang-close +@ssindex inextern-lang +@ssindex inclass +@noindent +line 2 is given the @code{extern-lang-open} syntax, while line 5 is given +the @code{extern-lang-close} syntax. The analysis for line 3 yields: + +@example +((inextern-lang) (topmost-intro 14)) +@end example + +@noindent +where @code{inextern-lang} is a modifier similar in purpose to +@code{inclass}. + +There are various other top level blocks like @code{extern}, and they +are all treated in the same way except that the symbols are named after +the keyword that introduces the block. E.g. C++ namespace blocks get +the three symbols @code{namespace-open}, @code{namespace-close} and +@code{innamespace}. The currently recognized top level blocks are: + +@table @asis +@item @code{extern-lang-open}, @code{extern-lang-close}, @code{inextern-lang} +@code{extern} blocks in C and C++.@footnote{These should logically be +named @code{extern-open}, @code{extern-close} and @code{inextern}, but +that isn't the case for historical reasons.} + +@item @code{namespace-open}, @code{namespace-close}, @code{innamespace} +@ssindex namespace-open +@ssindex namespace-close +@ssindex innamespace +@code{namespace} blocks in C++. + +@item @code{module-open}, @code{module-close}, @code{inmodule} +@ssindex module-open +@ssindex module-close +@ssindex inmodule +@code{module} blocks in CORBA IDL. + +@item @code{composition-open}, @code{composition-close}, @code{incomposition} +@ssindex composition-open +@ssindex composition-close +@ssindex incomposition +@code{composition} blocks in CORBA CIDL. +@end table + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Paren List Symbols, Literal Symbols, External Scope Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Parenthesis (Argument) List Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +A number of syntactic symbols are associated with parenthesis lists, +a.k.a argument lists, as found in function declarations and function +calls. This example illustrates these: + +@example + 1: void a_function( int line1, + 2: int line2 ); + 3: + 4: void a_longer_function( + 5: int line1, + 6: int line2 + 7: ); + 8: + 9: void call_them( int line1, int line2 ) +10: @{ +11: a_function( +12: line1, +13: line2 +14: ); +15: +16: a_longer_function( line1, +17: line2 ); +18: @} +@end example + +@ssindex arglist-intro +@ssindex arglist-close +Lines 5 and 12 are assigned @code{arglist-intro} syntax since they are +the first line following the open parenthesis, and lines 7 and 14 are +assigned @code{arglist-close} syntax since they contain the parenthesis +that closes the argument list. + +@ssindex arglist-cont-nonempty +@ssindex arglist-cont +Lines that continue argument lists can be assigned one of two syntactic +symbols. For example, Lines 2 and 17 +are assigned @code{arglist-cont-nonempty} syntax. What this means +is that they continue an argument list, but that the line containing the +parenthesis that opens the list is @emph{not empty} following the open +parenthesis. Contrast this against lines 6 and 13 which are assigned +@code{arglist-cont} syntax. This is because the parenthesis that opens +their argument lists is the last character on that line. + +Syntactic elements with @code{arglist-intro}, +@code{arglist-cont-nonempty}, and @code{arglist-close} contain two +buffer positions: the anchor position (the beginning of the +declaration or statement) and the position of the open parenthesis. +The latter position can be used in a line-up function (@pxref{Line-Up +Functions}). + +Note that there is no @code{arglist-open} syntax. This is because any +parenthesis that opens an argument list, appearing on a separate line, +is assigned the @code{statement-cont} syntax instead. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Literal Symbols, Multiline Macro Symbols, Paren List Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Comment String Label and Macro Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +A few miscellaneous syntactic symbols that haven't been previously +covered are illustrated by this C++ example: + +@example + 1: void Bass::play( int volume ) + 2: const + 3: @{ + 4: /* this line starts a multiline + 5: * comment. This line should get `c' syntax */ + 6: + 7: char* a_multiline_string = "This line starts a multiline \ + 8: string. This line should get `string' syntax."; + 9: +10: note: +11: @{ +12: #ifdef LOCK +13: Lock acquire(); +14: #endif // LOCK +15: slap_pop(); +16: cout << "I played " +17: << "a note\n"; +18: @} +19: @} +@end example + +The lines to note in this example include: + +@itemize @bullet +@item +@ssindex func-decl-cont +Line 2 is assigned the @code{func-decl-cont} syntax. + +@item +@ssindex comment-intro +Line 4 is assigned both @code{defun-block-intro} @emph{and} +@code{comment-intro} syntax. A syntactic element with +@code{comment-intro} has no anchor point --- It is always accompanied +by another syntactic element which does have one. + +@item +@ssindex c +Line 5 is assigned @code{c} syntax. + +@item +@cindex syntactic whitespace +Line 6 which, even though it contains nothing but whitespace, is +assigned @code{defun-block-intro}. Note that the appearance of the +comment on lines 4 and 5 do not cause line 6 to be assigned +@code{statement} syntax because comments are considered to be +@dfn{syntactic whitespace}, which are ignored when analyzing +code. + +@item +@ssindex string +Line 8 is assigned @code{string} syntax. + +@item +@ssindex label +Line 10 is assigned @code{label} syntax. + +@item +@ssindex block-open +Line 11 is assigned @code{block-open} as well as @code{statement} +syntax. A @code{block-open} syntactic element doesn't have an anchor +position, since it always appears with another syntactic element which +does have one. + +@item +@ssindex cpp-macro +Lines 12 and 14 are assigned @code{cpp-macro} syntax in addition to the +normal syntactic symbols (@code{statement-block-intro} and +@code{statement}, respectively). Normally @code{cpp-macro} is +configured to cancel out the normal syntactic context to make all +preprocessor directives stick to the first column, but that's easily +changed if you want preprocessor directives to be indented like the rest +of the code. Like @code{comment-intro}, a syntactic element with +@code{cpp-macro} doesn't contain an anchor position. + +@item +@ssindex stream-op +Line 17 is assigned @code{stream-op} syntax. +@end itemize + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Multiline Macro Symbols, Objective-C Method Symbols, Literal Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Multiline Macro Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex multiline macros +@cindex syntactic whitespace +@ssindex cpp-define-intro +@ssindex cpp-macro-cont +Multiline preprocessor macro definitions are normally handled just like +other code, i.e. the lines inside them are indented according to the +syntactic analysis of the preceding lines inside the macro. The first +line inside a macro definition (i.e. the line after the starting line of +the cpp directive itself) gets @code{cpp-define-intro}. In this example: + +@example + 1: #define LIST_LOOP(cons, listp) \ + 2: for (cons = listp; !NILP (cons); cons = XCDR (cons)) \ + 3: if (!CONSP (cons)) \ + 4: signal_error ("Invalid list format", listp); \ + 5: else +@end example + +@noindent +line 1 is given the syntactic symbol @code{cpp-macro}. The first line +of a cpp directive is always given that symbol. Line 2 is given +@code{cpp-define-intro}, so that you can give the macro body as a whole +some extra indentation. Lines 3 through 5 are then analyzed as normal +code, i.e. @code{substatement} on lines 3 and 4, and @code{else-clause} +on line 5. + +The syntactic analysis inside macros can be turned off with +@code{c-syntactic-indentation-in-macros} (@pxref{Custom Macros}). In +that case, lines 2 through 5 would all be given @code{cpp-macro-cont} +with an anchor position pointing to the @code{#} which starts the cpp +directive@footnote{This is how @ccmode{} 5.28 and earlier analyzed +macros.}. + +@xref{Custom Macros}, for more info about the treatment of macros. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Objective-C Method Symbols, Java Symbols, Multiline Macro Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Objective-C Method Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +In Objective-C buffers, there are three additional syntactic symbols +assigned to various message calling constructs. Here's an example +illustrating these: + +@example + 1: - (void)setDelegate:anObject + 2: withStuff:stuff + 3: @{ + 4: [delegate masterWillRebind:self + 5: toDelegate:anObject + 6: withExtraStuff:stuff]; + 7: @} +@end example + +@ssindex objc-method-intro +@ssindex objc-method-args-cont +@ssindex objc-method-call-cont +Here, line 1 is assigned @code{objc-method-intro} syntax, and line 2 is +assigned @code{objc-method-args-cont} syntax. Lines 5 and 6 are both +assigned @code{objc-method-call-cont} syntax. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Java Symbols, Statement Block Symbols, Objective-C Method Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Java Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Java has a concept of anonymous classes which can look something like +this: + +@example + 1: @@Test + 2: public void watch(Observable o) @{ + 3: @@NonNull + 4: Observer obs = new Observer() @{ + 5: public void update(Observable o, Object arg) @{ + 6: history.addElement(arg); + 7: @} + 8: @}; + 9: o.addObserver(obs); + 10: @} +@end example + +@ssindex inexpr-class +The brace following the @code{new} operator opens the anonymous class. +Lines 5 and 8 are assigned the @code{inexpr-class} syntax, besides the +@code{inclass} symbol used in normal classes. Thus, the class will be +indented just like a normal class, with the added indentation given to +@code{inexpr-class}. An @code{inexpr-class} syntactic element doesn't +have an anchor position. + +@ssindex annotation-top-cont +@ssindex annotation-var-cont +Line 2 is assigned the @code{annotation-top-cont} syntax, due to it being a +continuation of a topmost introduction with an annotation symbol preceding +the current line. Similarly, line 4 is assigned the @code{annotation-var-cont} +syntax due to it being a continuation of a variable declaration where preceding +the declaration is an annotation. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Statement Block Symbols, K&R Symbols, Java Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection Statement Block Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +There are a few occasions where a statement block might be used inside +an expression. One is in C or C++ code using the gcc extension for +this, e.g: + +@example + 1: int res = (@{ + 2: int y = foo (); int z; + 3: if (y > 0) z = y; else z = - y; + 4: z; + 5: @}); +@end example + +@ssindex inexpr-statement +Lines 2 and 5 get the @code{inexpr-statement} syntax, besides the +symbols they'd get in a normal block. Therefore, the indentation put on +@code{inexpr-statement} is added to the normal statement block +indentation. An @code{inexpr-statement} syntactic element doesn't +contain an anchor position. + +In Pike code, there are a few other situations where blocks occur inside +statements, as illustrated here: + +@example + 1: array itgob() + 2: @{ + 3: string s = map (backtrace()[-2][3..], + 4: lambda + 5: (mixed arg) + 6: @{ + 7: return sprintf ("%t", arg); + 8: @}) * ", " + "\n"; + 9: return catch @{ +10: write (s + "\n"); +11: @}; +12: @} +@end example + +@ssindex inlambda +@ssindex lambda-intro-cont +Lines 4 through 8 contain a lambda function, which @ccmode{} recognizes +by the @code{lambda} keyword. If the function argument list is put +on a line of its own, as in line 5, it gets the @code{lambda-intro-cont} +syntax. The function body is handled as an inline method body, with the +addition of the @code{inlambda} syntactic symbol. This means that line +6 gets @code{inlambda} and @code{inline-open}, and line 8 gets +@code{inline-close}@footnote{You might wonder why it doesn't get +@code{inlambda} too. It's because the closing brace is relative to the +opening brace, which stands on its own line in this example. If the +opening brace was hanging on the previous line, then the closing brace +would get the @code{inlambda} syntax too to be indented correctly.}. + +@ssindex inexpr-statement +On line 9, @code{catch} is a special function taking a statement block +as its argument. The block is handled as an in-expression statement +with the @code{inexpr-statement} syntax, just like the gcc extended C +example above. The other similar special function, @code{gauge}, is +handled like this too. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node K&R Symbols, , Statement Block Symbols, Syntactic Symbols +@comment node-name, next, previous, up +@subsection K&R Symbols +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@ssindex knr-argdecl-intro +@ssindex knr-argdecl +Two other syntactic symbols can appear in old style, non-prototyped C +code @footnote{a.k.a. K&R C, or Kernighan & Ritchie C}: + +@example + 1: int add_three_integers(a, b, c) + 2: int a; + 3: int b; + 4: int c; + 5: @{ + 6: return a + b + c; + 7: @} +@end example + +Here, line 2 is the first line in an argument declaration list and so is +given the @code{knr-argdecl-intro} syntactic symbol. Subsequent lines +(i.e. lines 3 and 4 in this example), are given @code{knr-argdecl} +syntax. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Indentation Calculation, , Syntactic Symbols, Indentation Engine Basics +@comment node-name, next, previous, up +@section Indentation Calculation +@cindex indentation +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Indentation for a line is calculated from the syntactic context +(@pxref{Syntactic Analysis}). + +First, a buffer position is found whose column will be the base for the +indentation calculation. It's the anchor position in the first +syntactic element that provides one that is used. If no syntactic +element has an anchor position then column zero is used. + +Second, the syntactic symbols in each syntactic element are looked up +in the @code{c-offsets-alist} style variable +(@pxref{c-offsets-alist}), which is an association list of syntactic +symbols and the offsets to apply for those symbols. These offsets are +added together with the base column to produce the new indentation +column. + +Let's use our two code examples above to see how this works. Here is +our first example again: + +@example + 1: void swap( int& a, int& b ) + 2: @{ + 3: int tmp = a; + 4: a = b; + 5: b = tmp; + 6: @} +@end example + +Let's say point is on line 3 and we hit the @key{TAB} key to reindent +the line. The syntactic context for that line is: + +@example +((defun-block-intro 29)) +@end example + +@noindent +Since buffer position 29 is the first and only anchor position in the +list, @ccmode{} goes there and asks for the current column. This brace +is in column zero, so @ccmode{} uses @samp{0} as the base column. + +Next, @ccmode{} looks up @code{defun-block-intro} in the +@code{c-offsets-alist} style variable. Let's say it finds the value +@samp{4}; it adds this to the base column @samp{0}, yielding a running +total indentation of 4 spaces. + +Since there is only one syntactic element on the list for this line, +indentation calculation is complete, and the total indentation for the +line is 4 spaces. + +Here's another example: + +@example + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end example + +If we were to hit @kbd{TAB} on line 4 in the above example, the same +basic process is performed, despite the differences in the syntactic +context. The context for this line is: + +@example +((substatement-open 46)) +@end example + +Here, @ccmode{} goes to buffer position 46, which is the @samp{i} in +@code{if} on line 3. This character is in the fourth column on that +line so the base column is @samp{4}. Then @ccmode{} looks up the +@code{substatement-open} symbol in @code{c-offsets-alist}. Let's say it +finds the value @samp{4}. It's added with the base column and yields an +indentation for the line of 8 spaces. + +Simple, huh? + +Actually, it's a bit more complicated than that since the entries on +@code{c-offsets-alist} can be much more than plain offsets. +@xref{c-offsets-alist}, for the full story. + +Anyway, the mode usually just does The Right Thing without you having to +think about it in this much detail. But when customizing indentation, +it's helpful to understand the general indentation model being used. + +As you configure @ccmode{}, you might want to set the variable +@code{c-echo-syntactic-information-p} to non-@code{nil} so that the +syntactic context and calculated offset always is echoed in the +minibuffer when you hit @kbd{TAB}. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Customizing Indentation, Custom Macros, Indentation Engine Basics, Top +@comment node-name, next, previous, up +@chapter Customizing Indentation +@cindex customization, indentation +@cindex indentation +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The principal variable for customizing indentation is the style +variable @code{c-offsets-alist}, which gives an @dfn{offset} (an +indentation rule) for each syntactic symbol. Its structure and +semantics are completely described in @ref{c-offsets-alist}. The +various ways you can set the variable, including the use of the +@ccmode{} style system, are described in @ref{Config Basics} and its +sections, in particular @ref{Style Variables}. + +The simplest and most used kind of ``offset'' setting in +@code{c-offsets-alist} is in terms of multiples of +@code{c-basic-offset}: + +@defopt c-basic-offset +@vindex basic-offset (c-) +This style variable holds the basic offset between indentation levels. +It's factory default is 4, but all the built-in styles set it +themselves, to some value between 2 (for @code{gnu} style) and 8 (for +@code{bsd}, @code{linux}, and @code{python} styles). +@end defopt + +The most flexible ``offset'' setting you can make in +@code{c-offsets-alist} is a line-up function (or even a list of them), +either one supplied by @ccmode{} (@pxref{Line-Up Functions}) or one +you write yourself (@pxref{Custom Line-Up}). + +Finally, in @ref{Other Indentation} you'll find the tool of last +resort: a hook which is called after a line has been indented. You +can install functions here to make ad-hoc adjustments to any line's +indentation. + +@menu +* c-offsets-alist:: +* Interactive Customization:: +* Line-Up Functions:: +* Custom Line-Up:: +* Other Indentation:: +@end menu + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node c-offsets-alist, Interactive Customization, Customizing Indentation, Customizing Indentation +@comment node-name, next, previous, up +@section c-offsets-alist +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +This section explains the structure and semantics of the style +variable @code{c-offsets-alist}, the principal variable for configuring +indentation. Details of how to set it up, and its relationship to +@ccmode{}'s style system are given in @ref{Style Variables}. + +@defopt c-offsets-alist +@vindex offsets-alist (c-) +This is an alist which associates an offset with each syntactic +symbol. This @dfn{offset} is a rule specifying how to indent a line +whose syntactic context matches the symbol. @xref{Syntactic +Analysis}. + +Note that the buffer-local binding of this alist in a @ccmode{} buffer +contains an entry for @emph{every} syntactic symbol. Its global +binding and its settings within style specifications usually contain +only a few entries. @xref{Style Variables}. + +The offset specification associated with any particular syntactic +symbol can be an integer, a variable name, a vector, a function or +lambda expression, a list, or one of the following special symbols: +@code{+}, @code{-}, @code{++}, @code{--}, @code{*}, or @code{/}. The +meanings of these values are described in detail below. + +Here is an example fragment of a @code{c-offsets-alist}, showing some +of these kinds of offsets: + +@example +((statement . 0) + (substatement . +) + (cpp-macro . [0]) + (topmost-intro-cont . c-lineup-topmost-intro-cont) + (statement-block-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + @dots{} +@*) +@end example +@end defopt + +@deffn Command c-set-offset (@kbd{C-c C-o}) +@findex set-offset (c-) +@kindex C-c C-o +This command changes the entry for a syntactic symbol in the current +binding of @code{c-offsets-alist}, or it inserts a new entry if there +isn't already one for that syntactic symbol. + +You can use @code{c-set-offsets} interactively within a @ccmode{} +buffer to make experimental changes to your indentation settings. +@kbd{C-c C-o} prompts you for the syntactic symbol to change +(defaulting to that of the current line) and the new offset +(defaulting to the current offset). + +@code{c-set-offsets} takes two arguments when used programmatically: +@var{symbol}, the syntactic element symbol to change and @var{offset}, +the new offset for that syntactic element. You can call the command +in your @file{.emacs} to change the global binding of +@code{c-offsets-alist} (@pxref{Style Variables}); you can use it in a +hook function to make changes from the current style. @ccmode{} +itself uses this function when initializing styles. +@end deffn + +@cindex offset specification +The ``offset specifications'' in @code{c-offsets-alist} can be any of +the following: + +@table @asis +@item An integer +The integer specifies a relative offset. All relative +offsets@footnote{The syntactic context @code{@w{((defun-block-intro +2724) (comment-intro))}} would likely have two relative offsets.} will +be added together and used to calculate the indentation relative to an +anchor position earlier in the buffer. @xref{Indentation +Calculation}, for details. Most of the time, it's probably better to +use one of the special symbols like @code{+} than an integer (apart +from zero). + +@item One of the symbols @code{+}, @code{-}, @code{++}, @code{--}, @code{*}, or @code{/} +These special symbols describe a relative offset in multiples of +@code{c-basic-offset}: + +By defining a style's indentation in terms of @code{c-basic-offset}, +you can change the amount of whitespace given to an indentation level +while maintaining the same basic shape of your code. Here are the +values that the special symbols correspond to: + +@table @code +@item + +@code{c-basic-offset} times 1 +@item - +@code{c-basic-offset} times -1 +@item ++ +@code{c-basic-offset} times 2 +@item -- +@code{c-basic-offset} times -2 +@item * +@code{c-basic-offset} times 0.5 +@item / +@code{c-basic-offset} times -0.5 +@end table + +@item A vector +The first element of the vector, an integer, sets the absolute +indentation column. This will override any previously calculated +indentation, but won't override relative indentation calculated from +syntactic elements later on in the syntactic context of the line being +indented. @xref{Indentation Calculation}. Any elements in the vector +beyond the first will be ignored. + +@item A function or lambda expression +The function will be called and its return value will in turn be +evaluated as an offset specification. Functions are useful when more +context than just the syntactic symbol is needed to get the desired +indentation. @xref{Line-Up Functions}, and @ref{Custom Line-Up}, for +details about them. + +@item A symbol with a variable binding +If the symbol also has a function binding, the function takes +precedence over the variable. Otherwise the value of the variable is +used. It must be an integer (which is used as relative offset) or a +vector (an absolute offset). + +@item A list +The offset can also be a list containing several offset +specifications; these are evaluated recursively and combined. A list +is typically only useful when some of the offsets are line-up +functions. A common strategy is calling a sequence of functions in +turn until one of them recognizes that it is appropriate for the +source line and returns a non-@code{nil} value. + +@code{nil} values are always ignored when the offsets are combined. +The first element of the list specifies the method of combining the +non-@code{nil} offsets from the remaining elements: + +@table @code +@item first +Use the first offset that doesn't evaluate to @code{nil}. Subsequent +elements of the list don't get evaluated. +@item min +Use the minimum of all the offsets. All must be either relative or +absolute - they can't be mixed. +@item max +Use the maximum of all the offsets. All must be either relative or +absolute - they can't be mixed. +@item add +Add all the evaluated offsets together. Exactly one of them may be +absolute, in which case the result is absolute. Any relative offsets +that preceded the absolute one in the list will be ignored in that case. +@end table + +As a compatibility measure, if the first element is none of the above +then it too will be taken as an offset specification and the whole list +will be combined according to the method @code{first}. +@end table + +@vindex c-strict-syntax-p +@vindex strict-syntax-p (c-) +If an offset specification evaluates to @code{nil}, then a relative +offset of 0 (zero) is used@footnote{There is however a variable +@code{c-strict-syntax-p} that when set to non-@code{nil} will cause an +error to be signaled in that case. It's now considered obsolete since +it doesn't work well with some of the alignment functions that return +@code{nil} instead of zero. You should therefore leave +@code{c-strict-syntax-p} set to @code{nil}.}. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Interactive Customization, Line-Up Functions, c-offsets-alist, Customizing Indentation +@comment node-name, next, previous, up +@section Interactive Customization +@cindex customization, interactive +@cindex interactive customization +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +As an example of how to customize indentation, let's change the +style of this example@footnote{In this and subsequent examples, the +original code is formatted using the @samp{gnu} style unless otherwise +indicated. @xref{Styles}.}: + +@example +@group + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end group +@end example + +@noindent +to: + +@example +@group + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end group +@end example + +In other words, we want to change the indentation of braces that open a +block following a condition so that the braces line up under the +conditional, instead of being indented. Notice that the construct we +want to change starts on line 4. To change the indentation of a line, +we need to see which syntactic symbols affect the offset calculations +for that line. Hitting @kbd{C-c C-s} on line 4 yields: + +@example +((substatement-open 44)) +@end example + +@noindent +so we know that to change the offset of the open brace, we need to +change the indentation for the @code{substatement-open} syntactic +symbol. + +To do this interactively, just hit @kbd{C-c C-o}. This prompts +you for the syntactic symbol to change, providing a reasonable default. +In this case, the default is @code{substatement-open}, which is just the +syntactic symbol we want to change! + +After you hit return, @ccmode{} will then prompt you for the new +offset value, with the old value as the default. The default in this +case is @samp{+}, but we want no extra indentation so enter +@samp{0} and @kbd{RET}. This will associate the offset 0 with the +syntactic symbol @code{substatement-open}. + +To check your changes quickly, just hit @kbd{C-c C-q} +(@code{c-indent-defun}) to reindent the entire function. The example +should now look like: + +@example +@group + 1: int add( int val, int incr, int doit ) + 2: @{ + 3: if( doit ) + 4: @{ + 5: return( val + incr ); + 6: @} + 7: return( val ); + 8: @} +@end group +@end example + +Notice how just changing the open brace offset on line 4 is all we +needed to do. Since the other affected lines are indented relative to +line 4, they are automatically indented the way you'd expect. For more +complicated examples, this might not always work. The general approach +to take is to always start adjusting offsets for lines higher up in the +file, then reindent and see if any following lines need further +adjustments. + +@c Move this bit to "Styles" (2005/10/7) +@deffn Command c-set-offset symbol offset +@findex set-offset (c-) +@kindex C-c C-o +This is the command bound to @kbd{C-c C-o}. It provides a convenient +way to set offsets on @code{c-offsets-alist} both interactively (see +the example above) and from your mode hook. + +It takes two arguments when used programmatically: @var{symbol} is the +syntactic element symbol to change and @var{offset} is the new offset +for that syntactic element. +@end deffn +@c End of MOVE THIS BIT. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Line-Up Functions, Custom Line-Up, Interactive Customization, Customizing Indentation +@comment node-name, next, previous, up +@section Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@cindex line-up function +@cindex indentation function +Often there are cases when a simple offset setting on a syntactic +symbol isn't enough to get the desired indentation---for example, you +might want to line up a closing parenthesis with the matching opening +one rather than indenting relative to its ``anchor point''. @ccmode{} +provides this flexibility with @dfn{line-up functions}. + +The way you associate a line-up function with a syntactic symbol is +described in @ref{c-offsets-alist}. @ccmode{} comes with many +predefined line-up functions for common situations. If none of these +does what you want, you can write your own. @xref{Custom Line-Up}. +Sometimes, it is easier to tweak the standard indentation by adding a +function to @code{c-special-indent-hook} (@pxref{Other Indentation}). + +The line-up functions haven't been adapted for AWK buffers or tested +with them. Some of them might work serendipitously. There shouldn't be +any problems writing custom line-up functions for AWK mode. + +The calling convention for line-up functions is described fully in +@ref{Custom Line-Up}. Roughly speaking, the return value is either an +offset itself (such as @code{+} or @code{[0]}) or it's @code{nil}, +meaning ``this function is inappropriate in this case - try a +different one''. @xref{c-offsets-alist}. + +The subsections below describe all the standard line-up functions, +categorized by the sort of token the lining-up centers around. For +each of these functions there is a ``works with'' list that indicates +which syntactic symbols the function is intended to be used with. + +@macro workswith +@emph{Works with:@ } +@end macro +@ifinfo +@unmacro workswith +@macro workswith +Works with: +@end macro +@end ifinfo + +@macro sssTBasicOffset +<--> @i{c-basic-offset}@c +@end macro + +@macro sssTsssTBasicOffset +<--><--> @i{c-basic-offset}@c +@end macro + +@macro hereFn{func} +<- @i{\func\}@c +@end macro + +@c The TeX backend seems to insert extra spaces around the argument. :P +@iftex +@unmacro hereFn +@macro hereFn{func} +<-@i{\func\}@c +@end macro +@end iftex + +@menu +* Brace/Paren Line-Up:: +* List Line-Up:: +* Operator Line-Up:: +* Comment Line-Up:: +* Misc Line-Up:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Brace/Paren Line-Up, List Line-Up, Line-Up Functions, Line-Up Functions +@comment node-name, next, previous, up +@subsection Brace and Parenthesis Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The line-up functions here calculate the indentation for braces, +parentheses and statements within brace blocks. + +@defun c-lineup-close-paren +@findex lineup-close-paren (c-) +Line up the closing paren under its corresponding open paren if the +open paren is followed by code. If the open paren ends its line, no +indentation is added. E.g: + +@example +@group +main (int, + char ** + ) @hereFn{c-lineup-close-paren} +@end group +@end example + +@noindent +and + +@example +@group +main ( + int, char ** +) @hereFn{c-lineup-close-paren} +@end group +@end example + +As a special case, if a brace block is opened at the same line as the +open parenthesis of the argument list, the indentation is +@code{c-basic-offset} instead of the open paren column. See +@code{c-lineup-arglist} for further discussion of this ``DWIM'' measure. + +@workswith All @code{*-close} symbols. +@end defun + +@comment ------------------------------------------------------------ + +@anchor{c-lineup-arglist-close-under-paren} +@defun c-lineup-arglist-close-under-paren +@findex lineup-arglist-close-under-paren (c-) +Set your @code{arglist-close} syntactic symbol to this line-up function +so that parentheses that close argument lists will line up under the +parenthesis that opened the argument list. It can also be used with +@code{arglist-cont} and @code{arglist-cont-nonempty} to line up all +lines inside a parenthesis under the open paren. + +As a special case, if a brace block is opened at the same line as the +open parenthesis of the argument list, the indentation is +@code{c-basic-offset} only. See @code{c-lineup-arglist} for further +discussion of this ``DWIM'' measure. + +@workswith Almost all symbols, but are typically most useful on +@code{arglist-close}, @code{brace-list-close}, @code{arglist-cont} and +@code{arglist-cont-nonempty}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-indent-one-line-block +@findex indent-one-line-block (c-) +Indent a one line block @code{c-basic-offset} extra. E.g: + +@example +@group +if (n > 0) + @{m+=n; n=0;@} @hereFn{c-indent-one-line-block} +@sssTBasicOffset{} +@end group +@end example + +@noindent +and + +@example +@group +if (n > 0) +@{ @hereFn{c-indent-one-line-block} + m+=n; n=0; +@} +@end group +@end example + +The block may be surrounded by any kind of parenthesis characters. +@code{nil} is returned if the line doesn't start with a one line block, +which makes the function usable in list expressions. + +@workswith Almost all syntactic symbols, but most useful on the +@code{-open} symbols. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-indent-multi-line-block +@findex indent-multi-line-block (c-) +Indent a multiline block @code{c-basic-offset} extra. E.g: + +@example +@group +int *foo[] = @{ + NULL, + @{17@}, @hereFn{c-indent-multi-line-block} +@end group +@end example + +@noindent +and + +@example +@group +int *foo[] = @{ + NULL, + @{ @hereFn{c-indent-multi-line-block} + 17 + @}, + @sssTBasicOffset{} +@end group +@end example + +The block may be surrounded by any kind of parenthesis characters. +@code{nil} is returned if the line doesn't start with a multiline +block, which makes the function usable in list expressions. + +@workswith Almost all syntactic symbols, but most useful on the +@code{-open} symbols. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-runin-statements +@findex lineup-runin-statements (c-) +Line up statements for coding standards which place the first statement +in a block on the same line as the block opening brace@footnote{Run-in +style doesn't really work too well. You might need to write your own +custom line-up functions to better support this style.}. E.g: + +@example +@group +int main() +@{ puts ("Hello!"); + return 0; @hereFn{c-lineup-runin-statements} +@} +@end group +@end example + +If there is no statement after the opening brace to align with, +@code{nil} is returned. This makes the function usable in list +expressions. + +@workswith The @code{statement} syntactic symbol. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-inexpr-block +@findex lineup-inexpr-block (c-) +This can be used with the in-expression block symbols to indent the +whole block to the column where the construct is started. E.g. for Java +anonymous classes, this lines up the class under the @samp{new} keyword, +and in Pike it lines up the lambda function body under the @samp{lambda} +keyword. Returns @code{nil} if the block isn't part of such a +construct. + +@workswith @code{inlambda}, @code{inexpr-statement}, +@code{inexpr-class}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-after-whitesmith-blocks +@findex lineup-after-whitesmith-blocks (c-) +Compensate for Whitesmith style indentation of blocks. Due to the way +@ccmode{} calculates anchor positions for normal lines inside blocks, +this function is necessary for those lines to get correct Whitesmith +style indentation. Consider the following examples: + +@example +@group +int foo() + @{ + a; + x; @hereFn{c-lineup-after-whitesmith-blocks} +@end group +@end example + +@example +@group +int foo() + @{ + @{ + a; + @} + x; @hereFn{c-lineup-after-whitesmith-blocks} +@end group +@end example + +The fact that the line with @code{x} is preceded by a Whitesmith style +indented block in the latter case and not the first should not affect +its indentation. But since CC Mode in cases like this uses the +indentation of the preceding statement as anchor position, the @code{x} +would in the second case be indented too much if the offset for +@code{statement} was set simply to zero. + +This lineup function corrects for this situation by detecting if the +anchor position is at an open paren character. In that case, it instead +indents relative to the surrounding block just like +@code{c-lineup-whitesmith-in-block}. + +@workswith @code{brace-list-entry}, @code{brace-entry-open}, +@code{statement}, @code{arglist-cont}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-whitesmith-in-block +@findex lineup-whitesmith-in-block (c-) +Line up lines inside a block in Whitesmith style. It's done in a way +that works both when the opening brace hangs and when it doesn't. E.g: + +@example +@group +something + @{ + foo; @hereFn{c-lineup-whitesmith-in-block} + @} +@end group +@end example + +@noindent +and + +@example +@group +something @{ + foo; @hereFn{c-lineup-whitesmith-in-block} + @} +@sssTBasicOffset{} +@end group +@end example + +In the first case the indentation is kept unchanged, in the second +@code{c-basic-offset} is added. + +@workswith @code{defun-close}, @code{defun-block-intro}, +@code{inline-close}, @code{block-close}, @code{brace-list-close}, +@code{brace-list-intro}, @code{statement-block-intro}, +@code{arglist-intro}, @code{arglist-cont-nonempty}, +@code{arglist-close}, and all @code{in*} symbols, e.g. @code{inclass} +and @code{inextern-lang}. +@end defun + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node List Line-Up, Operator Line-Up, Brace/Paren Line-Up, Line-Up Functions +@comment node-name, next, previous, up +@subsection List Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The line-up functions here calculate the indentation for lines which +form lists of items, usually separated by commas. + +The function @ref{c-lineup-arglist-close-under-paren}, which is mainly +for indenting a close parenthesis, is also useful for the lines +contained within parentheses. + +@defun c-lineup-arglist +@findex lineup-arglist (c-) +Line up the current argument line under the first argument. + +As a special case, if an argument on the same line as the open +parenthesis starts with a brace block opener, the indentation is +@code{c-basic-offset} only. This is intended as a ``DWIM'' measure in +cases like macros that contain statement blocks, e.g: + +@example +@group +A_VERY_LONG_MACRO_NAME (@{ + some (code, with + long, lines * in[it]); + @}); +@sssTBasicOffset{} +@end group +@end example + +This is motivated partly because it's more in line with how code +blocks are handled, and partly since it approximates the behavior of +earlier CC Mode versions, which due to inaccurate analysis tended to +indent such cases this way. + +@workswith @code{arglist-cont-nonempty}, @code{arglist-close}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-arglist-intro-after-paren +@findex lineup-arglist-intro-after-paren (c-) +Line up a line to just after the open paren of the surrounding paren or +brace block. + +@workswith @code{defun-block-intro}, @code{brace-list-intro}, +@code{statement-block-intro}, @code{statement-case-intro}, +@code{arglist-intro}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-multi-inher +@findex lineup-multi-inher (c-) +Line up the classes in C++ multiple inheritance clauses and member +initializers under each other. E.g: + +@example +@group +Foo::Foo (int a, int b): + Cyphr (a), + Bar (b) @hereFn{c-lineup-multi-inher} +@end group +@end example + +@noindent +and + +@example +@group +class Foo + : public Cyphr, + public Bar @hereFn{c-lineup-multi-inher} +@end group +@end example + +@noindent +and + +@example +@group +Foo::Foo (int a, int b) + : Cyphr (a) + , Bar (b) @hereFn{c-lineup-multi-inher} +@end group +@end example + +@workswith @code{inher-cont}, @code{member-init-cont}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-java-inher +@findex lineup-java-inher (c-) +Line up Java implements and extends declarations. If class names +follow on the same line as the @samp{implements}/@samp{extends} +keyword, they are lined up under each other. Otherwise, they are +indented by adding @code{c-basic-offset} to the column of the keyword. +E.g: + +@example +@group +class Foo + extends + Bar @hereFn{c-lineup-java-inher} + @sssTBasicOffset{} +@end group +@end example + +@noindent +and + +@example +@group +class Foo + extends Cyphr, + Bar @hereFn{c-lineup-java-inher} +@end group +@end example + +@workswith @code{inher-cont}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-java-throws +@findex lineup-java-throws (c-) +Line up Java throws declarations. If exception names follow on the +same line as the throws keyword, they are lined up under each other. +Otherwise, they are indented by adding @code{c-basic-offset} to the +column of the @samp{throws} keyword. The @samp{throws} keyword itself +is also indented by @code{c-basic-offset} from the function declaration +start if it doesn't hang. E.g: + +@example +@group +int foo() + throws @hereFn{c-lineup-java-throws} + Bar @hereFn{c-lineup-java-throws} +@sssTsssTBasicOffset{} +@end group +@end example + +@noindent +and + +@example +@group +int foo() throws Cyphr, + Bar, @hereFn{c-lineup-java-throws} + Vlod @hereFn{c-lineup-java-throws} +@end group +@end example + +@workswith @code{func-decl-cont}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-template-args +@findex lineup-template-args (c-) +Line up the arguments of a template argument list under each other, but +only in the case where the first argument is on the same line as the +opening @samp{<}. + +To allow this function to be used in a list expression, @code{nil} is +returned if there's no template argument on the first line. + +@workswith @code{template-args-cont}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-ObjC-method-call +@findex lineup-ObjC-method-call (c-) +For Objective-C code, line up selector args as Emacs Lisp mode does +with function args: go to the position right after the message receiver, +and if you are at the end of the line, indent the current line +c-basic-offset columns from the opening bracket; otherwise you are +looking at the first character of the first method call argument, so +lineup the current line with it. + +@workswith @code{objc-method-call-cont}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-ObjC-method-args +@findex lineup-ObjC-method-args (c-) +For Objective-C code, line up the colons that separate args. The colon +on the current line is aligned with the one on the first line. + +@workswith @code{objc-method-args-cont}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-ObjC-method-args-2 +@findex lineup-ObjC-method-args-2 (c-) +Similar to @code{c-lineup-ObjC-method-args} but lines up the colon on +the current line with the colon on the previous line. + +@workswith @code{objc-method-args-cont}. +@end defun + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Operator Line-Up, Comment Line-Up, List Line-Up, Line-Up Functions +@comment node-name, next, previous, up +@subsection Operator Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The line-up functions here calculate the indentation for lines which +start with an operator, by lining it up with something on the previous +line. + +@defun c-lineup-argcont +@findex lineup-argcont (c-) +Line up a continued argument. E.g: + +@example +@group +foo (xyz, aaa + bbb + ccc + + ddd + eee + fff); @hereFn{c-lineup-argcont} +@end group +@end example + +Only continuation lines like this are touched, @code{nil} is returned on +lines which are the start of an argument. + +Within a gcc @code{asm} block, @code{:} is recognized as an argument +separator, but of course only between operand specifications, not in the +expressions for the operands. + +@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-arglist-operators +@findex lineup-arglist-operators (c-) +Line up lines starting with an infix operator under the open paren. +Return @code{nil} on lines that don't start with an operator, to leave +those cases to other line-up functions. Example: + +@example +@group +if ( x < 10 + || at_limit (x, @hereFn{c-lineup-arglist-operators} + list) @hereFn{c-lineup-arglist-operators@r{ returns nil}} + ) +@end group +@end example + +Since this function doesn't do anything for lines without an infix +operator you typically want to use it together with some other lineup +settings, e.g. as follows (the @code{arglist-close} setting is just a +suggestion to get a consistent style): + +@example +(c-set-offset 'arglist-cont + '(c-lineup-arglist-operators 0)) +(c-set-offset 'arglist-cont-nonempty + '(c-lineup-arglist-operators c-lineup-arglist)) +(c-set-offset 'arglist-close + '(c-lineup-arglist-close-under-paren)) +@end example + +@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-assignments +@findex lineup-assignments (c-) +Line up the current line after the assignment operator on the first line +in the statement. If there isn't any, return nil to allow stacking with +other line-up functions. If the current line contains an assignment +operator too, try to align it with the first one. + +@workswith @code{topmost-intro-cont}, @code{statement-cont}, +@code{arglist-cont}, @code{arglist-cont-nonempty}. + +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-math +@findex lineup-math (c-) +Like @code{c-lineup-assignments} but indent with @code{c-basic-offset} +if no assignment operator was found on the first line. I.e. this +function is the same as specifying a list @code{(c-lineup-assignments ++)}. It's provided for compatibility with old configurations. + +@workswith @code{topmost-intro-cont}, @code{statement-cont}, +@code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-cascaded-calls +@findex lineup-cascaded-calls (c-) +Line up ``cascaded calls'' under each other. If the line begins with +@code{->} or @code{.} and the preceding line ends with one or more +function calls preceded by the same token, then the arrow is lined up +with the first of those tokens. E.g: + +@example +@group +r = proc->add(17)->add(18) + ->add(19) + @hereFn{c-lineup-cascaded-calls} + offset; @hereFn{c-lineup-cascaded-calls@r{ (inactive)}} +@end group +@end example + +In any other situation @code{nil} is returned to allow use in list +expressions. + +@workswith @code{topmost-intro-cont}, @code{statement-cont}, +@code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-streamop +@findex lineup-streamop (c-) +Line up C++ stream operators (i.e. @samp{<<} and @samp{>>}). + +@workswith @code{stream-op}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-string-cont +@findex lineup-string-cont (c-) +Line up a continued string under the one it continues. A continued +string in this sense is where a string literal follows directly after +another one. E.g: + +@example +@group +result = prefix + "A message " + "string."; @hereFn{c-lineup-string-cont} +@end group +@end example + +@code{nil} is returned in other situations, to allow stacking with other +lineup functions. + +@workswith @code{topmost-intro-cont}, @code{statement-cont}, +@code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Comment Line-Up, Misc Line-Up, Operator Line-Up, Line-Up Functions +@comment node-name, next, previous, up +@subsection Comment Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The lineup functions here calculate the indentation for several types +of comment structure. + +@defun c-lineup-C-comments +@findex lineup-C-comments (c-) +Line up C block comment continuation lines. Various heuristics are used +to handle most of the common comment styles. Some examples: + +@example +@group +/* /** /* + * text * text text + */ */ */ +@end group +@end example + +@example +@group +/* text /* /** + text ** text ** text +*/ */ */ +@end group +@end example + +@example +@group +/************************************************** + * text + *************************************************/ +@end group +@end example + +@vindex comment-start-skip +@example +@group +/************************************************** + Free form text comments: + In comments with a long delimiter line at the + start, the indentation is kept unchanged for lines + that start with an empty comment line prefix. The + delimiter line is whatever matches the + @code{comment-start-skip} regexp. +**************************************************/ +@end group +@end example + +The style variable @code{c-comment-prefix-regexp} is used to recognize +the comment line prefix, e.g. the @samp{*} that usually starts every +line inside a comment. + +@workswith The @code{c} syntactic symbol. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-comment +@findex lineup-comment (c-) +Line up a comment-only line according to the style variable +@code{c-comment-only-line-offset}. If the comment is lined up with a +comment starter on the previous line, that alignment is preserved. + +@defopt c-comment-only-line-offset +@vindex comment-only-line-offset (c-) +This style variable specifies the extra offset for the line. It can +contain an integer or a cons cell of the form + +@example +(@r{@var{non-anchored-offset}} . @r{@var{anchored-offset}}) +@end example + +@noindent +where @var{non-anchored-offset} is the amount of offset given to +non-column-zero anchored lines, and @var{anchored-offset} is the amount +of offset to give column-zero anchored lines. Just an integer as value +is equivalent to @code{(@r{@var{value}} . -1000)}. +@end defopt + +@workswith @code{comment-intro}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-knr-region-comment +@findex lineup-knr-region-comment (c-) +Line up a comment in the ``K&R region'' with the declaration. That is +the region between the function or class header and the beginning of the +block. E.g: + +@example +@group +int main() +/* Called at startup. */ @hereFn{c-lineup-knr-region-comment} +@{ + return 0; +@} +@end group +@end example + +Return @code{nil} if called in any other situation, to be useful in list +expressions. + +@workswith @code{comment-intro}. +@end defun + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Misc Line-Up, , Comment Line-Up, Line-Up Functions +@comment node-name, next, previous, up +@subsection Miscellaneous Line-Up Functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The line-up functions here are the odds and ends which didn't fit into +any earlier category. + +@defun c-lineup-dont-change +@findex lineup-dont-change (c-) +This lineup function makes the line stay at whatever indentation it +already has; think of it as an identity function for lineups. + +@workswith Any syntactic symbol. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-cpp-define +@findex lineup-cpp-define (c-) +Line up macro continuation lines according to the indentation of the +construct preceding the macro. E.g: + +@example +@group +const char msg[] = @hereFn{@r{The beginning of the preceding construct.}} + \"Some text.\"; + +#define X(A, B) \ +do @{ \ @hereFn{c-lineup-cpp-define} + printf (A, B); \ +@} while (0) +@end group +@end example + +@noindent +and: + +@example +@group +int dribble() @{ + if (!running) @hereFn{@r{The beginning of the preceding construct.}} + error(\"Not running!\"); + +#define X(A, B) \ + do @{ \ @hereFn{c-lineup-cpp-define} + printf (A, B); \ + @} while (0) +@end group +@end example + +If @code{c-syntactic-indentation-in-macros} is non-@code{nil}, the +function returns the relative indentation to the macro start line to +allow accumulation with other offsets. E.g. in the following cases, +@code{cpp-define-intro} is combined with the +@code{statement-block-intro} that comes from the @samp{do @{} that hangs +on the @samp{#define} line: + +@example +@group +const char msg[] = + \"Some text.\"; + +#define X(A, B) do @{ \ + printf (A, B); \ @hereFn{c-lineup-cpp-define} + this->refs++; \ +@} while (0) @hereFn{c-lineup-cpp-define} +@end group +@end example + +@noindent +and: + +@example +@group +int dribble() @{ + if (!running) + error(\"Not running!\"); + +#define X(A, B) do @{ \ + printf (A, B); \ @hereFn{c-lineup-cpp-define} + this->refs++; \ + @} while (0) @hereFn{c-lineup-cpp-define} +@end group +@end example + +The relative indentation returned by @code{c-lineup-cpp-define} is zero +and two, respectively, on the two lines in each of these examples. They +are then added to the two column indentation that +@code{statement-block-intro} gives in both cases here. + +If the relative indentation is zero, then @code{nil} is returned +instead. That is useful in a list expression to specify the default +indentation on the top level. + +If @code{c-syntactic-indentation-in-macros} is @code{nil} then this +function keeps the current indentation, except for empty lines (ignoring +the ending backslash) where it takes the indentation from the closest +preceding nonempty line in the macro. If there's no such line in the +macro then the indentation is taken from the construct preceding it, as +described above. + +@workswith @code{cpp-define-intro}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-gcc-asm-reg +@findex lineup-gcc-asm-reg (c-) +Line up a gcc asm register under one on a previous line. + +@example +@group + asm ("foo %1, %0\n" + "bar %0, %1" + : "=r" (w), + "=r" (x) + : "0" (y), + "1" (z)); +@end group +@end example + +The @samp{x} line is aligned to the text after the @samp{:} on the +@samp{w} line, and similarly @samp{z} under @samp{y}. + +This is done only in an @samp{asm} or @samp{__asm__} block, and only to +those lines mentioned. Anywhere else @code{nil} is returned. The usual +arrangement is to have this routine as an extra feature at the start of +arglist lineups, e.g. + +@example +(c-lineup-gcc-asm-reg c-lineup-arglist) +@end example + +@workswith @code{arglist-cont}, @code{arglist-cont-nonempty}. +@end defun + +@comment ------------------------------------------------------------ + +@defun c-lineup-topmost-intro-cont +@findex lineup-topmost-intro-cont (c-) +Line up declaration continuation lines zero or one indentation +step@footnote{This function is mainly provided to mimic the behavior of +CC Mode 5.28 and earlier where this case wasn't handled consistently so +that those lines could be analyzed as either topmost-intro-cont or +statement-cont. It's used for @code{topmost-intro-cont} by default, but +you might consider using @code{+} instead.}. For lines preceding a +definition, zero is used. For other lines, @code{c-basic-offset} is +added to the indentation. E.g: + +@example +@group +int +neg (int i) @hereFn{c-lineup-topmost-intro-cont} +@{ + return -i; +@} +@end group +@end example + +@noindent +and + +@example +@group +struct +larch @hereFn{c-lineup-topmost-intro-cont} +@{ + double height; +@} + the_larch, @hereFn{c-lineup-topmost-intro-cont} + another_larch; @hereFn{c-lineup-topmost-intro-cont} +@sssTBasicOffset{} +@end group +@end example + +@noindent +and + +@example +@group +struct larch +the_larch, @hereFn{c-lineup-topmost-intro-cont} + another_larch; @hereFn{c-lineup-topmost-intro-cont} +@end group +@end example + +@workswith @code{topmost-intro-cont}. +@end defun + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Custom Line-Up, Other Indentation, Line-Up Functions, Customizing Indentation +@comment node-name, next, previous, up +@section Custom Line-Up Functions +@cindex customization, indentation functions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The most flexible way to customize indentation is by writing custom +line-up functions, and associating them with specific syntactic +symbols (@pxref{c-offsets-alist}). Depending on the effect you want, +it might be better to write a @code{c-special-indent-hook} function +rather than a line-up function (@pxref{Other Indentation}). + +@ccmode{} comes with an extensive set of predefined line-up functions, +not all of which are used by the default styles. So there's a good +chance the function you want already exists. @xref{Line-Up +Functions}, for a list of them. If you write your own line-up +function, it's probably a good idea to start working from one of these +predefined functions, which can be found in the file +@file{cc-align.el}. If you have written a line-up function that you +think is generally useful, you're very welcome to contribute it; +please contact @email{bug-cc-mode@@gnu.org}. + + Line-up functions are passed a single argument, the syntactic +element (see below). The return value is a @code{c-offsets-alist} +offset specification: for example, an integer, a symbol such as +@code{+}, a vector, @code{nil}@footnote{Returning @code{nil} is useful +when the offset specification for a syntactic element is a list +containing the line-up function (@pxref{c-offsets-alist}).}, or even +another line-up function. Full details of these are in +@ref{c-offsets-alist}. + +Line-up functions must not move point or change the content of the +buffer (except temporarily). They are however allowed to do +@dfn{hidden buffer changes}, i.e. setting text properties for caching +purposes etc. Buffer undo recording is disabled while they run. + +The syntactic element passed as the parameter to a line-up function is +a cons cell of the form + +@example +(@r{@var{syntactic-symbol}} . @r{@var{anchor-position}}) +@end example + +@noindent +@c FIXME!!! The following sentence might be better omitted, since the +@c information is in the cross reference "Syntactic Analysis". 2005/10/2. +where @var{syntactic-symbol} is the symbol that the function was +called for, and @var{anchor-position} is the anchor position (if any) +for the construct that triggered the syntactic symbol +(@pxref{Syntactic Analysis}). This cons cell is how the syntactic +element of a line used to be represented in @ccmode{} 5.28 and +earlier. Line-up functions are still passed this cons cell, so as to +preserve compatibility with older configurations. In the future, we +may decide to convert to using the full list format---you can prepare +your setup for this by using the access functions +(@code{c-langelem-sym}, etc.) described below. + +@vindex c-syntactic-element +@vindex syntactic-element (c-) +@vindex c-syntactic-context +@vindex syntactic-context (c-) +Some syntactic symbols, e.g. @code{arglist-cont-nonempty}, have more +info in the syntactic element - typically other positions that can be +interesting besides the anchor position. That info can't be accessed +through the passed argument, which is a cons cell. Instead, you can +get this information from the variable @code{c-syntactic-element}, +which is dynamically bound to the complete syntactic element. The +variable @code{c-syntactic-context} might also be useful - it gets +dynamically bound to the complete syntactic context. @xref{Custom +Braces}. + +@ccmode{} provides a few functions to access parts of syntactic +elements in a more abstract way. Besides making the code easier to +read, they also hide the difference between the old cons cell form +used in the line-up function argument and the new list form used in +@code{c-syntactic-element} and everywhere else. The functions are: + +@defun c-langelem-sym langelem +@findex langelem-sym (c-) +Return the syntactic symbol in @var{langelem}. +@end defun + +@defun c-langelem-pos langelem +@findex langelem-pos (c-) +Return the anchor position in @var{langelem}, or nil if there is none. +@end defun + +@defun c-langelem-col langelem &optional preserve-point +@findex langelem-col (c-) +Return the column of the anchor position in @var{langelem}. Also move +the point to that position unless @var{preserve-point} is +non-@code{nil}. +@end defun + +@defun c-langelem-2nd-pos langelem +@findex langelem-2nd-pos (c-) +Return the secondary position in @var{langelem}, or @code{nil} if there +is none. + +Note that the return value of this function is always @code{nil} if +@var{langelem} is in the old cons cell form. Thus this function is +only meaningful when used on syntactic elements taken from +@code{c-syntactic-element} or @code{c-syntactic-context}. +@end defun + +Custom line-up functions can be as simple or as complex as you like, and +any syntactic symbol that appears in @code{c-offsets-alist} can have a +custom line-up function associated with it. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Other Indentation, , Custom Line-Up, Customizing Indentation +@comment node-name, next, previous, up +@section Other Special Indentations +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +To configure macros which you invoke without a terminating @samp{;}, +see @xref{Macros with ;}. + +Here are the remaining odds and ends regarding indentation: + +@defopt c-label-minimum-indentation +@vindex label-minimum-indentation (c-) +In @samp{gnu} style (@pxref{Built-in Styles}), a minimum indentation is +imposed on lines inside code blocks. This minimum indentation is +controlled by this style variable. The default value is 1. + +@findex c-gnu-impose-minimum +@findex gnu-impose-minimum (c-) +It's the function @code{c-gnu-impose-minimum} that enforces this minimum +indentation. It must be present on @code{c-special-indent-hook} to +work. +@end defopt + +@defopt c-special-indent-hook +@vindex special-indent-hook (c-) +This style variable is a standard hook variable that is called after +every line is indented by @ccmode{}. It is called only if +@code{c-syntactic-indentation} is non-@code{nil} (which it is by +default (@pxref{Indentation Engine Basics})). You can put a function +on this hook to do any special indentation or ad hoc line adjustments +your style dictates, such as adding extra indentation to constructors +or destructor declarations in a class definition, etc. Sometimes it +is better to write a custom Line-up Function instead (@pxref{Custom +Line-Up}). + +The indentation engine calls each function on this hook with no +parameters, with point somewhere on the pertinent line, and with the +variable @code{c-syntactic-context} bound to the current syntactic +context (i.e. what you would get by typing @kbd{C-c C-s} on the source +line. @xref{Custom Braces}.). Note that you should not change +@code{c-syntactic-context} or point or mark inside a +@code{c-special-indent-hook} function; thus you'll probably want to +wrap your function in a @code{save-excursion}@footnote{The numerical +value returned by @code{point} will change if you change the +indentation of the line within a @code{save-excursion} form, but point +itself will still be over the same piece of text.}. + +Setting @code{c-special-indent-hook} in style definitions is handled +slightly differently from other variables---A style can only add +functions to this hook, not remove them. @xref{Style Variables}. +@end defopt + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Custom Macros, Odds and Ends, Customizing Indentation, Top +@comment node-name, next, previous, up +@chapter Customizing Macros +@cindex macros +@cindex preprocessor directives +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Preprocessor macros in C, C++, and Objective C (introduced by +@code{#define}) have a syntax different from the main language---for +example, a macro declaration is not terminated by a semicolon, and if +it is more than a line long, line breaks in it must be escaped with +backslashes. @ccmode{} has some commands to manipulate these, see +@ref{Macro Backslashes}. + +Normally, the lines in a multi-line macro are indented relative to +each other as though they were code. You can suppress this behavior +by setting the following user option: + +@defopt c-syntactic-indentation-in-macros +@vindex syntactic-indentation-in-macros (c-) +Enable syntactic analysis inside macros, which is the default. If this +is @code{nil}, all lines inside macro definitions are analyzed as +@code{cpp-macro-cont}. +@end defopt + +Because a macro can expand into anything at all, near where one is +invoked @ccmode{} can only indent and fontify code heuristically. +Sometimes it gets it wrong. Usually you should try to design your +macros so that they ''look like ordinary code'' when you invoke them. +However, one situation is so common that @ccmode{} handles it +specially: that is when certain macros needn't (or mustn't) be +followed by a @samp{;}. You need to configure @ccmode{} to handle +these macros properly, see @ref{Macros with ;}. + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@menu +* Macro Backslashes:: +* Macros with ;:: +@end menu + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Macro Backslashes, Macros with ;, Custom Macros, Custom Macros +@comment node-name, next, previous, up +@section Customizing Macro Backslashes +@cindex #define +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@ccmode{} provides some tools to help keep the line continuation +backslashes in macros neat and tidy. Their precise action is +customized with these variables: + +@defopt c-backslash-column +@vindex backslash-column (c-) +@defoptx c-backslash-max-column +@vindex backslash-max-column (c-) +These variables control the alignment columns for line continuation +backslashes in multiline macros. They are used by the functions that +automatically insert or align such backslashes, +e.g. @code{c-backslash-region} and @code{c-context-line-break}. + +@code{c-backslash-column} specifies the minimum column for the +backslashes. If any line in the macro goes past this column, then the +next tab stop (i.e. next multiple of @code{tab-width}) in that line is +used as the alignment column for all the backslashes, so that they +remain in a single column. However, if any lines go past +@code{c-backslash-max-column} then the backslashes in the rest of the +macro will be kept at that column, so that the lines which are too +long ``stick out'' instead. + +Don't ever set these variables to @code{nil}. If you want to disable +the automatic alignment of backslashes, use +@code{c-auto-align-backslashes}. +@end defopt + +@defopt c-auto-align-backslashes +@vindex auto-align-backslashes (c-) +Align automatically inserted line continuation backslashes if +non-@code{nil}. When line continuation backslashes are inserted +automatically for line breaks in multiline macros, e.g. by +@code{c-context-line-break}, they are aligned with the other +backslashes in the same macro if this flag is set. + +If @code{c-auto-align-backslashes} is @code{nil}, automatically +inserted backslashes are preceded by a single space, and backslashes +get aligned only when you explicitly invoke the command +@code{c-backslash-region} (@kbd{C-c C-\}). +@end defopt + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Macros with ;, , Macro Backslashes, Custom Macros +@comment node-name, next, previous, up +@section Macros with semicolons +@cindex macros with semicolons +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +Macros which needn't (or mustn't) be followed by a semicolon when you +invoke them, @dfn{macros with semicolons}, are very common. These can +cause @ccmode{} to parse the next line wrongly as a +@code{statement-cont} (@pxref{Function Symbols}) and thus mis-indent +it. + +You can prevent this by specifying which macros have semicolons. It +doesn't matter whether or not such a macro has a parameter list: + +@defopt c-macro-names-with-semicolon +@vindex macro-names-with-semicolon (c-) +This buffer-local variable specifies which macros have semicolons. +After setting its value, you need to call +@code{c-make-macro-with-semi-re} for it to take effect. It should be +set to one of these values: + +@table @asis +@item nil +There are no macros with semicolons. +@item a list of strings +Each string is the name of a macro with a semicolon. Only valid +@code{#define} names are allowed here. For example, to set the +default value, you could write the following into your @file{.emacs}: + +@example +(setq c-macro-names-with-semicolon + '("Q_OBJECT" "Q_PROPERTY" "Q_DECLARE" "Q_ENUMS")) +@end example + +@item a regular expression +This matches each symbol which is a macro with a semicolon. It must +not match any string which isn't a valid @code{#define} name. For +example: + +@example +(setq c-macro-names-with-semicolon + "\\<\\(CLEAN_UP_AND_RETURN\\|Q_[[:upper:]]+\\)\\>") +@end example +@end table +@end defopt + +@defun c-make-macro-with-semi-re +@findex make-macro-with-semi-re (c-) +Call this (non-interactive) function, which sets internal variables, +each time you change the value of +@code{c-macro-names-with-semicolon}. It takes no arguments, and its +return value has no meaning. This function is called by @ccmode{}'s +initialization code. +@end defun + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Odds and Ends, Sample .emacs File, Custom Macros, Top +@comment node-name, next, previous, up +@chapter Odds and Ends +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +The stuff that didn't fit in anywhere else is documented here. + +@defopt c-require-final-newline +@vindex require-final-newline (c-) +Controls whether a final newline is enforced when the file is saved. +The value is an association list that for each language mode specifies +the value to give to @code{require-final-newline} (@pxref{Saving +Buffers,,, @lispref{}, @lispreftitle{}}) at mode initialization. If a +language isn't present on the association list, CC Mode won't touch +@code{require-final-newline} in buffers for that language. + +The default is to set @code{require-final-newline} to @code{t} in the +languages that mandate that source files should end with newlines. +These are C, C++ and Objective-C. +@end defopt + +@defopt c-echo-syntactic-information-p +@vindex echo-syntactic-information-p (c-) +If non-@code{nil}, the syntactic analysis for the current line is shown +in the echo area when it's indented (unless +@code{c-syntactic-indentation} is @code{nil}). That's useful when +finding out which syntactic symbols to modify to get the indentation you +want. +@end defopt + +@defopt c-report-syntactic-errors +@vindex report-syntactic-errors (c-) +If non-@code{nil}, certain syntactic errors are reported with a ding and +a message, for example when an @code{else} is indented for which there +is no corresponding @code{if}. + +Note however that @ccmode{} doesn't make any special effort to check for +syntactic errors; that's the job of the compiler. The reason it can +report cases like the one above is that it can't find the correct +anchoring position to indent the line in that case. +@end defopt + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Sample .emacs File, Performance Issues, Odds and Ends, Top +@comment node-name, next, previous, up +@appendix Sample .emacs File +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Here's a sample .emacs file fragment that might help you along the way. +Just copy this region and paste it into your .emacs file. You might want +to change some of the actual values. + +@verbatim +;; Make a non-standard key binding. We can put this in +;; c-mode-base-map because c-mode-map, c++-mode-map, and so on, +;; inherit from it. +(defun my-c-initialization-hook () + (define-key c-mode-base-map "\C-m" 'c-context-line-break)) +(add-hook 'c-initialization-hook 'my-c-initialization-hook) + +;; offset customizations not in my-c-style +;; This will take precedence over any setting of the syntactic symbol +;; made by a style. +(setq c-offsets-alist '((member-init-intro . ++))) + +;; Create my personal style. +(defconst my-c-style + '((c-tab-always-indent . t) + (c-comment-only-line-offset . 4) + (c-hanging-braces-alist . ((substatement-open after) + (brace-list-open))) + (c-hanging-colons-alist . ((member-init-intro before) + (inher-intro) + (case-label after) + (label after) + (access-label after))) + (c-cleanup-list . (scope-operator + empty-defun-braces + defun-close-semi)) + (c-offsets-alist . ((arglist-close . c-lineup-arglist) + (substatement-open . 0) + (case-label . 4) + (block-open . 0) + (knr-argdecl-intro . -))) + (c-echo-syntactic-information-p . t)) + "My C Programming Style") +(c-add-style "PERSONAL" my-c-style) + +;; Customizations for all modes in CC Mode. +(defun my-c-mode-common-hook () + ;; set my personal style for the current buffer + (c-set-style "PERSONAL") + ;; other customizations + (setq tab-width 8 + ;; this will make sure spaces are used instead of tabs + indent-tabs-mode nil) + ;; we like auto-newline, but not hungry-delete + (c-toggle-auto-newline 1)) +(add-hook 'c-mode-common-hook 'my-c-mode-common-hook) +@end verbatim + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Performance Issues, Limitations and Known Bugs, Sample .emacs File, Top +@comment node-name, next, previous, up +@chapter Performance Issues +@cindex performance +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@comment FIXME: (ACM, 2003/5/24). Check whether AWK needs mentioning here. + +C and its derivative languages are highly complex creatures. Often, +ambiguous code situations arise that require @ccmode{} to scan large +portions of the buffer to determine syntactic context. Such +pathological code can cause @ccmode{} to perform fairly badly. This +section gives some insight in how @ccmode{} operates, how that interacts +with some coding styles, and what you can use to improve performance. + +The overall goal is that @ccmode{} shouldn't be overly slow (i.e. take +more than a fraction of a second) in any interactive operation. +I.e. it's tuned to limit the maximum response time in single operations, +which is sometimes at the expense of batch-like operations like +reindenting whole blocks. If you find that @ccmode{} gradually gets +slower and slower in certain situations, perhaps as the file grows in +size or as the macro or comment you're editing gets bigger, then chances +are that something isn't working right. You should consider reporting +it, unless it's something that's mentioned in this section. + +Because @ccmode{} has to scan the buffer backwards from the current +insertion point, and because C's syntax is fairly difficult to parse in +the backwards direction, @ccmode{} often tries to find the nearest +position higher up in the buffer from which to begin a forward scan +(it's typically an opening or closing parenthesis of some kind). The +farther this position is from the current insertion point, the slower it +gets. + +@findex beginning-of-defun +In earlier versions of @ccmode{}, we used to recommend putting the +opening brace of a top-level construct@footnote{E.g. a function in C, +or outermost class definition in C++ or Java.} into the leftmost +column. Earlier still, this used to be a rigid Emacs constraint, as +embodied in the @code{beginning-of-defun} function. @ccmode now +caches syntactic information much better, so that the delay caused by +searching for such a brace when it's not in column 0 is minimal, +except perhaps when you've just moved a long way inside the file. + +@findex defun-prompt-regexp +@vindex c-Java-defun-prompt-regexp +@vindex Java-defun-prompt-regexp (c-) +A special note about @code{defun-prompt-regexp} in Java mode: The common +style is to hang the opening braces of functions and classes on the +right side of the line, and that doesn't work well with the Emacs +approach. @ccmode{} comes with a constant +@code{c-Java-defun-prompt-regexp} which tries to define a regular +expression usable for this style, but there are problems with it. In +some cases it can cause @code{beginning-of-defun} to hang@footnote{This +has been observed in Emacs 19.34 and XEmacs 19.15.}. For this reason, +it is not used by default, but if you feel adventurous, you can set +@code{defun-prompt-regexp} to it in your mode hook. In any event, +setting and relying on @code{defun-prompt-regexp} will definitely slow +things down because (X)Emacs will be doing regular expression searches a +lot, so you'll probably be taking a hit either way! + +@ccmode{} maintains a cache of the opening parentheses of the blocks +surrounding the point, and it adapts that cache as the point is moved +around. That means that in bad cases it can take noticeable time to +indent a line in a new surrounding, but after that it gets fast as long +as the point isn't moved far off. The farther the point is moved, the +less useful is the cache. Since editing typically is done in ``chunks'' +rather than on single lines far apart from each other, the cache +typically gives good performance even when the code doesn't fit the +Emacs approach to finding the defun starts. + +@vindex c-enable-xemacs-performance-kludge-p +@vindex enable-xemacs-performance-kludge-p (c-) +XEmacs users can set the variable +@code{c-enable-xemacs-performance-kludge-p} to non-@code{nil}. This +tells @ccmode{} to use XEmacs-specific built-in functions which, in some +circumstances, can locate the top-most opening brace much more quickly than +@code{beginning-of-defun}. Preliminary testing has shown that for +styles where these braces are hung (e.g. most JDK-derived Java styles), +this hack can improve performance of the core syntax parsing routines +from 3 to 60 times. However, for styles which @emph{do} conform to +Emacs' recommended style of putting top-level braces in column zero, +this hack can degrade performance by about as much. Thus this variable +is set to @code{nil} by default, since the Emacs-friendly styles should +be more common (and encouraged!). Note that this variable has no effect +in Emacs since the necessary built-in functions don't exist (in Emacs +22.1 as of this writing in February 2007). + +Text properties are used to speed up skipping over syntactic whitespace, +i.e. comments and preprocessor directives. Indenting a line after a +huge macro definition can be slow the first time, but after that the +text properties are in place and it should be fast (even after you've +edited other parts of the file and then moved back). + +Font locking can be a CPU hog, especially the font locking done on +decoration level 3 which tries to be very accurate. Note that that +level is designed to be used with a font lock support mode that only +fontifies the text that's actually shown, i.e. Lazy Lock or Just-in-time +Lock mode, so make sure you use one of them. Fontification of a whole +buffer with some thousand lines can often take over a minute. That is +a known weakness; the idea is that it never should happen. + +The most effective way to speed up font locking is to reduce the +decoration level to 2 by setting @code{font-lock-maximum-decoration} +appropriately. That level is designed to be as pretty as possible +without sacrificing performance. @xref{Font Locking Preliminaries}, for +more info. + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Limitations and Known Bugs, FAQ, Performance Issues, Top +@comment node-name, next, previous, up +@chapter Limitations and Known Bugs +@cindex limitations +@cindex bugs +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@itemize @bullet +@item +@ccmode{} doesn't support trigraphs. (These are character sequences +such as @samp{??(}, which represents @samp{[}. They date from a time +when some character sets didn't have all the characters that C needs, +and are now utterly obsolete.) + +@item +There is no way to apply auto newline settings (@pxref{Auto-newlines}) +on already typed lines. That's only a feature to ease interactive +editing. + +To generalize this issue a bit: @ccmode{} is not intended to be used as +a reformatter for old code in some more or less batch-like way. With +the exception of some functions like @code{c-indent-region}, it's only +geared to be used interactively to edit new code. There's currently no +intention to change this goal. + +@c WARNING!!!! +@c If you change the way the following reference to GNU indent gets +@c compiled into the HTML version of the manual, make sure that +@c 2www.gnu.org.sh still strips out the broken pointer, amending the +@c script if necessary. +If you want to reformat old code, you're probably better off using some +other tool instead, e.g. @ref{Top, , GNU indent, indent, The `indent' +Manual}, which has more powerful reformatting capabilities than +@ccmode{}. + +@item +The support for C++ templates (in angle brackets) is not yet complete. +When a non-nested template is used in a declaration, @ccmode{} indents +it and font-locks it OK. Templates used in expressions, and nested +templates do not fare so well. Sometimes a workaround is to refontify +the expression after typing the closing @samp{>}. + +@item +In a @dfn{k&r region} (the part of an old-fashioned C function +declaration which specifies the types of its parameters, coming +between the parameter list and the opening brace), there should be at +most 20 top-level parenthesis and bracket pairs. This limit has been +imposed for performance reasons. If it is violated, the source file +might be incorrectly indented or fontified. + +@item +On loading @ccmode{}, sometimes this error message appears: + +@example +File mode specification error: (void-variable c-font-lock-keywords-3) +@end example + +This is due to a bug in the function @code{eval-after-load} in some +versions of (X)Emacs. It can manifest itself when there is a symbolic +link in the path of the directory which contains (X)Emacs. As a +workaround, put the following into your @file{.emacs} file, fairly +early on: + +@example +(defun my-load-cc-fonts () + (require "cc-fonts")) +(add-hook 'c-initialization-hook 'my-load-cc-fonts) +@end example +@end itemize + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node FAQ, Updating CC Mode, Limitations and Known Bugs, Top +@comment node-name, next, previous, up +@appendix Frequently Asked Questions +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@itemize @bullet +@item +@emph{How can I change the indent level from 4 spaces to 2 spaces?} + +Set the variable @code{c-basic-offset}. @xref{Getting Started}. + +@item +@kindex RET +@kindex C-j +@emph{Why doesn't the @kbd{RET} key indent the new line?} + +Emacs' convention is that @kbd{RET} just adds a newline, and that +@kbd{C-j} adds a newline and indents it. You can make @kbd{RET} do this +too by adding this to your @code{c-initialization-hook}: + +@example +(define-key c-mode-base-map "\C-m" 'c-context-line-break) +@end example + +@xref{Getting Started}. This is a very common question. If you want +this to be the default behavior, don't lobby us, lobby RMS! @t{:-)} + +@item +@emph{How do I stop my code jumping all over the place when I type?} + +Deactivate ``electric minor mode'' with @kbd{C-c C-l}. @xref{Getting +Started}. + +@item +@kindex C-x h +@kindex C-M-\ +@emph{How do I reindent the whole file?} + +Visit the file and hit @kbd{C-x h} to mark the whole buffer. Then hit +@kbd{C-M-\}. @xref{Indentation Commands}. + +@item +@kindex C-M-q +@kindex C-M-u +@emph{How do I reindent the current block?} + +First move to the brace which opens the block with @kbd{C-M-u}, then +reindent that expression with @kbd{C-M-q}. @xref{Indentation +Commands}. + +@item +@emph{I put @code{(c-set-offset 'substatement-open 0)} in my +@file{.emacs} file but I get an error saying that @code{c-set-offset}'s +function definition is void. What's wrong?} + +This means that @ccmode{} hasn't yet been loaded into your Emacs +session by the time the @code{c-set-offset} call is reached, most +likely because @ccmode{} is being autoloaded. Instead of putting the +@code{c-set-offset} line in your top-level @file{.emacs} file, put it +in your @code{c-initialization-hook} (@pxref{CC Hooks}), or simply +modify @code{c-offsets-alist} directly: + +@example +(setq c-offsets-alist '((substatement-open . 0))) +@end example + +@item +@cindex open paren in column zero +@emph{I have an open paren character at column zero inside a comment or +multiline string literal, and it causes the fontification and/or +indentation to go haywire. What gives?} + +It's due to the ad-hoc rule in (X)Emacs that such open parens always +start defuns (which translates to functions, classes, namespaces or any +other top-level block constructs in the @ccmode{} languages). +@ifset XEMACS +@xref{Defuns,,, xemacs, XEmacs User's Manual}, for details. +@end ifset +@ifclear XEMACS +@xref{Left Margin Paren,,, emacs, GNU Emacs Manual}, for details +(@xref{Defuns,,, emacs, GNU Emacs Manual}, in the Emacs 20 manual). +@end ifclear + +This heuristic is built into the core syntax analysis routines in +(X)Emacs, so it's not really a @ccmode{} issue. However, in Emacs +21.1 it became possible to turn it off@footnote{Using the variable +@code{open-paren-in-column-0-is-defun-start}.} and @ccmode{} does so +there since it's got its own system to keep track of blocks. + +@end itemize + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Updating CC Mode, Mailing Lists and Bug Reports, FAQ, Top +@comment node-name, next, previous, up +@appendix Getting the Latest CC Mode Release +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@ccmode{} has been standard with all versions of Emacs since 19.34 and +of XEmacs since 19.16. + +@cindex web site +Due to release schedule skew, it is likely that all of these Emacsen +have old versions of @ccmode{} and so should be upgraded. Access to the +@ccmode{} source code, as well as more detailed information on Emacsen +compatibility, etc. are all available on the web site: + +@quotation +@uref{http://cc-mode.sourceforge.net/} +@end quotation + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Mailing Lists and Bug Reports, Command and Function Index, Updating CC Mode, Top +@comment node-name, next, previous, up +@appendix Mailing Lists and Submitting Bug Reports +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@kindex C-c C-b +@findex c-submit-bug-report +@findex submit-bug-report (c-) +To report bugs, use the @kbd{C-c C-b} (bound to +@code{c-submit-bug-report}) command. This provides vital information +we need to reproduce your problem. Make sure you include a concise, +but complete code example. Please try to boil your example down to +just the essential code needed to reproduce the problem, and include +an exact recipe of steps needed to expose the bug. Be especially sure +to include any code that appears @emph{before} your bug example, if +you think it might affect our ability to reproduce it. + +Please try to produce the problem in an Emacs instance without any +customizations loaded (i.e. start it with the @samp{-q --no-site-file} +arguments). If it works correctly there, the problem might be caused +by faulty customizations in either your own or your site +configuration. In that case, we'd appreciate it if you isolate the +Emacs Lisp code that triggers the bug and include it in your report. + +@cindex bug report mailing list +Bug reports should be sent to @email{bug-cc-mode@@gnu.org}. You can +also send other questions and suggestions (kudos? @t{;-)} to that +address. It's a mailing list which you can join or browse an archive +of; see the web site at @uref{http://cc-mode.sourceforge.net/} for +further details. + +@cindex announcement mailing list +If you want to get announcements of new @ccmode{} releases, send the +word @emph{subscribe} in the body of a message to +@email{cc-mode-announce-request@@lists.sourceforge.net}. It's possible +to subscribe from the web site too. Announcements will also be posted +to the Usenet newsgroups @code{gnu.emacs.sources}, @code{comp.emacs}, +@code{comp.emacs.xemacs}, @code{comp.lang.c}, @code{comp.lang.c++}, +@code{comp.lang.objective-c}, @code{comp.lang.java.softwaretools}, +@code{comp.lang.idl}, and @code{comp.lang.awk}. +@c There is no newsgroup for Pike. :-( + +@c Removed the tentative node "Mode Initialization" from here, 2005/8/27. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Command and Function Index, Variable Index, Mailing Lists and Bug Reports, Top +@comment node-name, next, previous, up +@unnumbered Command and Function Index +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Since most @ccmode{} commands are prepended with the string +@samp{c-}, each appears under its @code{c-@var{thing}} name and its +@code{@var{thing} (c-)} name. +@iftex +@sp 2 +@end iftex +@printindex fn + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Variable Index, Concept and Key Index, Command and Function Index, Top +@comment node-name, next, previous, up +@unnumbered Variable Index +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Since most @ccmode{} variables are prepended with the string +@samp{c-}, each appears under its @code{c-@var{thing}} name and its +@code{@var{thing} (c-)} name. +@iftex +@sp 2 +@end iftex +@printindex vr + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@node Concept and Key Index, , Variable Index, Top +@comment node-name, next, previous, up +@unnumbered Concept and Key Index +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@printindex cp + + +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +@comment Epilogue. +@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +@iftex +@page +@summarycontents +@contents +@end iftex + +@bye diff --git a/site-lisp/cc-mode/5.32.3/cc-styles.el b/site-lisp/cc-mode/5.32.3/cc-styles.el new file mode 100644 index 0000000..8efba83 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-styles.el @@ -0,0 +1,674 @@ +;;; cc-styles.el --- support for styles in CC Mode + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2004- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 22-Apr-1997 (split from cc-mode.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-vars) +(cc-require 'cc-align) +;; cc-align is only indirectly required: Styles added with +;; `c-add-style' often contains references to functions defined there. + +;; Silence the compiler. +(cc-bytecomp-defvar adaptive-fill-first-line-regexp) ; Emacs +(cc-bytecomp-obsolete-fun make-local-hook) ; Marked obsolete in Emacs 21.1. + ; Allegedly still required by + ; XEmacs 21.4.n (2011-08). + + +(defvar c-style-alist + '(("gnu" + (c-basic-offset . 2) + (c-comment-only-line-offset . (0 . 0)) + (c-hanging-braces-alist . ((substatement-open before after) + (arglist-cont-nonempty))) + (c-offsets-alist . ((statement-block-intro . +) + (knr-argdecl-intro . 5) + (substatement-open . +) + (substatement-label . 0) + (label . 0) + (statement-case-open . +) + (statement-cont . +) + (arglist-intro . c-lineup-arglist-intro-after-paren) + (arglist-close . c-lineup-arglist) + (inline-open . 0) + (brace-list-open . +) + (topmost-intro-cont + . (first c-lineup-topmost-intro-cont + c-lineup-gnu-DEFUN-intro-cont)))) + (c-special-indent-hook . c-gnu-impose-minimum) + (c-block-comment-prefix . "")) + + ("k&r" + (c-basic-offset . 5) + (c-comment-only-line-offset . 0) + (c-offsets-alist . ((statement-block-intro . +) + (knr-argdecl-intro . 0) + (substatement-open . 0) + (substatement-label . 0) + (label . 0) + (statement-cont . +)))) + + ("bsd" + (c-basic-offset . 8) + (c-comment-only-line-offset . 0) + (c-offsets-alist . ((statement-block-intro . +) + (knr-argdecl-intro . +) + (substatement-open . 0) + (substatement-label . 0) + (label . 0) + (statement-cont . +) + (inline-open . 0) + (inexpr-class . 0)))) + + ("stroustrup" + (c-basic-offset . 4) + (c-comment-only-line-offset . 0) + (c-offsets-alist . ((statement-block-intro . +) + (substatement-open . 0) + (substatement-label . 0) + (label . 0) + (statement-cont . +)))) + + ("whitesmith" + (c-basic-offset . 4) + (c-comment-only-line-offset . 0) + ;; It's obvious that the CC Mode way of choosing anchor positions + ;; doesn't fit this style at all. :P + (c-offsets-alist . ((defun-open . +) + (defun-close . c-lineup-whitesmith-in-block) + (defun-block-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (class-open . +) + (class-close . +) + (inline-open . +) + (inline-close . c-lineup-whitesmith-in-block) + (knr-argdecl-intro . +) + (block-open . 0) ; Get indentation from `statement' instead. + (block-close . c-lineup-whitesmith-in-block) + (brace-list-open . +) + (brace-list-close . c-lineup-whitesmith-in-block) + (brace-list-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (brace-list-entry . (add c-lineup-after-whitesmith-blocks + c-indent-multi-line-block)) + (brace-entry-open . (add c-lineup-after-whitesmith-blocks + c-indent-multi-line-block)) + (statement . (add c-lineup-after-whitesmith-blocks + c-indent-multi-line-block)) + (statement-block-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (substatement-open . +) + (substatement-label . +) + (label . 0) + (arglist-intro . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (arglist-cont . (add c-lineup-after-whitesmith-blocks + c-indent-multi-line-block)) + (arglist-cont-nonempty . (add c-lineup-whitesmith-in-block + c-indent-multi-line-block)) + (arglist-close . c-lineup-whitesmith-in-block) + (inclass . c-lineup-whitesmith-in-block) + (extern-lang-open . +) + (namespace-open . +) + (module-open . +) + (composition-open . +) + (extern-lang-close . +) + (namespace-close . +) + (module-close . +) + (composition-close . +) + (inextern-lang . c-lineup-whitesmith-in-block) + (innamespace . c-lineup-whitesmith-in-block) + (inmodule . c-lineup-whitesmith-in-block) + (incomposition . c-lineup-whitesmith-in-block) + (inexpr-class . 0)))) + + ("ellemtel" + (c-basic-offset . 3) + (c-comment-only-line-offset . 0) + (c-hanging-braces-alist . ((substatement-open before after) + (arglist-cont-nonempty))) + (c-offsets-alist . ((topmost-intro . 0) + (substatement . +) + (substatement-open . 0) + (case-label . +) + (access-label . -) + (inclass . +) + (inline-open . 0)))) + ("linux" + (c-basic-offset . 8) + (c-comment-only-line-offset . 0) + (c-hanging-braces-alist . ((brace-list-open) + (brace-entry-open) + (substatement-open after) + (block-close . c-snug-do-while) + (arglist-cont-nonempty))) + (c-cleanup-list . (brace-else-brace)) + (c-offsets-alist . ((statement-block-intro . +) + (knr-argdecl-intro . 0) + (substatement-open . 0) + (substatement-label . 0) + (label . 0) + (statement-cont . +)))) + + ("python" + (indent-tabs-mode . t) + (fill-column . 78) + (c-basic-offset . 8) + (c-offsets-alist . ((substatement-open . 0) + (inextern-lang . 0) + (arglist-intro . +) + (knr-argdecl-intro . +))) + (c-hanging-braces-alist . ((brace-list-open) + (brace-list-intro) + (brace-list-close) + (brace-entry-open) + (substatement-open after) + (block-close . c-snug-do-while) + (arglist-cont-nonempty))) + (c-block-comment-prefix . "")) + + ("java" + (c-basic-offset . 4) + (c-comment-only-line-offset . (0 . 0)) + ;; the following preserves Javadoc starter lines + (c-offsets-alist . ((inline-open . 0) + (topmost-intro-cont . +) + (statement-block-intro . +) + (knr-argdecl-intro . 5) + (substatement-open . +) + (substatement-label . +) + (label . +) + (statement-case-open . +) + (statement-cont . +) + (arglist-intro . c-lineup-arglist-intro-after-paren) + (arglist-close . c-lineup-arglist) + (access-label . 0) + (inher-cont . c-lineup-java-inher) + (func-decl-cont . c-lineup-java-throws)))) + + ;; awk style exists primarily for auto-newline settings. Otherwise it's + ;; pretty much like k&r. + ("awk" + (c-basic-offset . 4) + (c-comment-only-line-offset . 0) + (c-hanging-braces-alist . ((defun-open after) + (defun-close . c-snug-1line-defun-close) + (substatement-open after) + (block-close . c-snug-do-while) + (arglist-cont-nonempty))) + (c-hanging-semi&comma-criteria . nil) + (c-cleanup-list . nil) ; You might want one-liner-defun here. + (c-offsets-alist . ((statement-block-intro . +) + (substatement-open . 0) + (statement-cont . +)))) + + ) + "Styles of indentation. +Elements of this alist are of the form: + + (STYLE-STRING [BASE-STYLE] (VARIABLE . VALUE) [(VARIABLE . VALUE) ...]) + +where STYLE-STRING is a short descriptive string used to select a +style, VARIABLE is any Emacs variable, and VALUE is the intended value +for that variable when using the selected style. + +Optional BASE-STYLE if present, is a string and must follow +STYLE-STRING. BASE-STYLE names a style that this style inherits from. +By default, all styles inherit from the \"user\" style, which is +computed at run time. Style loops generate errors. + +Two variables are treated specially. When VARIABLE is +`c-offsets-alist', the VALUE is a list containing elements of the +form: + + (SYNTACTIC-SYMBOL . OFFSET) + +as described in `c-offsets-alist'. These are passed directly to +`c-set-offset' so there is no need to set every syntactic symbol in +your style, only those that are different from the default. + +When VARIABLE is `c-special-indent-hook', its VALUE is added to +`c-special-indent-hook' using `add-hook'. If VALUE is a list, each +element of the list is added with `add-hook'. + +Do not change this variable directly. Use the function `c-add-style' +to add new styles or modify existing styles (it is not a good idea to +modify existing styles -- you should create a new style that inherits +the existing style).") + + +;; Functions that manipulate styles +(defun c-set-style-1 (conscell dont-override) + ;; Set the style for one variable + (let ((attr (car conscell)) + (val (cdr conscell))) + (cond + ;; first special variable + ((eq attr 'c-offsets-alist) + (let ((offsets (cond ((eq dont-override t) + c-offsets-alist) + (dont-override + (default-value 'c-offsets-alist))))) + (mapcar (lambda (langentry) + (let ((langelem (car langentry)) + (offset (cdr langentry))) + (unless (assq langelem offsets) + (c-set-offset langelem offset)))) + val))) + ;; second special variable + ((eq attr 'c-special-indent-hook) + ;; Maybe we should ignore dont-override here and always add new + ;; hooks? + (unless (cond ((eq dont-override t) + c-special-indent-hook) + (dont-override + (default-value 'c-special-indent-hook))) + (if (listp val) + (mapcar (lambda (func) + (add-hook 'c-special-indent-hook func t t)) + val) + (add-hook 'c-special-indent-hook val t t)))) + ;; all other variables + (t (when (or (not dont-override) + (not (memq attr c-style-variables)) + (eq (if (eq dont-override t) + (symbol-value attr) + (default-value attr)) + 'set-from-style)) + (set attr val) + ;; Must update a number of other variables if + ;; c-comment-prefix-regexp is set. + (if (eq attr 'c-comment-prefix-regexp) + (c-setup-paragraph-variables))))))) + +(defun c-get-style-variables (style basestyles) + ;; Return all variables in a style by resolving inheritances. + (if (not style) + (copy-alist c-fallback-style) + (let ((vars (cdr (or (assoc (downcase style) c-style-alist) + (assoc (upcase style) c-style-alist) + (assoc style c-style-alist) + (progn + (c-benign-error "Undefined style: %s" style) + nil))))) + (let ((base (and (stringp (car-safe vars)) + (prog1 + (downcase (car vars)) + (setq vars (cdr vars)))))) + (if (memq base basestyles) + (c-benign-error "Style loop detected: %s in %s" base basestyles) + (nconc (c-get-style-variables base (cons base basestyles)) + (copy-alist vars))))))) + +(defvar c-set-style-history nil) + +;;;###autoload +(defun c-set-style (stylename &optional dont-override) + "Set the current buffer to use the style STYLENAME. +STYLENAME, a string, must be an existing CC Mode style - These are contained +in the variable `c-style-alist'. + +The variable `c-indentation-style' will get set to STYLENAME. + +\"Setting the style\" is done by setting CC Mode's \"style variables\" to the +values indicated by the pertinent entry in `c-style-alist'. Other variables +might get set too. + +If DONT-OVERRIDE is neither nil nor t, style variables whose default values +have been set (more precisely, whose default values are not the symbol +`set-from-style') will not be changed. This avoids overriding global settings +done in ~/.emacs. It is useful to call c-set-style from a mode hook in this +way. + +If DONT-OVERRIDE is t, style variables that already have values (i.e., whose +values are not the symbol `set-from-style') will not be overridden. CC Mode +calls c-set-style internally in this way whilst initializing a buffer; if +cc-set-style is called like this from anywhere else, it will usually behave as +a null operation." + (interactive + (list (let ((completion-ignore-case t) + (prompt (format "Which %s indentation style? " + mode-name))) + (completing-read prompt c-style-alist nil t nil + 'c-set-style-history + c-indentation-style)))) + (or c-buffer-is-cc-mode + (error "Buffer %s is not a CC Mode buffer (c-set-style)" (buffer-name))) + (or (stringp stylename) + (error "Argument to c-set-style was not a string")) + (c-initialize-builtin-style) + (let ((vars (c-get-style-variables stylename nil))) + (unless dont-override + ;; Since we always add to c-special-indent-hook we must reset it + ;; first, or else the hooks from the preceding style will + ;; remain. This is not necessary for c-offsets-alist, since + ;; c-get-style-variables contains every valid offset type in the + ;; fallback entry. + (setq c-special-indent-hook + (default-value 'c-special-indent-hook))) + (mapc (lambda (elem) + (c-set-style-1 elem dont-override)) + ;; Need to go through the variables backwards when we + ;; don't override any settings. + (if (eq dont-override t) (nreverse vars) vars))) + (setq c-indentation-style stylename) + (c-keep-region-active)) + +;;;###autoload +(defun c-add-style (style description &optional set-p) + "Adds a style to `c-style-alist', or updates an existing one. +STYLE is a string identifying the style to add or update. DESCRIPTION +is an association list describing the style and must be of the form: + + ([BASESTYLE] (VARIABLE . VALUE) [(VARIABLE . VALUE) ...]) + +See the variable `c-style-alist' for the semantics of BASESTYLE, +VARIABLE and VALUE. This function also sets the current style to +STYLE using `c-set-style' if the optional SET-P flag is non-nil." + (interactive + (let ((stylename (completing-read "Style to add: " c-style-alist + nil nil nil 'c-set-style-history)) + (descr (eval-minibuffer "Style description: "))) + (list stylename descr + (y-or-n-p "Set the style too? ")))) + (setq style (downcase style)) + (let ((s (assoc style c-style-alist))) + (if s + (setcdr s (copy-alist description)) ; replace + (setq c-style-alist (cons (cons style description) c-style-alist)))) + (and set-p (c-set-style style))) + + +(defvar c-read-offset-history nil) + +(defun c-read-offset (langelem) + ;; read new offset value for LANGELEM from minibuffer. return a + ;; valid value only + (let* ((oldoff (cdr-safe (or (assq langelem c-offsets-alist) + (assq langelem (get 'c-offsets-alist + 'c-stylevar-fallback))))) + (symname (symbol-name langelem)) + (defstr (format "(default %s): " oldoff)) + (errmsg (concat "Offset must be int, func, var, vector, list, " + "or [+,-,++,--,*,/] " + defstr)) + (prompt (concat symname " offset " defstr)) + (keymap (make-sparse-keymap)) + (minibuffer-completion-table obarray) + (minibuffer-completion-predicate 'fboundp) + offset input) + ;; In principle completing-read is used here, but SPC is unbound + ;; to make it less annoying to enter lists. + (set-keymap-parent keymap minibuffer-local-completion-map) + (define-key keymap " " 'self-insert-command) + (while (not offset) + (setq input (read-from-minibuffer prompt nil keymap t + 'c-read-offset-history + (format "%s" oldoff))) + (if (c-valid-offset input) + (setq offset input) + ;; error, but don't signal one, keep trying + ;; to read an input value + (ding) + (setq prompt errmsg))) + offset)) + +;;;###autoload +(defun c-set-offset (symbol offset &optional ignored) + "Change the value of a syntactic element symbol in `c-offsets-alist'. +SYMBOL is the syntactic element symbol to change and OFFSET is the new +offset for that syntactic element. The optional argument is not used +and exists only for compatibility reasons." + (interactive + (let* ((langelem + (intern (completing-read + (concat "Syntactic symbol to change" + (if current-prefix-arg " or add" "") + ": ") + (mapcar + #'(lambda (langelem) + (cons (format "%s" (car langelem)) nil)) + (get 'c-offsets-alist 'c-stylevar-fallback)) + nil (not current-prefix-arg) + ;; initial contents tries to be the last element + ;; on the syntactic analysis list for the current + ;; line + (and c-buffer-is-cc-mode + (c-save-buffer-state + ((syntax (c-guess-basic-syntax)) + (len (length syntax)) + (ic (format "%s" (car (nth (1- len) syntax))))) + (cons ic 0))) + ))) + (offset (c-read-offset langelem))) + (list langelem offset current-prefix-arg))) + ;; sanity check offset + (if (c-valid-offset offset) + (let ((entry (assq symbol c-offsets-alist))) + (if entry + (setcdr entry offset) + (if (assq symbol (get 'c-offsets-alist 'c-stylevar-fallback)) + (setq c-offsets-alist (cons (cons symbol offset) + c-offsets-alist)) + (c-benign-error "%s is not a valid syntactic symbol" symbol)))) + (c-benign-error "Invalid indentation setting for symbol %s: %S" + symbol offset)) + (c-keep-region-active)) + + +(defun c-setup-paragraph-variables () + "Fix things up for paragraph recognition and filling inside comments and +strings by incorporating the values of `c-comment-prefix-regexp', +`sentence-end', `paragraph-start' and `paragraph-separate' in the relevant +variables." + + (interactive) + (or c-buffer-is-cc-mode + (error "Buffer %s is not a CC Mode buffer (c-setup-paragraph-variables)" + (buffer-name))) + ;; Set up the values for use in comments. + (setq c-current-comment-prefix + (if (listp c-comment-prefix-regexp) + (cdr-safe (or (assoc major-mode c-comment-prefix-regexp) + (assoc 'other c-comment-prefix-regexp))) + c-comment-prefix-regexp)) + + (let* ((empty-is-prefix (string-match c-current-comment-prefix "")) + (nonws-comment-line-prefix + (concat "\\(" c-current-comment-prefix "\\)[ \t]*")) + (comment-line-prefix (concat "[ \t]*" nonws-comment-line-prefix)) + (blank-or-comment-line-prefix + (concat "[ \t]*" + (if empty-is-prefix "" "\\(") + nonws-comment-line-prefix + (if empty-is-prefix "" "\\)?")))) + + (setq paragraph-start (concat blank-or-comment-line-prefix + c-paragraph-start + "\\|" + page-delimiter) + paragraph-separate (concat blank-or-comment-line-prefix + c-paragraph-separate + "\\|" + page-delimiter) + paragraph-ignore-fill-prefix t + adaptive-fill-mode t + adaptive-fill-regexp + (concat comment-line-prefix + (if (default-value 'adaptive-fill-regexp) + (concat "\\(" + (default-value 'adaptive-fill-regexp) + "\\)") + ""))) + + (when (boundp 'adaptive-fill-first-line-regexp) + ;; XEmacs adaptive fill mode doesn't have this. + (make-local-variable 'adaptive-fill-first-line-regexp) + (setq adaptive-fill-first-line-regexp + (concat "\\`" comment-line-prefix + ;; Maybe we should incorporate the old value here, + ;; but then we have to do all sorts of kludges to + ;; deal with the \` and \' it probably contains. + "\\'")))) + + ;; Set up the values for use in strings. These are the default + ;; paragraph-start/separate values, enhanced to accept escaped EOLs as + ;; whitespace. Used in c-beginning/end-of-sentence-in-string in cc-cmds. + (setq c-string-par-start + ;;(concat "\\(" (default-value 'paragraph-start) "\\)\\|[ \t]*\\\\$")) + "\f\\|[ \t]*\\\\?$") + (setq c-string-par-separate + ;;(concat "\\(" (default-value 'paragraph-separate) "\\)\\|[ \t]*\\\\$")) + "[ \t\f]*\\\\?$") + (setq c-sentence-end-with-esc-eol + (concat "\\(\\(" (c-default-value-sentence-end) "\\)" + ;; N.B.: "$" would be invalid when not enclosed like "\\($\\)". + "\\|" "[.?!][]\"')}]* ?\\\\\\($\\)[ \t\n]*" + "\\)"))) + + +;; Helper for setting up Filladapt mode. It's not used by CC Mode itself. + +(cc-bytecomp-defvar filladapt-token-table) +(cc-bytecomp-defvar filladapt-token-match-table) +(cc-bytecomp-defvar filladapt-token-conversion-table) + +(defun c-setup-filladapt () + "Convenience function to configure Kyle E. Jones' Filladapt mode for +CC Mode by making sure the proper entries are present on +`filladapt-token-table', `filladapt-token-match-table', and +`filladapt-token-conversion-table'. This is intended to be used on +`c-mode-common-hook' or similar." + ;; This function is intended to be used explicitly by the end user + ;; only. + + ;; The default configuration already handles C++ comments, but we + ;; need to add handling of C block comments. A new filladapt token + ;; `c-comment' is added for that. + (let (p) + (setq p filladapt-token-table) + (while (and p (not (eq (car-safe (cdr-safe (car-safe p))) 'c-comment))) + (setq p (cdr-safe p))) + (if p + (setcar (car p) c-current-comment-prefix) + (setq filladapt-token-table + (append (list (car filladapt-token-table) + (list c-current-comment-prefix 'c-comment)) + (cdr filladapt-token-table))))) + (unless (assq 'c-comment filladapt-token-match-table) + (setq filladapt-token-match-table + (append '((c-comment c-comment)) + filladapt-token-match-table))) + (unless (assq 'c-comment filladapt-token-conversion-table) + (setq filladapt-token-conversion-table + (append '((c-comment . exact)) + filladapt-token-conversion-table)))) + + +(defun c-initialize-builtin-style () + ;; Dynamically append the default value of most variables. This is + ;; crucial because future c-set-style calls will always reset the + ;; variables first to the `cc-mode' style before instituting the new + ;; style. Only do this once! + (unless (get 'c-initialize-builtin-style 'is-run) + (put 'c-initialize-builtin-style 'is-run t) + ;;(c-initialize-cc-mode) + (unless (assoc "user" c-style-alist) + (let ((vars c-style-variables) var val uservars) + (while vars + (setq var (car vars) + val (symbol-value var) + vars (cdr vars)) + (cond ((eq var 'c-offsets-alist) + (or (null val) + (setq uservars (cons (cons 'c-offsets-alist val) + uservars)))) + ((not (eq val 'set-from-style)) + (setq uservars (cons (cons var val) + uservars))))) + (c-add-style "user" uservars))) + (unless (assoc "cc-mode" c-style-alist) + (c-add-style "cc-mode" '("user"))) + (if c-style-variables-are-local-p + (c-make-styles-buffer-local)))) + +(defun c-make-styles-buffer-local (&optional this-buf-only-p) + "Make all CC Mode style variables buffer local. +If `this-buf-only-p' is non-nil, the style variables will be made +buffer local only in the current buffer. Otherwise they'll be made +permanently buffer local in any buffer that changes their values. + +The buffer localness of the style variables are normally controlled +with the variable `c-style-variables-are-local-p', so there's seldom +any reason to call this function directly." + + ;; style variables + (let ((func (if this-buf-only-p + 'make-local-variable + 'make-variable-buffer-local)) + (varsyms (cons 'c-indentation-style (copy-alist c-style-variables)))) + (delq 'c-special-indent-hook varsyms) + (mapc func varsyms) + ;; Hooks must be handled specially + (if this-buf-only-p + (or (memq 'add-hook-local c-emacs-features) + (make-local-hook 'c-special-indent-hook)) + (make-variable-buffer-local 'c-special-indent-hook) + (setq c-style-variables-are-local-p t)) + )) + +(defun cc-choose-style-for-mode (mode default-style) + "Return suitable style for MODE from DEFAULT-STYLE. +DEFAULT-STYLE has the same format as `c-default-style'." + (if (stringp default-style) + default-style + (or (cdr (assq mode default-style)) + (cdr (assq 'other default-style)) + "gnu"))) + + + +(cc-provide 'cc-styles) + +;;; arch-tag: c764f61a-96ba-484a-a68f-101c0e9d5d2c +;;; cc-styles.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-subword.el b/site-lisp/cc-mode/5.32.3/cc-subword.el new file mode 100644 index 0000000..422f4f1 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-subword.el @@ -0,0 +1,326 @@ +;;; cc-subword.el --- Handling capitalized subwords in a nomenclature + +;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +;; Free Software Foundation, Inc. + +;; Author: Masatake YAMATO + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;; This package provides `subword' oriented commands and a minor mode +;; (`c-subword-mode') that substitutes the common word handling +;; functions with them. + +;; In spite of GNU Coding Standards, it is popular to name a symbol by +;; mixing uppercase and lowercase letters, e.g. "GtkWidget", +;; "EmacsFrameClass", "NSGraphicsContext", etc. Here we call these +;; mixed case symbols `nomenclatures'. Also, each capitalized (or +;; completely uppercase) part of a nomenclature is called a `subword'. +;; Here are some examples: + +;; Nomenclature Subwords +;; =========================================================== +;; GtkWindow => "Gtk" and "Window" +;; EmacsFrameClass => "Emacs", "Frame" and "Class" +;; NSGraphicsContext => "NS", "Graphics" and "Context" + +;; The subword oriented commands defined in this package recognize +;; subwords in a nomenclature to move between them and to edit them as +;; words. + +;; In the minor mode, all common key bindings for word oriented +;; commands are overridden by the subword oriented commands: + +;; Key Word oriented command Subword oriented command +;; ============================================================ +;; M-f `forward-word' `c-forward-subword' +;; M-b `backward-word' `c-backward-subword' +;; M-@ `mark-word' `c-mark-subword' +;; M-d `kill-word' `c-kill-subword' +;; M-DEL `backward-kill-word' `c-backward-kill-subword' +;; M-t `transpose-words' `c-transpose-subwords' +;; M-c `capitalize-word' `c-capitalize-subword' +;; M-u `upcase-word' `c-upcase-subword' +;; M-l `downcase-word' `c-downcase-subword' +;; +;; Note: If you have changed the key bindings for the word oriented +;; commands in your .emacs or a similar place, the keys you've changed +;; to are also used for the corresponding subword oriented commands. + +;; To make the mode turn on automatically, put the following code in +;; your .emacs: +;; +;; (add-hook 'c-mode-common-hook +;; (lambda () (c-subword-mode 1))) +;; + +;; Acknowledgment: +;; The regular expressions to detect subwords are mostly based on +;; the old `c-forward-into-nomenclature' originally contributed by +;; Terry_Glanfield dot Southern at rxuk dot xerox dot com. + +;; TODO: ispell-word and subword oriented C-w in isearch. + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) +(cc-require 'cc-cmds) + +;; Don't complain about the `define-minor-mode' form if it isn't defined. +(cc-bytecomp-defvar c-subword-mode) + +;; Autoload directives must be on the top level, so we construct an +;; autoload form instead. +;;;###autoload (autoload 'c-subword-mode "cc-subword" "Mode enabling subword movement and editing keys." t) + +(if (not (fboundp 'define-minor-mode)) + (defun c-subword-mode () + "(Missing) mode enabling subword movement and editing keys. +This mode is not (yet) available in this version of (X)Emacs. Sorry! If +you really want it, please send a request to , +telling us which (X)Emacs version you're using." + (interactive) + (error + "c-subword-mode is not (yet) available in this version of (X)Emacs. Sorry!")) + + (defvar c-subword-mode-map + (let ((map (make-sparse-keymap))) + (substitute-key-definition 'forward-word + 'c-forward-subword + map global-map) + (substitute-key-definition 'backward-word + 'c-backward-subword + map global-map) + (substitute-key-definition 'mark-word + 'c-mark-subword + map global-map) + + (substitute-key-definition 'kill-word + 'c-kill-subword + map global-map) + (substitute-key-definition 'backward-kill-word + 'c-backward-kill-subword + map global-map) + + (substitute-key-definition 'transpose-words + 'c-transpose-subwords + map global-map) + + (substitute-key-definition 'capitalize-word + 'c-capitalize-subword + map global-map) + (substitute-key-definition 'upcase-word + 'c-upcase-subword + map global-map) + (substitute-key-definition 'downcase-word + 'c-downcase-subword + map global-map) + map) + "Keymap used in command `c-subword-mode' minor mode.") + + (define-minor-mode c-subword-mode + "Mode enabling subword movement and editing keys. +In spite of GNU Coding Standards, it is popular to name a symbol by +mixing uppercase and lowercase letters, e.g. \"GtkWidget\", +\"EmacsFrameClass\", \"NSGraphicsContext\", etc. Here we call these +mixed case symbols `nomenclatures'. Also, each capitalized (or +completely uppercase) part of a nomenclature is called a `subword'. +Here are some examples: + + Nomenclature Subwords + =========================================================== + GtkWindow => \"Gtk\" and \"Window\" + EmacsFrameClass => \"Emacs\", \"Frame\" and \"Class\" + NSGraphicsContext => \"NS\", \"Graphics\" and \"Context\" + +The subword oriented commands activated in this minor mode recognize +subwords in a nomenclature to move between subwords and to edit them +as words. + +\\{c-subword-mode-map}" + nil + nil + c-subword-mode-map + (c-update-modeline)) + + ) + +(defun c-forward-subword (&optional arg) + "Do the same as `forward-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `forward-word'." + (interactive "p") + (unless arg (setq arg 1)) + (c-keep-region-active) + (cond + ((< 0 arg) + (dotimes (i arg (point)) + (c-forward-subword-internal))) + ((> 0 arg) + (dotimes (i (- arg) (point)) + (c-backward-subword-internal))) + (t + (point)))) + +(defun c-backward-subword (&optional arg) + "Do the same as `backward-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `backward-word'." + (interactive "p") + (c-forward-subword (- (or arg 1)))) + +(defun c-mark-subword (arg) + "Do the same as `mark-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `mark-word'." + ;; This code is almost copied from `mark-word' in GNU Emacs. + (interactive "p") + (cond ((and (eq last-command this-command) (mark t)) + (set-mark + (save-excursion + (goto-char (mark)) + (c-forward-subword arg) + (point)))) + (t + (push-mark + (save-excursion + (c-forward-subword arg) + (point)) + nil t)))) + +(defun c-kill-subword (arg) + "Do the same as `kill-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `kill-word'." + (interactive "p") + (kill-region (point) (c-forward-subword arg))) + +(defun c-backward-kill-subword (arg) + "Do the same as `backward-kill-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `backward-kill-word'." + (interactive "p") + (c-kill-subword (- arg))) + +(defun c-transpose-subwords (arg) + "Do the same as `transpose-words' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `transpose-words'." + (interactive "*p") + (transpose-subr 'c-forward-subword arg)) + + + +(defun c-downcase-subword (arg) + "Do the same as `downcase-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `downcase-word'." + (interactive "p") + (let ((start (point))) + (downcase-region (point) (c-forward-subword arg)) + (when (< arg 0) + (goto-char start)))) + +(defun c-upcase-subword (arg) + "Do the same as `upcase-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `upcase-word'." + (interactive "p") + (let ((start (point))) + (upcase-region (point) (c-forward-subword arg)) + (when (< arg 0) + (goto-char start)))) + +(defun c-capitalize-subword (arg) + "Do the same as `capitalize-word' but on subwords. +See the command `c-subword-mode' for a description of subwords. +Optional argument ARG is the same as for `capitalize-word'." + (interactive "p") + (let ((count (abs arg)) + (start (point)) + (advance (if (< arg 0) nil t))) + (dotimes (i count) + (if advance + (progn (re-search-forward + (concat "[" c-alpha "]") + nil t) + (goto-char (match-beginning 0))) + (c-backward-subword)) + (let* ((p (point)) + (pp (1+ p)) + (np (c-forward-subword))) + (upcase-region p pp) + (downcase-region pp np) + (goto-char (if advance np p)))) + (unless advance + (goto-char start)))) + + + +;; +;; Internal functions +;; +(defun c-forward-subword-internal () + (if (and + (save-excursion + (let ((case-fold-search nil)) + (re-search-forward + (concat "\\W*\\(\\([" c-upper "]*\\W?\\)[" c-lower c-digit "]*\\)") + nil t))) + (> (match-end 0) (point))) ; So we don't get stuck at a + ; "word-constituent" which isn't c-upper, + ; c-lower or c-digit + (goto-char + (cond + ((< 1 (- (match-end 2) (match-beginning 2))) + (1- (match-end 2))) + (t + (match-end 0)))) + (forward-word 1))) + + +(defun c-backward-subword-internal () + (if (save-excursion + (let ((case-fold-search nil)) + (re-search-backward + (concat + "\\(\\(\\W\\|[" c-lower c-digit "]\\)\\([" c-upper "]+\\W*\\)" + "\\|\\W\\w+\\)") + nil t))) + (goto-char + (cond + ((and (match-end 3) + (< 1 (- (match-end 3) (match-beginning 3))) + (not (eq (point) (match-end 3)))) + (1- (match-end 3))) + (t + (1+ (match-beginning 0))))) + (backward-word 1))) + + +(cc-provide 'cc-subword) + +;; arch-tag: 2be9d294-7f30-4626-95e6-9964bb93c7a3 +;;; cc-subword.el ends here diff --git a/site-lisp/cc-mode/5.32.3/cc-vars.el b/site-lisp/cc-mode/5.32.3/cc-vars.el new file mode 100644 index 0000000..fda63e0 --- /dev/null +++ b/site-lisp/cc-mode/5.32.3/cc-vars.el @@ -0,0 +1,1775 @@ +;;; cc-vars.el --- user customization variables for CC Mode + +;; Copyright (C) 1985, 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, +;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, +;; 2010, 2011, 2012 Free Software Foundation, Inc. + +;; Authors: 2002- Alan Mackenzie +;; 1998- Martin Stjernholm +;; 1992-1999 Barry A. Warsaw +;; 1987 Dave Detlefs and Stewart Clamen +;; 1985 Richard M. Stallman +;; Maintainer: bug-cc-mode@gnu.org +;; Created: 22-Apr-1997 (split from cc-mode.el) +;; Version: See cc-mode.el +;; Keywords: c languages oop + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GNU Emacs 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; see the file COPYING. If not, see +;; . + +;;; Commentary: + +;;; Code: + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-bytecomp" nil t))) + +(cc-require 'cc-defs) + +;; Silence the compiler. +(cc-bytecomp-defun get-char-table) ; XEmacs + +(cc-eval-when-compile + (require 'custom) + (require 'widget)) + +(cc-eval-when-compile + ;; Need the function form of `backquote', which isn't standardized + ;; between Emacsen. It's called `bq-process' in XEmacs, and + ;; `backquote-process' in Emacs. `backquote-process' returns a + ;; slightly more convoluted form, so let `bq-process' be the norm. + (if (fboundp 'backquote-process) + (cc-bytecomp-defmacro bq-process (form) + `(cdr (backquote-process ,form))))) + + +;;; Helpers + +;; This widget exists in newer versions of the Custom library +(or (get 'other 'widget-type) + (define-widget 'other 'sexp + "Matches everything, but doesn't let the user edit the value. +Useful as last item in a `choice' widget." + :tag "Other" + :format "%t%n" + :value 'other)) + +;; The next defun will supersede c-const-symbol. +(eval-and-compile + (defun c-constant-symbol (sym len) + "Create an uneditable symbol for customization buffers. +SYM is the name of the symbol, LEN the length of the field (in +characters) the symbol will be displayed in. LEN must be big +enough. + +This returns a (const ....) structure, suitable for embedding +within a customization type." + (or (symbolp sym) (error "c-constant-symbol: %s is not a symbol" sym)) + (let* ((name (symbol-name sym)) + (l (length name)) + (disp (concat name ":" (make-string (- len l 1) ?\ )))) + `(const + :size ,len + :format ,disp + :value ,sym)))) + +(define-widget 'c-const-symbol 'item + "An uneditable lisp symbol. This is obsolete - +use c-constant-symbol instead." + :value nil + :tag "Symbol" + :format "%t: %v\n%d" + :match (lambda (widget value) (symbolp value)) + :value-to-internal + (lambda (widget value) + (let ((s (if (symbolp value) + (symbol-name value) + value)) + (l (widget-get widget :size))) + (if l + (setq s (concat s (make-string (- l (length s)) ?\ )))) + s)) + :value-to-external + (lambda (widget value) + (if (stringp value) + (intern (progn + (string-match "\\`[^ ]*" value) + (match-string 0 value))) + value))) + +(define-widget 'c-integer-or-nil 'sexp + "An integer or the value nil." + :value nil + :tag "Optional integer" + :match (lambda (widget value) (or (integerp value) (null value)))) + +(define-widget 'c-symbol-list 'sexp + "A single symbol or a list of symbols." + :tag "Symbols separated by spaces" + :validate 'widget-field-validate + :match + (lambda (widget value) + (or (symbolp value) + (catch 'ok + (while (listp value) + (unless (symbolp (car value)) + (throw 'ok nil)) + (setq value (cdr value))) + (null value)))) + :value-to-internal + (lambda (widget value) + (cond ((null value) + "") + ((symbolp value) + (symbol-name value)) + ((consp value) + (mapconcat (lambda (symbol) + (symbol-name symbol)) + value + " ")) + (t + value))) + :value-to-external + (lambda (widget value) + (if (stringp value) + (let (list end) + (while (string-match "\\S +" value end) + (setq list (cons (intern (match-string 0 value)) list) + end (match-end 0))) + (if (and list (not (cdr list))) + (car list) + (nreverse list))) + value))) + +(defvar c-style-variables + '(c-basic-offset c-comment-only-line-offset c-indent-comment-alist + c-indent-comments-syntactically-p c-block-comment-prefix + c-comment-prefix-regexp c-doc-comment-style c-cleanup-list + c-hanging-braces-alist c-hanging-colons-alist + c-hanging-semi&comma-criteria c-backslash-column c-backslash-max-column + c-special-indent-hook c-label-minimum-indentation c-offsets-alist) + "List of the style variables.") + +(defvar c-fallback-style nil) + +(defsubst c-set-stylevar-fallback (name val) + (put name 'c-stylevar-fallback val) + (setq c-fallback-style (cons (cons name val) c-fallback-style))) + +(defmacro defcustom-c-stylevar (name val doc &rest args) + "Define a style variable NAME with VAL and DOC. +More precisely, convert the given `:type FOO', mined out of ARGS, +to an aggregate `:type (radio STYLE (PREAMBLE FOO))', append some +some boilerplate documentation to DOC, arrange for the fallback +value of NAME to be VAL, and call `custom-declare-variable' to +do the rest of the work. + +STYLE stands for the choice where the value is taken from some +style setting. PREAMBLE is optionally prepended to FOO; that is, +if FOO contains :tag or :value, the respective two-element list +component is ignored." + (declare (debug (symbolp form stringp &rest))) + (let* ((expanded-doc (concat doc " + +This is a style variable. Apart from the valid values described +above, it can be set to the symbol `set-from-style'. In that case, +it takes its value from the style system (see `c-default-style' and +`c-style-alist') when a CC Mode buffer is initialized. Otherwise, +the value set here overrides the style system (there is a variable +`c-old-style-variable-behavior' that changes this, though).")) + (typ (eval (c-safe (plist-get args :type)))) + (type (if (consp typ) typ (list typ))) + (head (car type)) + (tail (cdr type)) + (newt (append (unless (c-safe (plist-get tail :tag)) + '(:tag "Override style settings")) + (unless (c-safe (plist-get tail :value)) + `(:value ,val)) + tail)) + (aggregate `'(radio + (const :tag "Use style settings" set-from-style) + ,(cons head newt)))) + `(progn + (c-set-stylevar-fallback ',name ,val) + (custom-declare-variable + ',name ''set-from-style + ,expanded-doc + ,@(plist-put args :type aggregate))))) + +(defun c-valid-offset (offset) + "Return non-nil if OFFSET is a valid offset for a syntactic symbol. +See `c-offsets-alist'." + (or (eq offset '+) + (eq offset '-) + (eq offset '++) + (eq offset '--) + (eq offset '*) + (eq offset '/) + (integerp offset) + (functionp offset) + (and (symbolp offset) (boundp offset)) + (and (vectorp offset) + (= (length offset) 1) + (integerp (elt offset 0))) + (and (consp offset) + (not (eq (car offset) 'quote)) ; Detect misquoted lists. + (progn + (when (memq (car offset) '(first min max add)) + (setq offset (cdr offset))) + (while (and (consp offset) + (c-valid-offset (car offset))) + (setq offset (cdr offset))) + (null offset))))) + + + +;;; User variables + +(defcustom c-strict-syntax-p nil + "*If non-nil, all syntactic symbols must be found in `c-offsets-alist'. +If the syntactic symbol for a particular line does not match a symbol +in the offsets alist, or if no non-nil offset value can be determined +for a symbol, an error is generated, otherwise no error is reported +and the syntactic symbol is ignored. + +This variable is considered obsolete; it doesn't work well with lineup +functions that return nil to support the feature of using lists on +syntactic symbols in `c-offsets-alist'. Please keep it set to nil." + :type 'boolean + :group 'c) + +(defcustom c-echo-syntactic-information-p nil + "*If non-nil, syntactic info is echoed when the line is indented." + :type 'boolean + :group 'c) + +(defcustom c-report-syntactic-errors nil + "*If non-nil, certain syntactic errors are reported with a ding +and a message, for example when an \"else\" is indented for which +there's no corresponding \"if\". + +Note however that CC Mode doesn't make any special effort to check for +syntactic errors; that's the job of the compiler. The reason it can +report cases like the one above is that it can't find the correct +anchoring position to indent the line in that case." + :type 'boolean + :group 'c) + +(defcustom-c-stylevar c-basic-offset 4 + "*Amount of basic offset used by + and - symbols in `c-offsets-alist'. +Also used as the indentation step when `c-syntactic-indentation' is +nil." + :type 'integer + :group 'c) + +(defcustom c-tab-always-indent t + "*Controls the operation of the TAB key. +If t, hitting TAB always just indents the current line. If nil, hitting +TAB indents the current line if point is at the left margin or in the +line's indentation, otherwise it inserts a `real' tab character \(see +note\). If some other value (not nil or t), then tab is inserted only +within literals \(comments and strings), but the line is always +reindented. + +Note: The value of `indent-tabs-mode' will determine whether a real +tab character will be inserted, or the equivalent number of spaces. +When inserting a tab, actually the function stored in the variable +`c-insert-tab-function' is called. + +Note: indentation of lines containing only comments is also controlled +by the `c-comment-only-line-offset' variable." + :type '(radio + (const :tag "TAB key always indents, never inserts TAB" t) + (const :tag "TAB key indents in left margin, otherwise inserts TAB" nil) + (other :tag "TAB key inserts TAB in literals, otherwise indents" other)) + :group 'c) + +(defcustom c-insert-tab-function 'insert-tab + "*Function used when inserting a tab for \\[c-indent-command]. +Only used when `c-tab-always-indent' indicates a `real' tab character +should be inserted. Value must be a function taking no arguments." + :type 'function + :group 'c) + +(defcustom c-syntactic-indentation t + "*Whether the indentation should be controlled by the syntactic context. + +If t, the indentation functions indent according to the syntactic +context, using the style settings specified by `c-offsets-alist'. + +If nil, every line is just indented to the same level as the previous +one, and the \\[c-indent-command] command adjusts the indentation in +steps specified by `c-basic-offset'. The indentation style has no +effect in this mode, nor any of the indentation associated variables, +e.g. `c-special-indent-hook'." + :type 'boolean + :group 'c) +(make-variable-buffer-local 'c-syntactic-indentation) + +(defcustom c-syntactic-indentation-in-macros t + "*Enable syntactic analysis inside macros. +If this is nil, all lines inside macro definitions are analyzed as +`cpp-macro-cont'. Otherwise they are analyzed syntactically, just +like normal code, and `cpp-define-intro' is used to create the +additional indentation of the bodies of \"#define\" macros. + +Having this enabled simplifies editing of large multiline macros, but +it might complicate editing if CC Mode doesn't recognize the context +of the macro content. The default context inside the macro is the +same as the top level, so if it contains \"bare\" statements they +might be indented wrongly, although there are special cases that +handle this in most cases. If this problem occurs, it's usually +countered easily by surrounding the statements by a block \(or even +better with the \"do { ... } while \(0)\" trick)." + :type 'boolean + :group 'c) + +(defcustom c-defun-tactic 'go-outward + "*Whether functions are recognized inside, e.g., a class. +This is used by `c-beginning-of-defun' and like functions. + +Its value is one of: + t -- Functions are recognized only at the top level. + go-outward -- Nested functions are also recognized. Should a function + command hit the beginning/end of a nested scope, it will + carry on at the less nested level." + :type '(radio + (const :tag "Functions are at the top-level" t) + (const :tag "Functions are also recognized inside declaration scopes" go-outward)) + :group 'c) + +(defcustom-c-stylevar c-comment-only-line-offset 0 + "*Extra offset for line which contains only the start of a comment. +Can contain an integer or a cons cell of the form: + + (NON-ANCHORED-OFFSET . ANCHORED-OFFSET) + +Where NON-ANCHORED-OFFSET is the amount of offset given to +non-column-zero anchored comment-only lines, and ANCHORED-OFFSET is +the amount of offset to give column-zero anchored comment-only lines. +Just an integer as value is equivalent to ( . -1000). + +Note that this variable only has effect when the `c-lineup-comment' +lineup function is used on the `comment-intro' syntactic symbol (the +default)." + :type '(choice (integer :tag "Non-anchored offset" 0) + (cons :tag "Non-anchored & anchored offset" + :value (0 . 0) + (integer :tag "Non-anchored offset") + (integer :tag "Anchored offset"))) + :group 'c) + +(defcustom-c-stylevar c-indent-comment-alist + '((anchored-comment . (column . 0)) + (end-block . (space . 1)) + (cpp-end-block . (space . 2))) + "*Specifies how \\[indent-for-comment] calculates the comment start column. +This is an association list that contains entries of the form: + + (LINE-TYPE . INDENT-SPEC) + +LINE-TYPE specifies a type of line as described below, and INDENT-SPEC +says what \\[indent-for-comment] should do when used on that type of line. + +The recognized values for LINE-TYPE are: + + empty-line -- The line is empty. + anchored-comment -- The line contains a comment that starts in column 0. + end-block -- The line contains a solitary block closing brace. + cpp-end-block -- The line contains a preprocessor directive that + closes a block, i.e. either \"#endif\" or \"#else\". + other -- The line does not match any other entry + currently on the list. + +An INDENT-SPEC is a cons cell of the form: + + (ACTION . VALUE) + +ACTION says how \\[indent-for-comment] should align the comment, and +VALUE is interpreted depending on ACTION. ACTION can be any of the +following: + + space -- Put VALUE spaces between the end of the line and the start + of the comment. + column -- Start the comment at the column VALUE. If the line is + longer than that, the comment is preceded by a single + space. If VALUE is nil, `comment-column' is used. + align -- Align the comment with one on the previous line, if there + is any. If the line is too long, the comment is preceded + by a single space. If there isn't a comment start on the + previous line, the behavior is specified by VALUE, which + in turn is interpreted as an INDENT-SPEC. + +If a LINE-TYPE is missing, then \\[indent-for-comment] indents the comment +according to `comment-column'. + +Note that a non-nil value on `c-indent-comments-syntactically-p' +overrides this variable, so empty lines are indentented syntactically +in that case, i.e. as if \\[c-indent-command] was used instead." + :type + (let ((space '(cons :tag "space" + :format "%v" + :value (space . 1) + (const :format "space " space) + (integer :format "%v"))) + (column '(cons :tag "column" + :format "%v" + (const :format "column " column) + (c-integer-or-nil :format "%v")))) + `(set ,@(mapcar + (lambda (elt) + `(cons :format "%v" + ,(c-constant-symbol elt 20) + (choice + :format "%[Choice%] %v" + :value (column . nil) + ,space + ,column + (cons :tag "align" + :format "%v" + (const :format "align " align) + (choice + :format "%[Choice%] %v" + :value (column . nil) + ,space + ,column))))) + '(empty-line anchored-comment end-block cpp-end-block other)))) + :group 'c) + +(defcustom-c-stylevar c-indent-comments-syntactically-p nil + "*Specifies how \\[indent-for-comment] should handle comment-only lines. +When this variable is non-nil, comment-only lines are indented +according to syntactic analysis via `c-offsets-alist'. Otherwise, the +comment is indented as if it was preceded by code. Note that this +variable does not affect how the normal line indentation treats +comment-only lines." + :type 'boolean + :group 'c) + +(make-obsolete-variable 'c-comment-continuation-stars + 'c-block-comment-prefix + nil) + +;; Although c-comment-continuation-stars is obsolete, we look at it in +;; some places in CC Mode anyway, so make the compiler ignore it +;; during our compilation. +(cc-bytecomp-obsolete-var c-comment-continuation-stars) +(cc-bytecomp-defvar c-comment-continuation-stars) + +(defcustom-c-stylevar c-block-comment-prefix + (if (boundp 'c-comment-continuation-stars) + c-comment-continuation-stars + "* ") + "*Specifies the line prefix of continued C-style block comments. +You should set this variable to the literal string that gets inserted +at the front of continued block style comment lines. This should +either be the empty string, or some characters without preceding +spaces. To adjust the alignment under the comment starter, put an +appropriate value on the `c' syntactic symbol (see the +`c-offsets-alist' variable). + +It's only used when a one-line block comment is broken into two or +more lines for the first time; otherwise the appropriate prefix is +adapted from the comment. This variable is not used for C++ line +style comments." + :type 'string + :group 'c) + +(defcustom-c-stylevar c-comment-prefix-regexp + '((pike-mode . "//+!?\\|\\**") + (awk-mode . "#+") + (other . "//+\\|\\**")) + "*Regexp to match the line prefix inside comments. +This regexp is used to recognize the fill prefix inside comments for +correct paragraph filling and other things. + +If this variable is a string, it will be used in all CC Mode major +modes. It can also be an association list, to associate specific +regexps to specific major modes. The symbol for the major mode is +looked up in the association list, and its value is used as the line +prefix regexp. If it's not found, then the symbol `other' is looked +up and its value is used instead. + +The regexp should match the prefix used in both C++ style line +comments and C style block comments, but it does not need to match a +block comment starter. In other words, it should at least match +\"//\" for line comments and the string in `c-block-comment-prefix', +which is sometimes inserted by CC Mode inside block comments. It +should not match any surrounding whitespace. + +Note that CC Mode uses this variable to set many other variables that +handle the paragraph filling. That's done at mode initialization or +when you switch to a style which sets this variable. Thus, if you +change it in some other way, e.g. interactively in a CC Mode buffer, +you will need to do \\[c-setup-paragraph-variables] afterwards so that +the other variables are updated with the new value. + +Note also that when CC Mode starts up, all variables are initialized +before the mode hooks are run. It's therefore necessary to make a +call to `c-setup-paragraph-variables' explicitly if you change this +variable in a mode hook." + :type '(radio + (regexp :tag "Regexp for all modes") + (list + :tag "Mode-specific regexps" + (set + :inline t :format "%v" + (cons :format "%v" + (const :format "C " c-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "C++ " c++-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "ObjC " objc-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "Java " java-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "IDL " idl-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "Pike " pike-mode) (regexp :format "%v")) + (cons :format "%v" + (const :format "AWK " awk-mode) (regexp :format "%v"))) + (cons :format " %v" + (const :format "Other " other) (regexp :format "%v")))) + :group 'c) + +(defcustom-c-stylevar c-doc-comment-style + '((java-mode . javadoc) + (pike-mode . autodoc) + (c-mode . gtkdoc)) + "*Specifies documentation comment style(s) to recognize. +This is primarily used to fontify doc comments and the markup within +them, e.g. Javadoc comments. + +The value can be any of the following symbols for various known doc +comment styles: + + javadoc -- Javadoc style for \"/** ... */\" comments (default in Java mode). + autodoc -- Pike autodoc style for \"//! ...\" comments (default in Pike mode). + gtkdoc -- GtkDoc style for \"/** ... **/\" comments (default in C mode). + +The value may also be a list of doc comment styles, in which case all +of them are recognized simultaneously (presumably with markup cues +that don't conflict). + +The value may also be an association list to specify different doc +comment styles for different languages. The symbol for the major mode +is then looked up in the alist, and the value of that element is +interpreted as above if found. If it isn't found then the symbol +`other' is looked up and its value is used instead. + +Note that CC Mode uses this variable to set other variables that +handle fontification etc. That's done at mode initialization or when +you switch to a style which sets this variable. Thus, if you change +it in some other way, e.g. interactively in a CC Mode buffer, you will +need to do \\[java-mode] (or whatever mode you're currently using) to +reinitialize. + +Note also that when CC Mode starts up, the other variables are +modified before the mode hooks are run. If you change this variable +in a mode hook, you have to call `c-setup-doc-comment-style' +afterwards to redo that work." + ;; Symbols other than those documented above may be used on this + ;; variable. If a variable exists that has that name with + ;; "-font-lock-keywords" appended, it's value is prepended to the + ;; font lock keywords list. If it's a function then it's called and + ;; the result is prepended. + :type '(radio + (c-symbol-list :tag "Doc style(s) in all modes") + (list + :tag "Mode-specific doc styles" + (set + :inline t :format "%v" + (cons :format "%v" + (const :format "C " c-mode) + (c-symbol-list :format "%v")) + (cons :format "%v" + (const :format "C++ " c++-mode) + (c-symbol-list :format "%v")) + (cons :format "%v" + (const :format "ObjC " objc-mode) + (c-symbol-list :format "%v")) + (cons :format "%v" + (const :format "Java " java-mode) + (c-symbol-list :format "%v")) + (cons :format "%v" + (const :format "IDL " idl-mode) + (c-symbol-list :format "%v")) + (cons :format "%v" + (const :format "Pike " pike-mode) + (c-symbol-list :format "%v")) + (cons :format "%v" + (const :format "AWK " awk-mode) + (c-symbol-list :format "%v")) + (cons :format "%v" + (const :format "Other " other) + (c-symbol-list :format "%v"))))) + :group 'c) + +(defcustom c-ignore-auto-fill '(string cpp code) + "*List of contexts in which automatic filling never occurs. +If Auto Fill mode is active, it will be temporarily disabled if point +is in any context on this list. It's e.g. useful to enable Auto Fill +in comments only, but not in strings or normal code. The valid +contexts are: + + string -- inside a string or character literal + c -- inside a C style block comment + c++ -- inside a C++ style line comment + cpp -- inside a preprocessor directive + code -- anywhere else, i.e. in normal code" + :type '(set + (const :tag "String literals" string) + (const :tag "C style block comments" c) + (const :tag "C++ style line comments" c++) + (const :tag "Preprocessor directives" cpp) + (const :tag "Normal code" code)) + :group 'c) + +(defcustom-c-stylevar c-cleanup-list '(scope-operator) + "*List of various C/C++/ObjC constructs to \"clean up\". +The following clean ups only take place when the auto-newline feature +is turned on, as evidenced by the `/la' appearing next to the mode +name: + + brace-else-brace -- Clean up \"} else {\" constructs by placing + entire construct on a single line. This clean + up only takes place when there is nothing but + white space between the braces and the `else'. + Clean up occurs when the open brace after the + `else' is typed. + brace-elseif-brace -- Similar to brace-else-brace, but clean up + \"} else if (...) {\" constructs. Clean up + occurs after the open parenthesis and the open + brace. + brace-catch-brace -- Similar to brace-elseif-brace, but clean up + \"} catch (...) {\" constructs. + empty-defun-braces -- Clean up empty defun braces by placing the + braces on the same line. Clean up occurs when + the defun closing brace is typed. + one-liner-defun -- If the code inside a function body can fit in + a single line, then remove any newlines + between that line and the defun braces so that + the whole body becomes a single line. + `c-max-one-liner-length' gives the maximum + length allowed for the resulting line. Clean + up occurs when the closing brace is typed. + defun-close-semi -- Clean up the terminating semi-colon on defuns + by placing the semi-colon on the same line as + the closing brace. Clean up occurs when the + semi-colon is typed. + list-close-comma -- Clean up commas following braces in array + and aggregate initializers. Clean up occurs + when the comma is typed. + scope-operator -- Clean up double colons which may designate + a C++ scope operator split across multiple + lines. Note that certain C++ constructs can + generate ambiguous situations. This clean up + only takes place when there is nothing but + whitespace between colons. Clean up occurs + when the second colon is typed. + +The following clean ups always take place when they are on this list, +regardless of the auto-newline feature, since they typically don't +involve auto-newline inserted newlines: + + space-before-funcall -- Insert exactly one space before the opening + parenthesis of a function call. Clean up + occurs when the opening parenthesis is typed. + compact-empty-funcall -- Clean up any space before the function call + opening parenthesis if and only if the + argument list is empty. This is typically + useful together with `space-before-funcall' to + get the style \"foo (bar)\" and \"foo()\". + Clean up occurs when the closing parenthesis + is typed. + comment-close-slash -- When a slash is typed after the comment prefix + on a bare line in a c-style comment, the comment + is closed by cleaning up preceding space and + inserting a star if needed." + :type '(set + (const :tag "Put \"} else {\" on one line (brace-else-brace)" + brace-else-brace) + (const :tag "Put \"} else if (...) {\" on one line (brace-elseif-brace)" + brace-elseif-brace) + (const :tag "Put \"} catch (...) {\" on one line (brace-catch-brace)" + brace-catch-brace) + (const :tag "Put empty defun braces on one line (empty-defun-braces)" + empty-defun-braces) + (const :tag "Put short function bodies on one line (one-liner-defun)" + one-liner-defun) + (const :tag "Put \"};\" ending defuns on one line (defun-close-semi)" + defun-close-semi) + (const :tag "Put \"},\" in aggregates on one line (list-close-comma)" + list-close-comma) + (const :tag "Put C++ style \"::\" on one line (scope-operator)" + scope-operator) + (const :tag "Put a space before funcall parens, e.g. \"foo (bar)\" (space-before-funcall)" + space-before-funcall) + (const :tag "Remove space before empty funcalls, e.g. \"foo()\" (compact-empty-funcall)" + compact-empty-funcall) + (const :tag "Make / on a bare line of a C-style comment close it (comment-close-slash)" + comment-close-slash)) + :group 'c) + +(defcustom-c-stylevar c-hanging-braces-alist '((brace-list-open) + (brace-entry-open) + (statement-cont) + (substatement-open after) + (block-close . c-snug-do-while) + (extern-lang-open after) + (namespace-open after) + (module-open after) + (composition-open after) + (inexpr-class-open after) + (inexpr-class-close before) + (arglist-cont-nonempty)) + "*Controls the insertion of newlines before and after braces +when the auto-newline feature is active. This variable contains an +association list with elements of the following form: +\(SYNTACTIC-SYMBOL . ACTION). + +When a brace (either opening or closing) is inserted, the syntactic +context it defines is looked up in this list, and if found, the +associated ACTION is used to determine where newlines are inserted. +If the context is not found, the default is to insert a newline both +before and after the brace. + +SYNTACTIC-SYMBOL can be statement-cont, brace-list-intro, +inexpr-class-open, inexpr-class-close, and any of the *-open and +*-close symbols. See `c-offsets-alist' for details, except for +inexpr-class-open and inexpr-class-close, which doesn't have any +corresponding symbols there. Those two symbols are used for the +opening and closing braces, respectively, of anonymous inner classes +in Java. + +ACTION can be either a function symbol or a list containing any +combination of the symbols `before' or `after'. If the list is empty, +no newlines are inserted either before or after the brace. + +When ACTION is a function symbol, the function is called with a two +arguments: the syntactic symbol for the brace and the buffer position +at which the brace was inserted. The function must return a list as +described in the preceding paragraph. Note that during the call to +the function, the variable `c-syntactic-context' is set to the entire +syntactic context for the brace line." + :type + `(set ,@(mapcar + (lambda (elt) + `(cons :format "%v" + ,(c-constant-symbol elt 24) + (choice :format "%[Choice%] %v" + :value (before after) + (set :menu-tag "Before/after" + :format "Newline %v brace\n" + (const :format "%v, " before) + (const :format "%v " after)) + (function :menu-tag "Function" + :format "Run function: %v")))) + '(defun-open defun-close + class-open class-close + inline-open inline-close + block-open block-close + statement-cont substatement-open statement-case-open + brace-list-open brace-list-close + brace-list-intro brace-entry-open + extern-lang-open extern-lang-close + namespace-open namespace-close + module-open module-close + composition-open composition-close + inexpr-class-open inexpr-class-close + arglist-cont-nonempty))) + :group 'c) + +(defcustom c-max-one-liner-length 80 + "Maximum length of line that clean-up \"one-liner-defun\" will compact to. +Zero or nil means no limit." + :type 'integer + :group 'c) + +(defcustom-c-stylevar c-hanging-colons-alist nil + "*Controls the insertion of newlines before and after certain colons. +This variable contains an association list with elements of the +following form: (SYNTACTIC-SYMBOL . ACTION). + +SYNTACTIC-SYMBOL can be any of: case-label, label, access-label, +member-init-intro, or inher-intro. + +See the variable `c-hanging-braces-alist' for the semantics of this +variable. Note however that making ACTION a function symbol is +currently not supported for this variable." + :type + `(set ,@(mapcar + (lambda (elt) + `(cons :format "%v" + ,(c-constant-symbol elt 20) + (set :format "Newline %v colon\n" + (const :format "%v, " before) + (const :format "%v" after)))) + '(case-label label access-label member-init-intro inher-intro))) + :group 'c) + +(defcustom-c-stylevar c-hanging-semi&comma-criteria + '(c-semi&comma-inside-parenlist) + "*List of functions that decide whether to insert a newline or not. +The functions in this list are called, in order, whenever the +auto-newline minor mode is activated (as evidenced by a `/a' or `/ah' +string in the mode line), and a semicolon or comma is typed (see +`c-electric-semi&comma'). Each function in this list is called with +no arguments, and should return one of the following values: + + nil -- no determination made, continue checking + 'stop -- do not insert a newline, and stop checking + (anything else) -- insert a newline, and stop checking + +If every function in the list is called with no determination made, +then no newline is inserted." + :type '(repeat function) + :group 'c) + +(defcustom-c-stylevar c-backslash-column 48 + "*Minimum alignment column for line continuation backslashes. +This is used by the functions that automatically insert or align the +line continuation backslashes in multiline macros. If any line in the +macro exceeds this column then the next tab stop from that line is +used as alignment column instead. See also `c-backslash-max-column'." + :type 'integer + :group 'c) + +(defcustom-c-stylevar c-backslash-max-column 72 + "*Maximum alignment column for line continuation backslashes. +This is used by the functions that automatically insert or align the +line continuation backslashes in multiline macros. If any line in the +macro exceeds this column then the backslashes for the other lines +will be aligned at this column." + :type 'integer + :group 'c) + +(defcustom c-auto-align-backslashes t + "*Align automatically inserted line continuation backslashes. +When line continuation backslashes are inserted automatically for line +breaks in multiline macros, e.g. by \\[c-context-line-break], they are +aligned with the other backslashes in the same macro if this flag is +set. Otherwise the inserted backslashes are preceded by a single +space." + :type 'boolean + :group 'c) + +(defcustom c-backspace-function 'backward-delete-char-untabify + "*Function called by `c-electric-backspace' when deleting backwards." + :type 'function + :group 'c) + +(defcustom c-delete-function 'delete-char + "*Function called by `c-electric-delete-forward' when deleting forwards." + :type 'function + :group 'c) + +(defcustom c-require-final-newline + ;; C and C++ mandate that all nonempty files should end with a + ;; newline. Objective-C refers to C for all things it doesn't + ;; specify, so the same holds there. The other languages do not + ;; require it (at least not explicitly in a normative text). + '((c-mode . t) + (c++-mode . t) + (objc-mode . t)) + "*Controls whether a final newline is ensured when the file is saved. +The value is an association list that for each language mode specifies +the value to give to `require-final-newline' at mode initialization; +see that variable for details about the value. If a language isn't +present on the association list, CC Mode won't touch +`require-final-newline' in buffers for that language." + :type `(set (cons :format "%v" + (const :format "C " c-mode) + (symbol :format "%v" :value ,require-final-newline)) + (cons :format "%v" + (const :format "C++ " c++-mode) + (symbol :format "%v" :value ,require-final-newline)) + (cons :format "%v" + (const :format "ObjC " objc-mode) + (symbol :format "%v" :value ,require-final-newline)) + (cons :format "%v" + (const :format "Java " java-mode) + (symbol :format "%v" :value ,require-final-newline)) + (cons :format "%v" + (const :format "IDL " idl-mode) + (symbol :format "%v" :value ,require-final-newline)) + (cons :format "%v" + (const :format "Pike " pike-mode) + (symbol :format "%v" :value ,require-final-newline)) + (cons :format "%v" + (const :format "AWK " awk-mode) + (symbol :format "%v" :value ,require-final-newline))) + :group 'c) + +(defcustom c-electric-pound-behavior nil + "*List of behaviors for electric pound insertion. +Only currently supported behavior is `alignleft'." + :type '(set (const alignleft)) + :group 'c) + +(defcustom c-special-indent-hook nil + "*Hook for user defined special indentation adjustments. +This hook gets called after each line is indented by the mode. It is only +called when `c-syntactic-indentation' is non-nil." + :type 'hook + :group 'c) + +(defcustom-c-stylevar c-label-minimum-indentation 1 + "*Minimum indentation for lines inside code blocks. +This variable typically only affects code using the `gnu' style, which +mandates a minimum of one space in front of every line inside code +blocks. Specifically, the function `c-gnu-impose-minimum' on your +`c-special-indent-hook' is what enforces this." + :type 'integer + :group 'c) + +(defcustom c-progress-interval 5 + "*Interval used to update progress status during long re-indentation. +If a number, percentage complete gets updated after each interval of +that many seconds. To inhibit all messages during indentation, set +this variable to nil." + :type 'integer + :group 'c) + +(defcustom c-objc-method-arg-min-delta-to-bracket 2 + "*Minimum number of chars to the opening bracket. + +Consider this ObjC snippet: + + [foo blahBlah: fred + |<-x->|barBaz: barney + +If `x' is less than this number then `c-lineup-ObjC-method-call-colons' +will defer the indentation decision to the next function. By default +this is `c-lineup-ObjC-method-call', which would align it like: + + [foo blahBlahBlah: fred + thisIsTooDamnLong: barney + +This behaviour can be overridden by customizing the indentation of +`objc-method-call-cont' in the \"objc\" style." + :type 'integer + :group 'c) + +(defcustom c-objc-method-arg-unfinished-offset 4 + "*Offset relative to bracket if first selector is on a new line. + + [aaaaaaaaa + |<-x->|bbbbbbb: cccccc + ddddd: eeee];" + :type 'integer + :group 'c) + +(defcustom c-objc-method-parameter-offset 4 + "*Offset for selector parameter on a new line (relative to first selector. + + [aaaaaaa bbbbbbbbbb: + |<-x->|cccccccc + ddd: eeee + ffff: ggg];" + :type 'integer + :group 'c) + +(defcustom c-default-style '((java-mode . "java") (awk-mode . "awk") + (other . "gnu")) + "*Style which gets installed by default when a file is visited. + +The value of this variable can be any style defined in +`c-style-alist', including styles you add. The value can also be an +association list of major mode symbols to style names. + +When the value is a string, all CC Mode major modes will install this +style by default. + +When the value is an alist, the major mode symbol is looked up in it +and the associated style is installed. If the major mode is not +listed in the alist, then the symbol `other' is looked up in it, and +if found, the style in that entry is used. If `other' is not found in +the alist, then \"gnu\" style is used. + +The default style gets installed before your mode hooks run, so you +can always override the use of `c-default-style' by making calls to +`c-set-style' in the appropriate mode hook." + :type '(radio + (string :tag "Style in all modes") + (set :tag "Mode-specific styles" + (cons :format "%v" + (const :format "C " c-mode) (string :format "%v")) + (cons :format "%v" + (const :format "C++ " c++-mode) (string :format "%v")) + (cons :format "%v" + (const :format "ObjC " objc-mode) (string :format "%v")) + (cons :format "%v" + (const :format "Java " java-mode) (string :format "%v")) + (cons :format "%v" + (const :format "IDL " idl-mode) (string :format "%v")) + (cons :format "%v" + (const :format "Pike " pike-mode) (string :format "%v")) + (cons :format "%v" + (const :format "AWK " awk-mode) (string :format "%v")) + (cons :format "%v" + (const :format "Other " other) (string :format "%v")))) + :group 'c) + +;; *) At the start of a statement or declaration means in more detail: +;; At the closest preceding statement/declaration that starts at boi +;; and doesn't have a label or comment at that position. If there's +;; no such statement within the same block, then back up to the +;; surrounding block or statement, add the appropriate +;; statement-block-intro, defun-block-intro or substatement syntax +;; symbol and continue searching. +(c-set-stylevar-fallback 'c-offsets-alist + '((string . c-lineup-dont-change) + ;; Anchor pos: Beg of previous line. + (c . c-lineup-C-comments) + ;; Anchor pos: Beg of the comment. + (defun-open . 0) + ;; Anchor pos: When inside a class: Boi at the func decl start. + ;; When at top level: Bol at the func decl start. When inside + ;; a code block (only possible in Pike): At the func decl + ;; start(*). + (defun-close . 0) + ;; Anchor pos: At the defun block open if it's at boi, + ;; otherwise boi at the func decl start. + (defun-block-intro . +) + ;; Anchor pos: At the block open(*). + (class-open . 0) + ;; Anchor pos: Boi at the class decl start. + (class-close . 0) + ;; Anchor pos: Boi at the class decl start. + (inline-open . +) + ;; Anchor pos: None for functions (inclass got the relpos + ;; then), boi at the lambda start for lambdas. + (inline-close . 0) + ;; Anchor pos: Inexpr functions: At the lambda block open if + ;; it's at boi, else at the statement(*) at boi of the start of + ;; the lambda construct. Otherwise: At the inline block open + ;; if it's at boi, otherwise boi at the func decl start. + (func-decl-cont . +) + ;; Anchor pos: Boi at the func decl start. + (knr-argdecl-intro . +) + ;; Anchor pos: Boi at the topmost intro line. + (knr-argdecl . 0) + ;; Anchor pos: At the beginning of the first K&R argdecl. + (topmost-intro . 0) + ;; Anchor pos: Bol at the last line of previous construct. + (topmost-intro-cont . c-lineup-topmost-intro-cont) + ;;Anchor pos: Bol at the topmost annotation line + (annotation-top-cont . 0) + ;;Anchor pos: Bol at the topmost annotation line + (annotation-var-cont . +) + ;; Anchor pos: Boi at the topmost intro line. + (member-init-intro . +) + ;; Anchor pos: Boi at the func decl arglist open. + (member-init-cont . c-lineup-multi-inher) + ;; Anchor pos: Beg of the first member init. + (inher-intro . +) + ;; Anchor pos: Boi at the class decl start. + (inher-cont . c-lineup-multi-inher) + ;; Anchor pos: Java: At the implements/extends keyword start. + ;; Otherwise: At the inher start colon, or boi at the class + ;; decl start if the first inherit clause hangs and it's not a + ;; func-local inherit clause (when does that occur?). + (block-open . 0) + ;; Anchor pos: Inexpr statement: At the statement(*) at boi of + ;; the start of the inexpr construct. Otherwise: None. + (block-close . 0) + ;; Anchor pos: Inexpr statement: At the inexpr block open if + ;; it's at boi, else at the statement(*) at boi of the start of + ;; the inexpr construct. Block hanging on a case/default + ;; label: At the closest preceding label that starts at boi. + ;; Otherwise: At the block open(*). + (brace-list-open . 0) + ;; Anchor pos: Boi at the brace list decl start, but a starting + ;; "typedef" token is ignored. + (brace-list-close . 0) + ;; Anchor pos: At the brace list decl start(*). + (brace-list-intro . +) + ;; Anchor pos: At the brace list decl start(*). + (brace-list-entry . 0) + ;; Anchor pos: At the first non-ws char after the open paren if + ;; the first token is on the same line, otherwise boi at that + ;; token. + (brace-entry-open . 0) + ;; Anchor pos: Same as brace-list-entry. + (statement . 0) + ;; Anchor pos: After a `;' in the condition clause of a for + ;; statement: At the first token after the starting paren. + ;; Otherwise: At the preceding statement(*). + (statement-cont . +) + ;; Anchor pos: After the first token in the condition clause of + ;; a for statement: At the first token after the starting + ;; paren. Otherwise: At the containing statement(*). + (statement-block-intro . +) + ;; Anchor pos: In inexpr statement block: At the inexpr block + ;; open if it's at boi, else at the statement(*) at boi of the + ;; start of the inexpr construct. In a block hanging on a + ;; case/default label: At the closest preceding label that + ;; starts at boi. Otherwise: At the start of the containing + ;; block(*). + (statement-case-intro . +) + ;; Anchor pos: At the case/default label(*). + (statement-case-open . 0) + ;; Anchor pos: At the case/default label(*). + (substatement . +) + ;; Anchor pos: At the containing statement(*). + (substatement-open . +) + ;; Anchor pos: At the containing statement(*). + (substatement-label . 2) + ;; Anchor pos: At the containing statement(*). + (case-label . 0) + ;; Anchor pos: At the start of the switch block(*). + (access-label . -) + ;; Anchor pos: Same as inclass. + (label . 2) + ;; Anchor pos: At the start of the containing block(*). + (do-while-closure . 0) + ;; Anchor pos: At the corresponding while statement(*). + (else-clause . 0) + ;; Anchor pos: At the corresponding if statement(*). + (catch-clause . 0) + ;; Anchor pos: At the previous try or catch statement clause(*). + (comment-intro . (c-lineup-knr-region-comment c-lineup-comment)) + ;; Anchor pos: None. + (arglist-intro . +) + ;; Anchor pos: At the containing statement(*). + ;; 2nd pos: At the open paren. + (arglist-cont . (c-lineup-gcc-asm-reg 0)) + ;; Anchor pos: At the first token after the open paren. + (arglist-cont-nonempty . (c-lineup-gcc-asm-reg c-lineup-arglist)) + ;; Anchor pos: At the containing statement(*). + ;; 2nd pos: At the open paren. + (arglist-close . +) + ;; Anchor pos: At the containing statement(*). + ;; 2nd pos: At the open paren. + (stream-op . c-lineup-streamop) + ;; Anchor pos: Boi at the first stream op in the statement. + (inclass . +) + ;; Anchor pos: At the class open brace if it's at boi, + ;; otherwise boi at the class decl start. + (cpp-macro . [0]) + ;; Anchor pos: None. + (cpp-macro-cont . +) + ;; Anchor pos: At the macro start (always at boi). + (cpp-define-intro . (c-lineup-cpp-define +)) + ;; Anchor pos: None. + (friend . 0) + ;; Anchor pos: None. + (objc-method-intro . [0]) + ;; Anchor pos: Boi. + (objc-method-args-cont . c-lineup-ObjC-method-args) + ;; Anchor pos: At the method start (always at boi). + (objc-method-call-cont . (c-lineup-ObjC-method-call-colons + c-lineup-ObjC-method-call +)) + ;; Anchor pos: At the open bracket. + (extern-lang-open . 0) + (namespace-open . 0) + (module-open . 0) + (composition-open . 0) + ;; Anchor pos: Boi at the extern/namespace/etc keyword. + (extern-lang-close . 0) + (namespace-close . 0) + (module-close . 0) + (composition-close . 0) + ;; Anchor pos: Boi at the corresponding extern/namespace/etc keyword. + (inextern-lang . +) + (innamespace . +) + (inmodule . +) + (incomposition . +) + ;; Anchor pos: At the extern/namespace/etc block open brace if + ;; it's at boi, otherwise boi at the keyword. + (template-args-cont . (c-lineup-template-args +)) + ;; Anchor pos: Boi at the decl start. This might be changed; + ;; the logical position is clearly the opening '<'. + (inlambda . c-lineup-inexpr-block) + ;; Anchor pos: None. + (lambda-intro-cont . +) + ;; Anchor pos: Boi at the lambda start. + (inexpr-statement . +) + ;; Anchor pos: None. + (inexpr-class . +) + ;; Anchor pos: None. + )) +(defcustom c-offsets-alist nil + "Association list of syntactic element symbols and indentation offsets. +As described below, each cons cell in this list has the form: + + (SYNTACTIC-SYMBOL . OFFSET) + +When a line is indented, CC Mode first determines the syntactic +context of it by generating a list of symbols called syntactic +elements. The global variable `c-syntactic-context' is bound to the +that list. Each element in the list is in turn a list where the first +element is a syntactic symbol which tells what kind of construct the +indentation point is located within. More elements in the syntactic +element lists are optional. If there is one more and it isn't nil, +then it's the anchor position for that construct. + +After generating the syntactic context for the line, CC Mode +calculates the absolute indentation: First the base indentation is +found by using the anchor position for the first syntactic element +that provides one. If none does, zero is used as base indentation. +Then CC Mode looks at each syntactic element in the context in turn. +It compares the car of the syntactic element against the +SYNTACTIC-SYMBOL's in `c-offsets-alist'. When it finds a match, it +adds OFFSET to the base indentation. The sum of this calculation is +the absolute offset for line being indented. + +If the syntactic element does not match any in the `c-offsets-alist', +the element is ignored. + +OFFSET can specify an offset in several different ways: + + If OFFSET is nil then it's ignored. + + If OFFSET is an integer then it's used as relative offset, i.e. it's + added to the base indentation. + + If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/' + then a positive or negative multiple of `c-basic-offset' is added to + the base indentation; 1, -1, 2, -2, 0.5, and -0.5, respectively. + + If OFFSET is a symbol with a value binding then that value, which + must be an integer, is used as relative offset. + + If OFFSET is a vector then its first element, which must be an + integer, is used as an absolute indentation column. This overrides + the previous base indentation and the relative offsets applied to + it, and it becomes the new base indentation. + + If OFFSET is a function or a lambda expression then it's called with + a single argument containing the cons of the syntactic symbol and + the anchor position (or nil if there is none). The return value + from the function is then reinterpreted as an offset specification. + + If OFFSET is a list then its elements are evaluated recursively as + offset specifications. If the first element is any of the symbols + below then it isn't evaluated but instead specifies how the + remaining offsets in the list should be combined. If it's something + else then the list is combined according the method `first'. The + valid combination methods are: + + `first' -- Use the first offset (that doesn't evaluate to nil). + `min' -- Use the minimum of all the offsets. All must be either + relative or absolute - they can't be mixed. + `max' -- Use the maximum of all the offsets. All must be either + relative or absolute - they can't be mixed. + `add' -- Add all the evaluated offsets together. Exactly one of + them may be absolute, in which case the result is + absolute. Any relative offsets that preceded the + absolute one in the list will be ignored in that case. + +`c-offsets-alist' is a style variable. This means that the offsets on +this variable are normally taken from the style system in CC Mode +\(see `c-default-style' and `c-style-alist'). However, any offsets +put explicitly on this list will override the style system when a CC +Mode buffer is initialized \(there is a variable +`c-old-style-variable-behavior' that changes this, though). + +Here is the current list of valid syntactic element symbols: + + string -- Inside multi-line string. + c -- Inside a multi-line C style block comment. + defun-open -- Brace that opens a function definition. + defun-close -- Brace that closes a function definition. + defun-block-intro -- The first line in a top-level defun. + class-open -- Brace that opens a class definition. + class-close -- Brace that closes a class definition. + inline-open -- Brace that opens an in-class inline method. + inline-close -- Brace that closes an in-class inline method. + func-decl-cont -- The region between a function definition's + argument list and the function opening brace + (excluding K&R argument declarations). In C, you + cannot put anything but whitespace and comments + between them; in C++ and Java, throws declarations + and other things can appear in this context. + knr-argdecl-intro -- First line of a K&R C argument declaration. + knr-argdecl -- Subsequent lines in a K&R C argument declaration. + topmost-intro -- The first line in a topmost construct definition. + topmost-intro-cont -- Topmost definition continuation lines. + annotation-top-cont -- Topmost definition continuation line where only + annotations are on previous lines. + annotation-var-cont -- A continuation of a C (or like) statement where + only annotations are on previous lines. + member-init-intro -- First line in a member initialization list. + member-init-cont -- Subsequent member initialization list lines. + inher-intro -- First line of a multiple inheritance list. + inher-cont -- Subsequent multiple inheritance lines. + block-open -- Statement block open brace. + block-close -- Statement block close brace. + brace-list-open -- Open brace of an enum or static array list. + brace-list-close -- Close brace of an enum or static array list. + brace-list-intro -- First line in an enum or static array list. + brace-list-entry -- Subsequent lines in an enum or static array list. + brace-entry-open -- Subsequent lines in an enum or static array + list that start with an open brace. + statement -- A C (or like) statement. + statement-cont -- A continuation of a C (or like) statement. + statement-block-intro -- The first line in a new statement block. + statement-case-intro -- The first line in a case \"block\". + statement-case-open -- The first line in a case block starting with brace. + substatement -- The first line after an if/while/for/do/else. + substatement-open -- The brace that opens a substatement block. + substatement-label -- Labelled line after an if/while/for/do/else. + case-label -- A \"case\" or \"default\" label. + access-label -- C++ private/protected/public access label. + label -- Any ordinary label. + do-while-closure -- The \"while\" that ends a do/while construct. + else-clause -- The \"else\" of an if/else construct. + catch-clause -- The \"catch\" or \"finally\" of a try/catch construct. + comment-intro -- A line containing only a comment introduction. + arglist-intro -- The first line in an argument list. + arglist-cont -- Subsequent argument list lines when no + arguments follow on the same line as the + arglist opening paren. + arglist-cont-nonempty -- Subsequent argument list lines when at + least one argument follows on the same + line as the arglist opening paren. + arglist-close -- The solo close paren of an argument list. + stream-op -- Lines continuing a stream operator construct. + inclass -- The construct is nested inside a class definition. + Used together with e.g. `topmost-intro'. + cpp-macro -- The start of a C preprocessor macro definition. + cpp-macro-cont -- Inside a multi-line C preprocessor macro definition. + friend -- A C++ friend declaration. + objc-method-intro -- The first line of an Objective-C method definition. + objc-method-args-cont -- Lines continuing an Objective-C method definition. + objc-method-call-cont -- Lines continuing an Objective-C method call. + extern-lang-open -- Brace that opens an \"extern\" block. + extern-lang-close -- Brace that closes an \"extern\" block. + inextern-lang -- Analogous to the `inclass' syntactic symbol, + but used inside \"extern\" blocks. + namespace-open, namespace-close, innamespace + -- Similar to the three `extern-lang' symbols, but for + C++ \"namespace\" blocks. + module-open, module-close, inmodule + -- Similar to the three `extern-lang' symbols, but for + CORBA IDL \"module\" blocks. + composition-open, composition-close, incomposition + -- Similar to the three `extern-lang' symbols, but for + CORBA CIDL \"composition\" blocks. + template-args-cont -- C++ template argument list continuations. + inlambda -- In the header or body of a lambda function. + lambda-intro-cont -- Continuation of the header of a lambda function. + inexpr-statement -- The statement is inside an expression. + inexpr-class -- The class is inside an expression. Used e.g. for + Java anonymous classes." + :type + `(set :format "%{%t%}: + Override style setting + | Syntax Offset +%v" + ,@(mapcar + (lambda (elt) + `(cons :format "%v" + :value ,elt + ,(c-constant-symbol (car elt) 25) + (sexp :format "%v" + :validate + (lambda (widget) + (unless (c-valid-offset (widget-value widget)) + (widget-put widget :error "Invalid offset") + widget))))) + (get 'c-offsets-alist 'c-stylevar-fallback))) + :group 'c) + +;; The syntactic symbols that can occur inside code blocks. Used by +;; `c-gnu-impose-minimum'. +(defconst c-inside-block-syms + '(defun-block-intro block-open block-close statement statement-cont + statement-block-intro statement-case-intro statement-case-open + substatement substatement-open substatement-label case-label label + do-while-closure else-clause catch-clause inlambda annotation-var-cont)) + +(defcustom c-style-variables-are-local-p t + "*Whether style variables should be buffer local by default. +If non-nil, then all indentation style related variables will be made +buffer local by default. If nil, they will remain global. Variables +are made buffer local when this file is loaded, and once buffer +localized, they cannot be made global again. + +This variable must be set appropriately before CC Mode is loaded. + +The list of variables to buffer localize are: + c-basic-offset + c-comment-only-line-offset + c-indent-comment-alist + c-indent-comments-syntactically-p + c-block-comment-prefix + c-comment-prefix-regexp + c-doc-comment-style + c-cleanup-list + c-hanging-braces-alist + c-hanging-colons-alist + c-hanging-semi&comma-criteria + c-backslash-column + c-backslash-max-column + c-label-minimum-indentation + c-offsets-alist + c-special-indent-hook + c-indentation-style" + :type 'boolean + :group 'c) + +(defcustom c-mode-hook nil + "*Hook called by `c-mode'." + :type 'hook + :group 'c) + +(defcustom c++-mode-hook nil + "*Hook called by `c++-mode'." + :type 'hook + :group 'c) + +(defcustom objc-mode-hook nil + "*Hook called by `objc-mode'." + :type 'hook + :group 'c) + +(defcustom java-mode-hook nil + "*Hook called by `java-mode'." + :type 'hook + :group 'c) + +(defcustom idl-mode-hook nil + "*Hook called by `idl-mode'." + :type 'hook + :group 'c) + +(defcustom pike-mode-hook nil + "*Hook called by `pike-mode'." + :type 'hook + :group 'c) + +(defcustom awk-mode-hook nil + "*Hook called by `awk-mode'." + :type 'hook + :group 'c) + +(defcustom c-mode-common-hook nil + "*Hook called by all CC Mode modes for common initializations." + :type 'hook + :group 'c) + +(defcustom c-initialization-hook nil + "*Hook called when the CC Mode package gets initialized. +This hook is only run once per Emacs session and can be used as a +`load-hook' or in place of using `eval-after-load'." + :type 'hook + :group 'c) + +(defcustom c-enable-xemacs-performance-kludge-p nil + "*Enables a XEmacs only hack that may improve speed for some coding styles. +For styles that hang top-level opening braces (as is common with JDK +Java coding styles) this can improve performance between 3 and 60 +times for core indentation functions (e.g. `c-parse-state'). For +styles that conform to the Emacs recommendation of putting these +braces in column zero, this can degrade performance about as much. +This variable only has effect in XEmacs." + :type 'boolean + :group 'c) + +(defvar c-old-style-variable-behavior nil + "*Enables the old style variable behavior when non-nil. + +Normally the values of the style variables will override the style +settings specified by the variables `c-default-style' and +`c-style-alist'. However, in CC Mode 5.25 and earlier, it was the +other way around, meaning that changes made to the style variables +from e.g. Customize would not take effect unless special precautions +were taken. That was confusing, especially for novice users. + +It's believed that despite this change, the new behavior will still +produce the same results for most old CC Mode configurations, since +all style variables are per default set in a special non-override +state. Set this variable only if your configuration has stopped +working due to this change.") + +(define-widget 'c-extra-types-widget 'radio + "Internal CC Mode widget for the `*-font-lock-extra-types' variables." + :args '((const :tag "none" nil) + (repeat :tag "types" regexp))) + +(defun c-make-font-lock-extra-types-blurb (mode1 mode2 example) + (concat "\ +*List of extra types (aside from the type keywords) to recognize in " +mode1 " mode. +Each list item should be a regexp matching a single identifier. +" example " + +Note that items on this list that don't include any regexp special +characters are automatically optimized using `regexp-opt', so you +should not use `regexp-opt' explicitly to build regexps here. + +On decoration level 3 (and higher, where applicable), a method is used +that finds most types and declarations by syntax alone. This variable +is still used as a first step, but other types are recognized +correctly anyway in most cases. Therefore this variable should be +fairly restrictive and not contain patterns that are uncertain. + +Note that this variable is only consulted when the major mode is +initialized. If you change it later you have to reinitialize CC Mode +by doing \\[" mode2 "]. + +Despite the name, this variable is not only used for font locking but +also elsewhere in CC Mode to tell types from other identifiers.")) + +;; Note: Most of the variables below are also defined in font-lock.el +;; in older versions of Emacs, so depending on the load order we might +;; not install the values below. There's no kludge to cope with this +;; (as opposed to the *-font-lock-keywords-* variables) since the old +;; values work fairly well anyway. + +(defcustom c-font-lock-extra-types + '("\\sw+_t" + ;; Defined in C99: + "bool" "complex" "imaginary" + ;; Standard library types (except those matched by the _t pattern): + "FILE" "lconv" "tm" "va_list" "jmp_buf" + ;; I do not appreciate the following very Emacs-specific luggage + ;; in the default value, but otoh it can hardly get in the way for + ;; other users, and removing it would cause unnecessary grief for + ;; the old timers that are used to it. /mast + "Lisp_Object") + (c-make-font-lock-extra-types-blurb "C" "c-mode" +"For example, a value of (\"FILE\" \"\\\\sw+_t\") means the word \"FILE\" +and words ending in \"_t\" are treated as type names.") + :type 'c-extra-types-widget + :group 'c) + +(defcustom c++-font-lock-extra-types + '("\\sw+_t" + ;; C library types (except those matched by the _t pattern): + "FILE" "lconv" "tm" "va_list" "jmp_buf" + ;; Some standard C++ types that came from font-lock.el. + ;; Experienced C++ users says there's no clear benefit in + ;; extending this to all the types in the standard library, at + ;; least not when they'll be recognized without "std::" too. + "istream" "istreambuf" + "ostream" "ostreambuf" + "ifstream" "ofstream" "fstream" + "strstream" "strstreambuf" "istrstream" "ostrstream" + "ios" + "string" "rope" + "list" "slist" + "deque" "vector" "bit_vector" + "set" "multiset" + "map" "multimap" + "hash" + "hash_set" "hash_multiset" + "hash_map" "hash_multimap" + "stack" "queue" "priority_queue" + "type_info" + "iterator" "const_iterator" "reverse_iterator" "const_reverse_iterator" + "reference" "const_reference") + (c-make-font-lock-extra-types-blurb "C++" "c++-mode" +"For example, a value of (\"string\") means the word \"string\" is treated +as a type name.") + :type 'c-extra-types-widget + :group 'c) + +(defcustom objc-font-lock-extra-types + (list (concat "[" c-upper "]\\sw*[" c-lower "]\\sw*")) + (c-make-font-lock-extra-types-blurb "ObjC" "objc-mode" (concat +"For example, a value of (\"[" c-upper "]\\\\sw*[" c-lower "]\\\\sw*\") means +capitalized words are treated as type names (the requirement for a +lower case char is to avoid recognizing all-caps macro and constant +names).")) + :type 'c-extra-types-widget + :group 'c) + +(defcustom java-font-lock-extra-types + (list (concat "[" c-upper "]\\sw*[" c-lower "]\\sw")) + (c-make-font-lock-extra-types-blurb "Java" "java-mode" (concat +"For example, a value of (\"[" c-upper "]\\\\sw*[" c-lower "]\\\\sw*\") means +capitalized words are treated as type names (the requirement for a +lower case char is to avoid recognizing all-caps constant names).")) + :type 'c-extra-types-widget + :group 'c) + +(defcustom idl-font-lock-extra-types nil + (c-make-font-lock-extra-types-blurb "IDL" "idl-mode" "") + :type 'c-extra-types-widget + :group 'c) + +(defcustom pike-font-lock-extra-types + (list (concat "[" c-upper "]\\sw*[" c-lower "]\\sw*")) + (c-make-font-lock-extra-types-blurb "Pike" "pike-mode" (concat +"For example, a value of (\"[" c-upper "]\\\\sw*[" c-lower "]\\\\sw*\") means +capitalized words are treated as type names (the requirement for a +lower case char is to avoid recognizing all-caps macro and constant +names).")) + :type 'c-extra-types-widget + :group 'c) + + +;; Non-customizable variables, still part of the interface to CC Mode +(defvar c-macro-with-semi-re nil + ;; Regular expression which matches a (#define'd) symbol whose expansion + ;; ends with a semicolon. + ;; + ;; This variable should be set by `c-make-macros-with-semi-re' rather than + ;; directly. +) +(make-variable-buffer-local 'c-macro-with-semi-re) + +(defun c-make-macro-with-semi-re () + ;; Convert `c-macro-names-with-semicolon' into the regexp + ;; `c-macro-with-semi-re' (or just copy it if it's already a re). + (setq c-macro-with-semi-re + (and + c-opt-cpp-macro-define + (cond + ((stringp c-macro-names-with-semicolon) + (copy-sequence c-macro-names-with-semicolon)) + ((consp c-macro-names-with-semicolon) + (concat + "\\<" + (regexp-opt c-macro-names-with-semicolon) + "\\>")) ; N.B. the PAREN param of regexp-opt isn't supported by + ; all XEmacsen. + ((null c-macro-names-with-semicolon) + nil) + (t (error "c-make-macro-with-semi-re: invalid \ +c-macro-names-with-semicolon: %s" + c-macro-names-with-semicolon)))))) + +(defvar c-macro-names-with-semicolon + '("Q_OBJECT" "Q_PROPERTY" "Q_DECLARE" "Q_ENUMS") + "List of #defined symbols whose expansion ends with a semicolon. +Alternatively it can be a string, a regular expression which +matches all such symbols. + +The \"symbols\" must be syntactically valid identifiers in the +target language \(C, C++, Objective C), or \(as the case may be) +the regular expression must match only valid identifiers. + +If you change this variable's value, call the function +`c-make-macros-with-semi-re' to set the necessary internal +variables. + +Note that currently \(2008-11-04) this variable is a prototype, +and is likely to disappear or change its form soon.") +(make-variable-buffer-local 'c-macro-names-with-semicolon) + +(defvar c-file-style nil + "Variable interface for setting style via File Local Variables. +In a file's Local Variable section, you can set this variable to a +string suitable for `c-set-style'. When the file is visited, CC Mode +will set the style of the file to this value automatically. + +Note that file style settings are applied before file offset settings +as designated in the variable `c-file-offsets'.") +(make-variable-buffer-local 'c-file-style) + +(defvar c-file-offsets nil + "Variable interface for setting offsets via File Local Variables. +In a file's Local Variable section, you can set this variable to an +association list similar to the values allowed in `c-offsets-alist'. +When the file is visited, CC Mode will institute these offset settings +automatically. + +Note that file offset settings are applied after file style settings +as designated in the variable `c-file-style'.") +(make-variable-buffer-local 'c-file-offsets) + +;; It isn't possible to specify a doc-string without specifying an +;; initial value with `defvar', so the following two variables have been +;; given doc-strings by setting the property `variable-documentation' +;; directly. C-h v will read this documentation only for versions of GNU +;; Emacs from 22.1. It's really good not to have an initial value for +;; variables like these that always should be dynamically bound, so it's +;; worth the inconvenience. + +(cc-bytecomp-defvar c-syntactic-context) +(defvar c-syntactic-context) +(put 'c-syntactic-context 'variable-documentation + "Variable containing the syntactic analysis list for a line of code. + +It is a list with one element for each syntactic symbol pertinent to the +line, for example \"((defun-block-intro 1) (comment-intro))\". + +It is dynamically bound when calling \(i) a brace hanging \"action +function\"; \(ii) a semicolon/comma hanging \"criteria function\"; \(iii) a +\"line-up function\"; \(iv) a c-special-indent-hook function. It is also +used internally by CC Mode. + +c-syntactic-context is always bound dynamically. It must NEVER be set +statically (e.g. with `setq').") + + +(cc-bytecomp-defvar c-syntactic-element) +(defvar c-syntactic-element) +(put 'c-syntactic-element 'variable-documentation + "Variable containing the current syntactic element during calls to +the lineup functions. The value is one of the elements in the list in +`c-syntactic-context' and is a list with the symbol name in the first +position, followed by zero or more elements containing any additional +info associated with the syntactic symbol. There are accessor functions +`c-langelem-sym', `c-langelem-pos', `c-langelem-col', and +`c-langelem-2nd-pos' to access the list. + +Specifically, the element returned by `c-langelem-pos' is the anchor +position, or nil if there isn't any. See the comments in the +`c-offsets-alist' variable and the CC Mode manual for more detailed info +about the data each syntactic symbol provides. + +This is always bound dynamically. It should never be set +statically (e.g. with `setq').") + +(defvar c-indentation-style nil + "Name of the currently installed style. +Don't change this directly; call `c-set-style' instead, or set the variable +`c-file-style' in the file's Local Variable list.") + +(defvar c-current-comment-prefix nil + "The current comment prefix regexp. +Set from `c-comment-prefix-regexp' at mode initialization.") +(make-variable-buffer-local 'c-current-comment-prefix) + +;; N.B. The next three variables are initialized in +;; c-setup-paragraph-variables. Their initializations here are "just in +;; case". ACM, 2004/2/15. They are NOT buffer local (yet?). +(defvar c-string-par-start +;; (concat "\\(" (default-value 'paragraph-start) "\\)\\|[ \t]*\\\\$") + "\f\\|[ \t]*\\\\?$" + "Value of paragraph-start used when scanning strings. +It treats escaped EOLs as whitespace.") + +(defvar c-string-par-separate + ;; (concat "\\(" (default-value 'paragraph-separate) "\\)\\|[ \t]*\\\\$") + "[ \t\f]*\\\\?$" + "Value of paragraph-separate used when scanning strings. +It treats escaped EOLs as whitespace.") + +(defvar c-sentence-end-with-esc-eol + (concat "\\(\\(" (c-default-value-sentence-end) "\\)" + ;; N.B.: "$" would be illegal when not enclosed like "\\($\\)". + "\\|" "[.?!][]\"')}]* ?\\\\\\($\\)[ \t\n]*" + "\\)") + "Value used like sentence-end used when scanning strings. +It treats escaped EOLs as whitespace.") + + +(cc-provide 'cc-vars) + +;;; arch-tag: d62e9a55-c9fe-409b-b5b6-050b6aa202c9 +;;; cc-vars.el ends here diff --git a/site-lisp/cc-mode/csharp-only/csharp-mode-0.8.6.el b/site-lisp/cc-mode/csharp-only/csharp-mode-0.8.6.el new file mode 100644 index 0000000..765722b --- /dev/null +++ b/site-lisp/cc-mode/csharp-only/csharp-mode-0.8.6.el @@ -0,0 +1,5911 @@ +;;; csharp-mode.el --- C# mode derived mode + +;; Author : Dylan R. E. Moonfire (original) +;; Maintainer : Dino Chiesa +;; Created : Feburary 2005 +;; Modified : May 2011 +;; Version : 0.8.6 +;; Keywords : c# languages oop mode +;; X-URL : http://code.google.com/p/csharpmode/ +;; Last-saved : <2011-May-21 20:28:30> + +;; +;; 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; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: +;; +;; This is a major mode for editing C# code. It performs automatic +;; indentation of C# syntax; font locking; and integration with compile.el; +;; flymake.el; yasnippet.el; and imenu.el. +;; +;; csharp-mode requires CC Mode 5.30 or later. It works with +;; cc-mode 5.31.3, which is current at this time. +;; +;; Features: +;; +;; - font-lock and indent of C# syntax including: +;; all c# keywords and major syntax +;; attributes that decorate methods, classes, fields, properties +;; enum types +;; #if/#endif #region/#endregion +;; instance initializers +;; anonymous functions and methods +;; verbatim literal strings (those that begin with @) +;; generics +;; +;; - automagic code-doc generation when you type three slashes. +;; +;; - intelligent insertion of matched pairs of curly braces. +;; +;; - compile tweaks. Infers the compile command from special comments +;; in the file header. Also, sets the regex for next-error, so that +;; compile.el can handle csc.exe output. +;; +;; - flymake integration +;; - select flymake command from code comments +;; - infer flymake command otherwise (presence of makefile, etc) +;; - Turn off query-on-exit-flag for the flymake process. +;; - define advice to flymake-goto-line , to allow it to goto the +;; appropriate column for the error on a given line. This works +;; with `flymake-goto-next-error' etc. +;; +;; - yasnippet integration +;; - preloaded snippets +;; +;; - imenu integration - generates an index of namespaces, classes, +;; interfaces, methods, and properties for easy navigation within +;; the buffer. +;; + + +;; Installation instructions +;; -------------------------------- +;; +;; Put csharp-mode.el somewhere in your load path, optionally byte-compile +;; it, and add the following to your .emacs file: +;; +;; (autoload 'csharp-mode "csharp-mode" "Major mode for editing C# code." t) +;; (setq auto-mode-alist +;; (append '(("\\.cs$" . csharp-mode)) auto-mode-alist)) +;; +;; +;; Optionally, define and register a mode-hook function. To do so, use +;; something like this in your .emacs file: +;; +;; (defun my-csharp-mode-fn () +;; "function that runs when csharp-mode is initialized for a buffer." +;; (turn-on-auto-revert-mode) +;; (setq indent-tabs-mode nil) +;; (require 'flymake) +;; (flymake-mode 1) +;; (require 'yasnippet) +;; (yas/minor-mode-on) +;; (require 'rfringe) +;; ...insert more code here... +;; ...including any custom key bindings you might want ... +;; ) +;; (add-hook 'csharp-mode-hook 'my-csharp-mode-fn t) +;; +;; +;; General +;; ---------------------------- +;; +;; Mostly C# mode will "just work." Use `describe-mode' to see the +;; default keybindings and the highlights of the mode. +;; +;; +;; Flymake Integration +;; ---------------------------- +;; +;; You can use flymake with csharp mode to automatically check the +;; syntax of your csharp code, and highlight errors. To do so, add a +;; comment line like this to each .cs file that you use flymake with: +;; +;; // flymake: c:\.net3.5\csc.exe /t:module /nologo /R:Foo.dll @@FILE@@ +;; +;; That lines specifies a command "stub". Flymake appends the name of +;; the file to compile, and then runs the command to check +;; syntax. Flymake assumes that syntax errors will be noted in the +;; output of the command in a form that fits one of the regexs in the +;; `compilation-error-regexp-alist-alist'. Check the flymake module for +;; more information on that. +;; +;; Some rules for the command: +;; +;; 1. it must appear all on a single line. +;; +;; 2. csharp-mode generally looks for the marker line in the first N +;; lines of the file, where N is set in +;; `csharp-cmd-line-limit'. See the documentation on that +;; variable for more information. +;; +;; 3. the command SHOULD use @@FILE@@ in place of the name of the +;; source file to be compiled, normally the file being edited. +;; This is because normally flymake saves a copy of the buffer +;; into a temporary file with a unique name, and then compiles +;; that temporary file. The token @@FILE@@ is replaced by +;; csharp-mode with the name of the temporary file created by +;; flymake, before invoking the command. +;; +;; 4. The command should include /R options specifying external +;; libraries that the code depends on. +;; +;; If you have no external dependencies, then you need not specify any +;; flymake command at all. csharp-mode will implicitly act as if you had +;; specified the command: +;; +;; // flymake: c:\.net3.5\csc.exe /t:module /nologo @@FILE@@ +;; +;; +;; If you use csc.exe as the syntax check tool (as almost everyone +;; will), the /t:module is important. csharp-mode assumes that the +;; syntax-check compile command will produce a file named +;; NAME.netmodule, which is the default when using /t:module. (Remember +;; than NAME is dynamically generated). csharp-mode will remove the +;; generated netmodule file after the syntax check is complete. If you +;; don't specify /t:module, then csharp-mode won't know what file to +;; delete. +;; +;; csharp-mode also fiddles with some other flymake things. In +;; particular it: adds .cs to the flymake "allowed filename masks"; +;; adds parsing for csc error messages; and adds advice to the error +;; parsing logic. This all should be pretty benign for all other +;; flymake buffers. But it might not be. +;; +;; You can explicitly turn the flymake integration for C# off by +;; setting `csharp-want-flymake-fixup' to nil. +;; +;; +;; Compile Integration +;; ---------------------------- +;; +;; csharp-mode binds the function `csharp-invoke-compile-interactively' +;; to "\C-x\C-e" . This function attempts to intellgently guess the +;; format of the compile command to use for a buffer. It looks in the +;; comments at the head of the buffer for a line that begins with +;; compile: . If found, csharp-mode suggests the text that follows as +;; the compilation command when running `compile' . If such a line is +;; not found, csharp-mode falls back to a msbuild or nmake command. +;; See the documentation on `csharp-cmd-line-limit' for further +;; information. +;; +;; Also, csharp-mode installs an error regexp for csc.exe into +;; `compilation-error-regexp-alist-alist', which allows `next-error' +;; and `previous-error' (defined in compile.el) to navigate to the next +;; and previous compile errors in the cs buffer, after you've run `compile'. +;; +;; +;; YASnippet integration +;; ----------------------------- +;; +;; csharp-mode defines some built-in snippets for +;; convenience. For example, if statements, for, foreach, and +;; so on. You can see them on the YASnippet menu that is displayed +;; when a csharp-mode buffer is opened. csharp-mode defines this +;; snippets happens only if ya-snippet is available. (It is done in an +;; `eval-after-load' clause.) The builtin snippets will not overwrite +;; snippets that use the same name, if they are defined in the normal +;; way (in a compiled bundle) with ya-snippet. +;; +;; You can explicitly turn off ya-snippet integration. See the var, +;; `csharp-want-yasnippet-fixup'. +;; +;; +;; imenu integration +;; ----------------------------- +;; +;; This should just work. For those who don't know what imenu is, it +;; allows navigation to different points within the file from an +;; "Index" menu, in the window's menubar. csharp-mode computes the +;; menu containing the namespaces, classes, methods, and so on, in the +;; buffer. This happens at the time the file is loaded; for large +;; files it takes a bit of time to complete the scan. If you don't +;; want this capability, set `csharp-want-imenu' to nil. +;; +;; + + +;;; Known Bugs: +;; +;; The imenu scan is text-based and naive. For example, if you +;; intersperse comments between the name of a class/method/namespace, +;; and the curly brace, the scan will not recognize the thing being +;; declared. This is fixable - would need to extract the buffer +;; substring then remove comments before doing the regexp checks - but +;; it would make the scan much slower. Also, the scan doesn't deal +;; with preproc symbol definitions and #if/#else. Those things are +;; invisible to the scanner csharp-mode uses to build the imenu menu. +;; +;; Leading identifiers are no longer being fontified, for some reason. +;; See matchers-before. (Not sure this is still a problem - 19 may +;; 2011 DPC) +;; +;; Method names with a preceding attribute are not fontified. +;; +;; The symbol followng #if is not fontified. It should be treated like +;; define and get font-lock-variable-name-face . +;; +;; This code doesn't seem to work when you compile it, then +;; load/require in the emacs file. You will get an error (error +;; "`c-lang-defconst' must be used in a file") which happens because +;; cc-mode doesn't think it is in a buffer while loading directly +;; from the init. However, if you call it based on a file extension, +;; it works properly. Interestingly enough, this doesn't happen if +;; you don't byte-compile cc-mode. +;; +;; +;; +;; Todo: +;; +;; imenu should scan for and find delegates and events, in addition +;; to the classes, structs, properties and methods it does currently. +;; +;; Get csharp-mode.el accepted as part of the emacs standard distribution. +;; Must contact monnier at iro.umontreal.ca to make this happen. +;; +;; Add refactoring capabilities? +;; - extract as method - extract a block of code into a method +;; - extract as Func<> - extract a block of code into an Action +;; +;; More code-gen power: +;; - interface implementation - I think would require csharp-shell +;; +;; +;; Acknowledgements: +;; +;; Thanks to Alan Mackenzie and Stefan Monnier for answering questions +;; and making suggestions. And to Trey Jackson for sharing his +;; knowledge of emacs lisp. +;; +;; + +;;; Versions: +;; +;; 0.1.0 - Initial release. +;; 0.2.0 - Fixed the identification on the "enum" keyword. +;; - Fixed the font-lock on the "base" keyword +;; 0.3.0 - Added a regex to fontify attributes. It isn't the +;; the best method, but it handles single-like attributes +;; well. +;; - Got "super" not to fontify as a keyword. +;; - Got extending classes and interfaces to fontify as something. +;; 0.4.0 - Removed the attribute matching because it broke more than +;; it fixed. +;; - Corrected a bug with namespace not being properly identified +;; and treating the class level as an inner object, which screwed +;; up formatting. +;; - Added "partial" to the keywords. +;; 0.5.0 - Found bugs with compiled cc-mode and loading from init files. +;; - Updated the eval-when-compile to code to let the mode be +;; compiled. +;; 0.6.0 - Added the c-filter-ops patch for 5.31.1 which made that +;; function in cc-langs.el unavailable. +;; - Added a csharp-lineup-region for indention #region and +;; #endregion block differently. +;; 0.7.0 - Added autoload so update-directory-autoloads works +;; (Thank you, Nikolaj Schumacher) +;; - Fontified the entire #region and #endregion lines. +;; - Initial work to get get, set, add, remove font-locked. +;; 0.7.1 - Added option to indent #if/endif with code +;; - Fixed c-opt-cpp-prefix defn (it must not include the BOL +;; char (^). +;; - proper fontification and indent of classes that inherit +;; (previously the colon was confusing the parser) +;; - reclassified namespace as a block beginner +;; - removed $ as a legal symbol char - not legal in C#. +;; - added struct to c-class-decl-kwds so indent is correct +;; within a struct. +;; 0.7.2 - Added automatic codedoc insertion. +;; 0.7.3 - Instance initializers (new Type { ... } ) and +;; (new Type() { ...} ) are now indented properly. +;; - proper fontification and indent of enums as brace-list-*, +;; including special treatment for enums that explicitly +;; inherit from an int type. Previously the colon was +;; confusing the parser. +;; - proper fontification of verbatim literal strings, +;; including those that end in slash. This edge case was not +;; handled at all before; it is now handled correctly. +;; - code cleanup and organization; removed the formfeed. +;; - intelligent curly-brace insertion with +;; `csharp-insert-open-brace' +;; 0.7.4 - added a C# style +;; - using is now a keyword and gets fontified correctly +;; - fixed a bug that had crept into the codedoc insertion. +;; 0.7.5 - now fontify namespaces in the using statements. This is +;; done in the csharp value for c-basic-matchers-before . +;; - also fontify the name following namespace decl. +;; This is done in the csharp value for c-basic-matchers-after . +;; - turn on recognition of generic types. They are now +;; fontified correctly. +;; - <> are now treated as syntactic parens and can be jumped +;; over with c-forward-sexp. +;; - Constructors are now fontified. +;; - Field/Prop names inside object initializers are now fontified. +;; +;; 0.7.7 - relocate running c-run-mode-hooks to the end of +;; csharp-mode, to allow user to modify key bindings in a +;; hook if he doesn't like the defaults. +;; +;; 0.7.8 - redefine csharp-log to insert timestamp. +;; - Fix byte-compile errors on emacs 23.2 ? Why was +;; c-filter-ops duplicated here? What was the purpose of its +;; presence here, I am not clear. +;; +;; 0.8.0 - include flymake magic into this module. +;; - include yasnippet integration +;; +;; 0.8.2 2011 April DPC +;; - small tweaks; now set a one-time bool for flymake installation +;; - some doc updates on flymake +;; +;; 0.8.3 2011 May 17 DPC +;; - better help on csharp-mode +;; - csharp-move-* functions for manual navigation. +;; - imenu integration for menu-driven navigation - navigate to +;; named methods, classes, etc. +;; - adjusted the flymake regexp to handle output from fxcopcmd, +;; and extended the help to provide examples how to use this. +;; +;; 0.8.4 DPC 2011 May 18 +;; - fix a basic bug in the `csharp-yasnippet-fixup' fn. +;; +;; 0.8.5 DPC 2011 May 21 +;; - imenu: correctly parse Properties that are part of an +;; explicitly specified interface. Probably need to do this +;; for methods, too. +;; - fontify the optional alias before namespace in a using (import). +;; - Tweak open-curly magic insertion for object initializers. +;; - better fontification of variables and references +;; - "sealed" is now fontified as a keyword +;; - imenu: correctly index ctors that call this or base. +;; - imenu: correctly index Extension methods (this System.Enum e) +;; - imenu: correctly scan method params tagged with out, ref, params +;; - imenu scan: now handle curlies within strings. +;; - imenu: split menus now have better labels, are sorted correctly. +;; +;; 0.8.6 DPC 2011 May ?? +;; - + + +(require 'cc-mode) + +(message (concat "Loading " load-file-name)) + + +;; ================================================================== +;; c# upfront stuff +;; ================================================================== + +;; This is a copy of the function in cc-mode which is used to handle the +;; eval-when-compile which is needed during other times. +;; +;; NB: I think this is needed to satisfy requirements when this module +;; calls `c-lang-defconst'. (DPC) + +;; (defun c-filter-ops (ops opgroup-filter op-filter &optional xlate) +;; ;; See cc-langs.el, a direct copy. +;; (unless (listp (car-safe ops)) +;; (setq ops (list ops))) +;; (cond ((eq opgroup-filter t) +;; (setq opgroup-filter (lambda (opgroup) t))) +;; ((not (functionp opgroup-filter)) +;; (setq opgroup-filter `(lambda (opgroup) +;; (memq opgroup ',opgroup-filter))))) +;; (cond ((eq op-filter t) +;; (setq op-filter (lambda (op) t))) +;; ((stringp op-filter) +;; (setq op-filter `(lambda (op) +;; (string-match ,op-filter op))))) +;; (unless xlate +;; (setq xlate 'identity)) +;; (c-with-syntax-table (c-lang-const c-mode-syntax-table) +;; (delete-duplicates +;; (mapcan (lambda (opgroup) +;; (when (if (symbolp (car opgroup)) +;; (when (funcall opgroup-filter (car opgroup)) +;; (setq opgroup (cdr opgroup)) +;; t) +;; t) +;; (mapcan (lambda (op) +;; (when (funcall op-filter op) +;; (let ((res (funcall xlate op))) +;; (if (listp res) res (list res))))) +;; opgroup))) +;; ops) +;; :test 'equal))) + + + +;; These are only required at compile time to get the sources for the +;; language constants. (The load of cc-fonts and the font-lock +;; related constants could additionally be put inside an +;; (eval-after-load "font-lock" ...) but then some trickery is +;; necessary to get them compiled.) + +(eval-when-compile + (let ((load-path + (if (and (boundp 'byte-compile-dest-file) + (stringp byte-compile-dest-file)) + (cons (file-name-directory byte-compile-dest-file) load-path) + load-path))) + (load "cc-mode" nil t) + (load "cc-fonts" nil t) + (load "cc-langs" nil t))) + +(eval-and-compile + ;; Make our mode known to the language constant system. Use Java + ;; mode as the fallback for the constants we don't change here. + ;; This needs to be done also at compile time since the language + ;; constants are evaluated then. + (c-add-language 'csharp-mode 'java-mode)) + +;; ================================================================== +;; end of c# upfront stuff +;; ================================================================== + + + + + +;; ================================================================== +;; constants used in this module +;; ================================================================== + +;;(error (byte-compile-dest-file)) +;;(error (c-get-current-file)) + +(defconst csharp-aspnet-directive-re + "<%@.+?%>" + "Regex for matching directive blocks in ASP.NET files (.aspx, .ashx, .ascx)") + + +(defconst csharp-enum-decl-re + (concat + "\\ + +Providing this function allows the indenting in csharp-mode +to work properly with code that includes attributes and ASPNET +directives. + +" + (save-excursion + (let ((pos-or-point (progn (if pos (goto-char pos)) (point)))) + + (cond + + ;; before open curly in object initializer. new Foo* { } + ((and (looking-back + (concat "\\ + ((looking-back (concat csharp-aspnet-directive-re "$") nil t) + t) + + ;; put a vsemi after an attribute, as with + ;; [XmlElement] + ;; Except when the attribute is used within a line of code, as + ;; specifying something for a parameter. + ((c-safe (backward-sexp) t) + (cond + ((re-search-forward + (concat + "\\(\\[" + "[ \t\n\r\f\v]*" + "\\(" + "\\(?:[A-Za-z_][[:alnum:]]*\\.\\)*" + "[A-Za-z_][[:alnum:]]*" + "\\)" + "[^]]*\\]\\)" + ) + (1+ pos-or-point) t) + + (c-safe (backward-sexp)) + (c-backward-syntactic-ws) + (cond + + ((eq (char-before) 93) ;; close sq brace (a previous attribute) + (csharp--at-vsemi-p (point))) ;; recurse + + ((or + (eq (char-before) 59) ;; semicolon + (eq (char-before) 123) ;; open curly + (eq (char-before) 125)) ;; close curly + t) + + ;; attr is used within a line of code + (t nil))) + + (t nil))) + + (t nil)) + ))) + + + + +(defun csharp-lineup-region (langelem) + "Indent all #region and #endregion blocks inline with code while +retaining normal column-zero indention for #if and the other +processing blocks. + +To use this indenting just put the following in your emacs file: + (c-set-offset 'cpp-macro 'csharp-lineup-region) + +An alternative is to use `csharp-lineup-if-and-region'. +" + + (save-excursion + (back-to-indentation) + (if (re-search-forward "#\\(end\\)?region" (c-point 'eol) [0]) 0 [0]))) + + + + + +(defun csharp-lineup-if-and-region (langelem) + +"Indent all #region/endregion blocks and #if/endif blocks inline +with code while retaining normal column-zero indention for any +other processing blocks. + +To use this indenting just put the following in your emacs file: + (c-set-offset 'cpp-macro 'csharp-lineup-if-and-region) + +Another option is to use `csharp-lineup-region'. + +" + (save-excursion + (back-to-indentation) + (if (re-search-forward "#\\(\\(end\\)?\\(if\\|region\\)\\|else\\)" (c-point 'eol) [0]) 0 [0]))) + + + + + (defun csharp-in-literal (&optional lim detect-cpp) + "Return the type of literal point is in, if any. +Basically this works like `c-in-literal' except it doesn't +use or fill the cache (`c-in-literal-cache'). + +The return value is a symbol: `c' if in a C-style comment, `c++' +if in a C++ style comment, `string' if in a string literal, +`pound' if DETECT-CPP is non-nil and in a preprocessor line, or +nil if somewhere else. Optional LIM is used as the backward +limit of the search. If omitted, or nil, `c-beginning-of-syntax' +is used. + +Note that this function might do hidden buffer changes. See the +comment at the start of cc-engine.el for more info." + + (let ((rtn + (save-excursion + (let* ((pos (point)) + (lim (or lim (progn + (c-beginning-of-syntax) + (point)))) + (state (parse-partial-sexp lim pos))) + (csharp-log 4 "parse lim(%d) state: %s" lim (prin1-to-string state)) + (cond + ((elt state 3) + (csharp-log 4 "in literal string (%d)" pos) + 'string) + ((elt state 4) + (csharp-log 4 "in literal comment (%d)" pos) + (if (elt state 7) 'c++ 'c)) + ((and detect-cpp (c-beginning-of-macro lim)) 'pound) + (t nil)))))) + rtn)) + + + +(defun csharp-insert-open-brace () + "Intelligently insert a pair of curly braces. This fn should be +bound to the open-curly brace, with + + (local-set-key (kbd \"{\") 'csharp-insert-open-brace) + +The default binding for an open curly brace in cc-modes is often +`c-electric-brace' or `skeleton-pair-insert-maybe'. The former +can be configured to insert newlines around braces in various +syntactic positions. The latter inserts a pair of braces and +then does not insert a newline, and does not indent. + +This fn provides another option, with some additional +intelligence for csharp-mode. When you type an open curly, the +appropriate pair of braces appears, with spacing and indent set +in a context-sensitive manner: + + - Within a string literal, you just get a pair of braces, and + point is set between them. This works for String.Format() + purposes. + + - Following = or [], as in an array assignment, you get a pair + of braces, with two intervening spaces, with a semincolon + appended. Point is left between the braces. + + - Following \"new Foo\", it's an object initializer. You get: + newline, open brace, newline, newline, close, semi. Point is + left on the blank line between the braces. Unless the object + initializer is within an array initializer, in which case, no + newlines, and the semi is replaced with a comma. (Try it to + see what this means). + + - Following => , implying a lambda, you get an open/close pair, + with two intervening spaces, no semicolon, and point on the + 2nd space. + + - Otherwise, you get a newline, the open curly, followed by + an empty line and the closing curly on the line following, + with point on the empty line. + + +There may be another way to get this to happen appropriately just +within emacs, but I could not figure out how to do it. So I +wrote this alternative. + + " + (interactive) + (let + (tpoint + (in-string (string= (csharp-in-literal) "string")) + (preceding3 + (save-excursion + (and + (skip-chars-backward " \t") + (> (- (point) 2) (point-min)) + (buffer-substring-no-properties (point) (- (point) 3))))) + (one-word-back + (save-excursion + (backward-word 2) + (thing-at-point 'word)))) + + (cond + + ;; Case 1: inside a string literal? + ;; -------------------------------------------- + ;; If so, then just insert a pair of braces and put the point + ;; between them. The most common case is a format string for + ;; String.Format() or Console.WriteLine(). + (in-string + (self-insert-command 1) + (insert "}") + (backward-char)) + + ;; Case 2: the open brace starts an array initializer. + ;; -------------------------------------------- + ;; When the last non-space was an equals sign or square brackets, + ;; then it's an initializer. + ((save-excursion + (and (c-safe (backward-sexp) t) + (looking-at "\\(\\w+\\b *=\\|[[]]+\\)"))) + (self-insert-command 1) + (insert " };") + (backward-char 3)) + + ;; Case 3: the open brace starts an instance initializer + ;; -------------------------------------------- + ;; If one-word-back was "new", then it's an object initializer. + ((string= one-word-back "new") + (csharp-log 2 "object initializer") + (setq tpoint (point)) ;; prepare to indent-region later + (backward-word 2) + (c-backward-syntactic-ws) + (if (or (eq (char-before) ?,) ;; comma + (and (eq (char-before) 123) ;; open curly + (progn (backward-char) + (c-backward-syntactic-ws) + (looking-back "\\[\\]")))) + (progn + ;; within an array - emit no newlines + (goto-char tpoint) + (self-insert-command 1) + (insert " },") + (backward-char 3)) + + (progn + (goto-char tpoint) + (newline) + (self-insert-command 1) + (newline-and-indent) + (newline) + (insert "};") + (c-indent-region tpoint (point)) + (forward-line -1) + (indent-according-to-mode) + (end-of-line)))) + + + ;; Case 4: a lambda initialier. + ;; -------------------------------------------- + ;; If the open curly follows =>, then it's a lambda initializer. + ((string= (substring preceding3 -2) "=>") + (csharp-log 2 "lambda init") + (self-insert-command 1) + (insert " }") + (backward-char 2)) + + ;; else, it's a new scope. (if, while, class, etc) + (t + (save-excursion + (csharp-log 2 "new scope") + (set-mark (point)) ;; prepare to indent-region later + ;; check if the prior sexp is on the same line + (if (save-excursion + (let ((curline (line-number-at-pos)) + (aftline (progn + (if (c-safe (backward-sexp) t) + (line-number-at-pos) + -1)))) + (= curline aftline))) + (newline-and-indent)) + (self-insert-command 1) + (c-indent-line-or-region) + (end-of-line) + (newline) + (insert "}") + ;;(c-indent-command) ;; not sure of the difference here + (c-indent-line-or-region) + (forward-line -1) + (end-of-line) + (newline-and-indent) + ;; point ends up on an empty line, within the braces, properly indented + (setq tpoint (point))) + + (goto-char tpoint))))) + + +;; ================================================================== +;; end of csharp-mode utility and feature defuns +;; ================================================================== + + + +;; ================================================================== +;; c# values for "language constants" defined in cc-langs.el +;; ================================================================== + +(c-lang-defconst c-at-vsemi-p-fn + csharp 'csharp--at-vsemi-p) + + +;; This c-opt-after-id-concat-key is a regexp that matches +;; dot. In other words: "\\(\\.\\)" +;; Not sure why this needs to be so complicated. +;; This const is now internal (obsolete); need to move to +;; c-after-id-concat-ops. I don't yet understand the meaning +;; of that variable, so for now. . . . + +;; (c-lang-defconst c-opt-after-id-concat-key +;; csharp (if (c-lang-const c-opt-identifier-concat-key) +;; (c-lang-const c-symbol-start))) + +(c-lang-defconst c-opt-after-id-concat-key + csharp "[[:alpha:]_]" ) + + + + +;; The matchers elements can be of many forms. It gets pretty +;; complicated. Do a describe-variable on font-lock-keywords to get a +;; description. (Why on font-lock-keywords? I don't know, but that's +;; where you get the help.) +;; +;; Aside from the provided documentation, the other option of course, is +;; to look in the source code as an example for what to do. The source +;; in cc-fonts uses a defun c-make-font-lock-search-function to produce +;; most of the matchers. Called this way: +;; +;; (c-make-font-lock-search-function regexp '(A B c)) +;; +;; The REGEXP is used in re-search-forward, and if there's a match, then +;; A is called within a save-match-data. If B and C are non-nil, they +;; are called as pre and post blocks, respecitvely. +;; +;; Anyway the c-make-font-lock-search-function works for a single regex, +;; but more complicated scenarios such as those intended to match and +;; fontify object initializers, call for a hand-crafted lambda. +;; +;; The object initializer is special because matching on it must +;; allow nesting. +;; +;; In c#, the object initializer block is used directly after a +;; constructor, like this: +;; +;; new MyType +;; { +;; Prop1 = "foo" +;; } +;; +;; csharp-mode needs to fontify the properties in the +;; initializer block in font-lock-variable-name-face. The key thing is +;; to set the text property on the open curly, using type c-type and +;; value c-decl-id-start. This apparently allows `parse-partial-sexp' to +;; do the right thing, later. +;; +;; This simple case is easy to handle in a regex, using the basic +;; `c-make-font-lock-search-function' form. But the general syntax for a +;; constructor + object initializer in C# is more complex: +;; +;; new MyType(..arglist..) { +;; Prop1 = "foo" +;; } +;; +;; A simple regex match won't satisfy here, because the ..arglist.. can +;; be anything, including calls to other constructors, potentially with +;; object initializer blocks. This may nest arbitrarily deeply, and the +;; regex in emacs doesn't support balanced matching. Therefore there's +;; no way to match on the "outside" pair of parens, to find the relevant +;; open curly. What's necessary is to do the match on "new MyType" then +;; skip over the sexp defined by the parens, then set the text property on +;; the appropriate open-curly. +;; +;; To make that happen, it's good to have insight into what the matcher +;; really does. The output of `c-make-font-lock-search-function' before +;; byte-compiling, is: +;; +;; (lambda (limit) +;; (let ((parse-sexp-lookup-properties +;; (cc-eval-when-compile +;; (boundp 'parse-sexp-lookup-properties)))) +;; (while (re-search-forward REGEX limit t) +;; (unless +;; (progn +;; (goto-char (match-beginning 0)) +;; (c-skip-comments-and-strings limit)) +;; (goto-char (match-end 0)) +;; (progn +;; B +;; (save-match-data A) +;; C )))) +;; nil) +;; +;; csharp-mode uses this hand-crafted form of a matcher to handle the +;; general case for constructor + object initializer, within +;; `c-basic-matchers-after' . +;; + + + + +;; (defun c-make-font-lock-search-function (regexp &rest highlights) +;; ;; This function makes a byte compiled function that works much like +;; ;; a matcher element in `font-lock-keywords'. It cuts out a little +;; ;; bit of the overhead compared to a real matcher. The main reason +;; ;; is however to pass the real search limit to the anchored +;; ;; matcher(s), since most (if not all) font-lock implementations +;; ;; arbitrarily limits anchored matchers to the same line, and also +;; ;; to insulate against various other irritating differences between +;; ;; the different (X)Emacs font-lock packages. +;; ;; +;; ;; REGEXP is the matcher, which must be a regexp. Only matches +;; ;; where the beginning is outside any comment or string literal are +;; ;; significant. +;; ;; +;; ;; HIGHLIGHTS is a list of highlight specs, just like in +;; ;; `font-lock-keywords', with these limitations: The face is always +;; ;; overridden (no big disadvantage, since hits in comments etc are +;; ;; filtered anyway), there is no "laxmatch", and an anchored matcher +;; ;; is always a form which must do all the fontification directly. +;; ;; `limit' is a variable bound to the real limit in the context of +;; ;; the anchored matcher forms. +;; ;; +;; ;; This function does not do any hidden buffer changes, but the +;; ;; generated functions will. (They are however used in places +;; ;; covered by the font-lock context.) +;; +;; ;; Note: Replace `byte-compile' with `eval' to debug the generated +;; ;; lambda easier. +;; (byte-compile +;; `(lambda (limit) +;; (let (;; The font-lock package in Emacs is known to clobber +;; ;; `parse-sexp-lookup-properties' (when it exists). +;; (parse-sexp-lookup-properties +;; (cc-eval-when-compile +;; (boundp 'parse-sexp-lookup-properties)))) +;; (while (re-search-forward ,regexp limit t) +;; (unless (progn +;; (goto-char (match-beginning 0)) +;; (c-skip-comments-and-strings limit)) +;; (goto-char (match-end 0)) +;; ,@(mapcar +;; (lambda (highlight) +;; (if (integerp (car highlight)) +;; (progn +;; (unless (eq (nth 2 highlight) t) +;; (error +;; "The override flag must currently be t in %s" +;; highlight)) +;; (when (nth 3 highlight) +;; (error +;; "The laxmatch flag may currently not be set in %s" +;; highlight)) +;; `(save-match-data +;; (c-put-font-lock-face +;; (match-beginning ,(car highlight)) +;; (match-end ,(car highlight)) +;; ,(elt highlight 1)))) +;; (when (nth 3 highlight) +;; (error "Match highlights currently not supported in %s" +;; highlight)) +;; `(progn +;; ,(nth 1 highlight) +;; (save-match-data ,(car highlight)) +;; ,(nth 2 highlight)))) +;; highlights)))) +;; nil)) +;; ) + + +(c-lang-defconst c-basic-matchers-before + csharp `( + ;;;; Font-lock the attributes by searching for the + ;;;; appropriate regex and marking it as TODO. + ;;,`(,(concat "\\(" csharp-attribute-regex "\\)") + ;; 0 font-lock-function-name-face) + + ;; Put a warning face on the opener of unclosed strings that + ;; can't span lines. Later font + ;; lock packages have a `font-lock-syntactic-face-function' for + ;; this, but it doesn't give the control we want since any + ;; fontification done inside the function will be + ;; unconditionally overridden. + ,(c-make-font-lock-search-function + ;; Match a char before the string starter to make + ;; `c-skip-comments-and-strings' work correctly. + (concat ".\\(" c-string-limit-regexp "\\)") + '((c-font-lock-invalid-string))) + + + ;; Fontify keyword constants. + ,@(when (c-lang-const c-constant-kwds) + (let ((re (c-make-keywords-re nil + (c-lang-const c-constant-kwds)))) + `((eval . (list ,(concat "\\<\\(" re "\\)\\>") + 1 c-constant-face-name))))) + + + ;; Fontify the namespaces that follow using statements. + ;; This regex handles the optional alias, as well. + ,`(,(concat + "\\<\\(using\\)[ \t\n\f\v\r]+" + "\\(?:" + "\\([A-Za-z_][[:alnum:]]*\\)" + "[ \t\n\f\v\r]*=" + "[ \t\n\f\v\r]*" + "\\)?" + "\\(\\(?:[A-Za-z_][[:alnum:]]*\\.\\)*[A-Za-z_][[:alnum:]]*\\)" + "[ \t\n\f\v\r]*;") + (2 font-lock-constant-face t t) + (3 font-lock-constant-face)) + + + ;; Fontify all keywords except the primitive types. + ,`(,(concat "\\<" (c-lang-const c-regular-keywords-regexp)) + 1 font-lock-keyword-face) + + + ;; Fontify leading identifiers as a reference? in fully + ;; qualified names like "Foo.Bar". + ,@(when (c-lang-const c-opt-identifier-concat-key) + `((,(byte-compile + `(lambda (limit) + (csharp-log 3 "bmb reference? p(%d) L(%d)" (point) limit) + (while (re-search-forward + ,(concat "\\(\\<" ;; 1 + "\\(" ;; 2 + ;;"[A-Z]";; uppercase - assume upper = classname + "[A-Za-z_]" ;; any old + "[A-Za-z0-9_]*" ;; old: (c-lang-const c-symbol-key) + "\\)" + "[ \t\n\r\f\v]*" + "\\." ;;(c-lang-const c-opt-identifier-concat-key) + "[ \t\n\r\f\v]*" + "\\)" ;; 1 ends + "\\(" + "[[:alpha:]_][A-Za-z0-9_]*" ;; start of another symbolname + "\\)" ;; 3 ends + ) + limit t) + (csharp-log 3 "bmb ref? B(%d)" (match-beginning 0)) + (unless (progn + (goto-char (match-beginning 0)) + (c-skip-comments-and-strings limit)) + (let* ((prefix (match-string 2)) + (me1 (match-end 1)) + (first-char (string-to-char prefix)) + (is-upper (and (>= first-char 65) + (<= first-char 90)))) + (csharp-log 3 " - class/intf ref (%s)" prefix) + ;; only put face if not there already + (or (get-text-property (match-beginning 2) 'face) + (c-put-font-lock-face (match-beginning 2) + (match-end 2) + (if is-upper + font-lock-type-face ;; it's a type! + font-lock-variable-name-face))) + + (goto-char (match-end 3)) + (c-forward-syntactic-ws limit) + + ;; now, maybe fontify the thing afterwards, too + (let ((c (char-after))) + (csharp-log 3 " - now lkg at c(%c)" c) + + (cond + + ((= c 40) ;; open paren + (or (get-text-property (match-beginning 3) 'face) + (c-put-font-lock-face (match-beginning 3) + (match-end 3) + font-lock-function-name-face)) + (goto-char (match-end 3))) + + ;; these all look like variables or properties + ((or (= c 59) ;; semicolon + (= c 91) ;; open sq brack + (= c 41) ;; close paren + (= c 44) ;; , + (= c 33) ;; ! + (= c 124) ;; | + (= c 61) ;; = + (= c 43) ;; + + (= c 45) ;; - + (= c 42) ;; * + (= c 47)) ;; / + (or (get-text-property (match-beginning 3) 'face) + (c-put-font-lock-face (match-beginning 3) + (match-end 3) + font-lock-variable-name-face)) + (goto-char (match-end 3))) + + (t + (goto-char (match-end 1))))))))))))) + + )) + + + +(c-lang-defconst c-basic-matchers-after + csharp `( + + ;; option 1: + ;; ,@(when condition + ;; `((,(byte-compile + ;; `(lambda (limit) ... + ;; + ;; option 2: + ;; ,`((lambda (limit) ... + ;; + ;; I don't know how to avoid the (when condition ...) in the + ;; byte-compiled version. + ;; + ;; X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+ + + ;; Case 1: invocation of constructor + maybe an object + ;; initializer. Some possible examples that satisfy: + ;; + ;; new Foo (); + ;; + ;; new Foo () { }; + ;; + ;; new Foo { }; + ;; + ;; new Foo { Prop1= 7 }; + ;; + ;; new Foo { + ;; Prop1= 7 + ;; }; + ;; + ;; new Foo { + ;; Prop1= 7, + ;; Prop2= "Fred" + ;; }; + ;; + ;; new Foo { + ;; Prop1= new Bar() + ;; }; + ;; + ;; new Foo { + ;; Prop1= new Bar { PropA = 5.6F } + ;; }; + ;; + ,@(when t + `((,(byte-compile + `(lambda (limit) + (let ((parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + + (while (re-search-forward + ,(concat "\\ or {} or nothing (semicolon, comma). + + ;; fontify the typename + (c-put-font-lock-face (match-beginning 1) + (match-end 1) + 'font-lock-type-face) + + (goto-char (match-end 0)) + (c-forward-syntactic-ws limit) + (if (eq (char-after) ?<) ;; ctor for generic type + (progn + (csharp-log 3 " - this is a generic type") + ;; skip over <> safely + (c-safe (c-forward-sexp 1) t) + (c-forward-syntactic-ws))) + + ;; now, could be [] or (..) or {..} or semicolon. + + (csharp-log 3 " - looking for sexp") + + (if (or + (eq (char-after) ?{) ;; open curly + (and (eq (char-after) 91) ;; open square + (while (eq (char-after) 91) + (c-safe (c-forward-sexp 1))) + (eq (char-before) 93)) ;; close square + (and (eq (char-after) 40) ;; open paren + (c-safe (c-forward-sexp 1) t))) + + (progn + ;; at this point we've jumped over any intervening s-exp, + ;; like sq brackets or parens. + (c-forward-syntactic-ws) + (csharp-log 3 " - after fwd-syn-ws point(%d)" (point)) + (csharp-log 3 " - next char: %c" (char-after)) + (if (eq (char-after) ?{) + (let ((start (point)) + (end (if (c-safe (c-forward-sexp 1) t) + (point) 0))) + (csharp-log 3 " - open curly gets c-decl-id-start %d" start) + (c-put-char-property start + 'c-type + 'c-decl-id-start) + (goto-char start) + (if (> end start) + (progn + (forward-char 1) ;; step over open curly + (c-forward-syntactic-ws) + (while (> end (point)) + ;; now, try to fontify/assign variables to any properties inside the curlies + (csharp-log 3 " - inside open curly point(%d)" (point)) + (csharp-log 3 " - next char: %c" (char-after)) + ;; fontify each property assignment + (if (re-search-forward + (concat "\\(" (c-lang-const c-symbol-key) "\\)\\s*=") + end t) + (progn + (csharp-log 3 " - found variable %d-%d" + (match-beginning 1) + (match-end 1)) + (c-put-font-lock-face (match-beginning 1) + (match-end 1) + 'font-lock-variable-name-face) + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + ;; advance to the next assignment, if possible + (if (eq (char-after) ?@) + (forward-char 1)) + + (if (c-safe (c-forward-sexp 1) t) + (progn + (forward-char 1) + (c-forward-syntactic-ws)))) + + ;; else + (csharp-log 3 " - no more assgnmts found") + (goto-char end))))) + ))))) + + (goto-char (match-end 0)) + ))) + nil)) + ))) + + + ;; Case 2: declaration of enum with or without an explicit + ;; base type. + ;; + ;; Examples: + ;; + ;; public enum Foo { ... } + ;; + ;; public enum Foo : uint { ... } + ;; + ,@(when t + `((,(byte-compile + `(lambda (limit) + (let ((parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + (while (re-search-forward + ,(concat csharp-enum-decl-re + "[ \t\n\r\f\v]*" + "{") + limit t) + + (csharp-log 3 "enum? at %d" (match-beginning 0)) + + (unless + (progn + (goto-char (match-beginning 0)) + (c-skip-comments-and-strings limit)) + (progn + (save-match-data + (goto-char (match-end 0)) + (c-put-char-property (1- (point)) + 'c-type + 'c-decl-id-start) + (c-forward-syntactic-ws)) + (save-match-data + (c-font-lock-declarators limit t nil)) + (goto-char (match-end 0)) + ) + ))) + nil)) + ))) + + + ;; Case 3: declaration of constructor + ;; + ;; Example: + ;; + ;; private Foo(...) {...} + ;; + ,@(when t + `((,(byte-compile + `(lambda (limit) + (let ((parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties))) + (found-it nil)) + (while (re-search-forward + ,(concat + "^[ \t\n\r\f\v]*" + "\\(\\<\\(public\\|private\\|protected\\)\\)?[ \t\n\r\f\v]+" + "\\(@?[[:alpha:]_][[:alnum:]_]*\\)" ;; name of constructor + "[ \t\n\r\f\v]*" + "\\(" + "(" + "\\)") + limit t) + + (unless + (progn + (goto-char (match-beginning 0)) + (c-skip-comments-and-strings limit)) + + (goto-char (match-end 0)) + + (csharp-log 3 "ctor decl? L(%d) B(%d) E(%d)" + limit (match-beginning 0) (point)) + + (backward-char 1) ;; just left of the open paren + (save-match-data + ;; Jump over the parens, safely. + ;; If it's an unbalanced paren, no problem, + ;; do nothing. + (if (c-safe (c-forward-sexp 1) t) + (progn + (c-forward-syntactic-ws) + (cond + + ;; invokes base or this constructor. + ((re-search-forward + ,(concat + "\\(:[ \t\n\r\f\v]*\\(base\\|this\\)\\)" + "[ \t\n\r\f\v]*" + "(" + ) + limit t) + (csharp-log 3 " - ctor with dependency?") + + (goto-char (match-end 0)) + (backward-char 1) ;; just left of the open paren + (csharp-log 3 " - before paren at %d" (point)) + + (if (c-safe (c-forward-sexp 1) t) + (progn + (c-forward-syntactic-ws) + (csharp-log 3 " - skipped over paren pair %d" (point)) + (if (eq (char-after) ?{) + (setq found-it t))))) + + ;; open curly. no depedency on other ctor. + ((eq (char-after) ?{) + (csharp-log 3 " - no dependency, curly at %d" (point)) + (setq found-it t))) + + ))) + + (if found-it + ;; fontify the constructor symbol + (c-put-font-lock-face (match-beginning 3) + (match-end 3) + 'font-lock-function-name-face)) + (goto-char (match-end 0))))) + nil))))) + + + ;; Case 4: using clause. Without this, using (..) gets fontified as a fn. + ,@(when t + `((,(byte-compile + `(lambda (limit) + (let ((parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + (while (re-search-forward + ,(concat "\\<\\(using\\)" + "[ \t\n\r\f\v]*" + "(") + limit t) + + (csharp-log 3 "using clause p(%d)" (match-beginning 0)) + + (unless + (progn + (goto-char (match-beginning 0)) + (c-skip-comments-and-strings limit)) + + (save-match-data + (c-put-font-lock-face (match-beginning 1) + (match-end 1) + 'font-lock-keyword-face) + (goto-char (match-end 0)))))) + nil)) + ))) + + ;; Case 5: attributes + ,`((lambda (limit) + (let ((parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + + (while (re-search-forward + ,(concat "[ \t\n\r\f\v]+" + "\\(\\[" + "[ \t\n\r\f\v]*" + "\\(?:\\(?:return\\|assembly\\)[ \t]*:[ \t]*\\)?" + "\\(" + "\\(?:[A-Za-z_][[:alnum:]]*\\.\\)*" + "[A-Za-z_][[:alnum:]]*" + "\\)" + "[^]]*\\]\\)" + ) + limit t) + + (csharp-log 3 "attribute? - %d limit(%d)" (match-beginning 1) + limit) + + (unless + (progn + (goto-char (match-beginning 1)) + (c-skip-comments-and-strings limit)) + + (let ((b2 (match-beginning 2)) + (e2 (match-end 2)) + (is-attr nil)) + (csharp-log 3 " - type match: %d - %d" + b2 e2) + (save-match-data + (c-backward-syntactic-ws) + (setq is-attr (or + (eq (char-before) 59) ;; semicolon + (eq (char-before) 93) ;; close square brace + (eq (char-before) 123) ;; open curly + (eq (char-before) 125) ;; close curly + (save-excursion + (c-beginning-of-statement-1) + (looking-at + "#\\(pragma\\|endregion\\|region\\|if\\|else\\|endif\\)")) + ))) + + (if is-attr + (progn + (if (<= 3 csharp-log-level) + (csharp-log 3 " - attribute: '%s'" + (buffer-substring-no-properties b2 e2))) + (c-put-font-lock-face b2 e2 'font-lock-type-face))))) + (goto-char (match-end 0)) + )) + nil)) + + + ;; Case 6: directive blocks for .aspx/.ashx/.ascx + ,`((lambda (limit) + (let ((parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)))) + + (while (re-search-forward csharp-aspnet-directive-re limit t) + (csharp-log 3 "aspnet template? - %d limit(%d)" (match-beginning 1) + limit) + + (unless + (progn + (goto-char (match-beginning 0)) + (c-skip-comments-and-strings limit)) + + (save-match-data + (let ((end-open (+ (match-beginning 0) 3)) + (beg-close (- (match-end 0) 2))) + (c-put-font-lock-face (match-beginning 0) + end-open + 'font-lock-preprocessor-face) + + (c-put-font-lock-face beg-close + (match-end 0) + 'font-lock-preprocessor-face) + + ;; fontify within the directive + (while (re-search-forward + ,(concat + "\\(" + (c-lang-const c-symbol-key) + "\\)" + "=?" + ) + beg-close t) + + (c-put-font-lock-face (match-beginning 1) + (match-end 1) + 'font-lock-keyword-face) + (c-skip-comments-and-strings beg-close)) + )) + (goto-char (match-end 0))))) + nil)) + + +;; ;; Case 5: #if +;; ,@(when t +;; `((,(byte-compile +;; `(lambda (limit) +;; (let ((parse-sexp-lookup-properties +;; (cc-eval-when-compile +;; (boundp 'parse-sexp-lookup-properties)))) +;; (while (re-search-forward +;; "\\<\\(#if\\)[ \t\n\r\f\v]+\\([A-Za-z_][[:alnum:]]*\\)" +;; limit t) +;; +;; (csharp-log 3 "#if directive - %d" (match-beginning 1)) +;; +;; (unless +;; (progn +;; (goto-char (match-beginning 0)) +;; (c-skip-comments-and-strings limit)) +;; +;; (save-match-data +;; (c-put-font-lock-face (match-beginning 2) +;; (match-end 2) +;; 'font-lock-variable-name-face) +;; (goto-char (match-end 0)))))) +;; nil)) +;; ))) + + + ;; ,`(,(c-make-font-lock-search-function + ;; (concat "\\" + "\\s *" + "\\(" ; identifier-offset + (c-lang-const c-symbol-key) + "\\)") + (list ,(+ (regexp-opt-depth c-before-label-re) 2) + c-label-face-name nil t)))))) + + + + ;; Fontify the clauses after various keywords. + ,@(when (or (c-lang-const c-type-list-kwds) + (c-lang-const c-ref-list-kwds) + (c-lang-const c-colon-type-list-kwds) + (c-lang-const c-paren-type-kwds)) + `((,(c-make-font-lock-search-function + (concat "\\<\\(" + (c-make-keywords-re nil + (append (c-lang-const c-type-list-kwds) + (c-lang-const c-ref-list-kwds) + (c-lang-const c-colon-type-list-kwds) + (c-lang-const c-paren-type-kwds))) + "\\)\\>") + '((c-fontify-types-and-refs ((c-promote-possible-types t)) + (c-forward-keyword-clause 1) + (if (> (point) limit) (goto-char limit)))))))) + + + ;; Fontify the name that follows each namespace declaration + ;; this needs to be done in the matchers-after because + ;; otherwise the namespace names get the font-lock-type-face, + ;; due to the energetic efforts of c-forward-type. + ,`("\\<\\(namespace\\)[ \t\n\r\f\v]+\\(\\(?:[A-Za-z_][[:alnum:]]*\\.\\)*[A-Za-z_][[:alnum:]]*\\)" + 2 font-lock-constant-face t) + + + )) + + + +;; C# does generics. Setting this to t tells the parser to put +;; parenthesis syntax on angle braces that surround a comma-separated +;; list. +(c-lang-defconst c-recognize-<>-arglists + csharp t) + + +(c-lang-defconst c-identifier-key + csharp (concat "\\([[:alpha:]_][[:alnum:]_]*\\)" ; 1 + "\\(" + "[ \t\n\r\f\v]*" + "\\(\\.\\)" ;;(c-lang-const c-opt-identifier-concat-key) + "[ \t\n\r\f\v]*" + "\\(\\([[:alpha:]_][[:alnum:]_]*\\)\\)" + "\\)*")) + +;; C# has a few rules that are slightly different than Java for +;; operators. This also removed the Java's "super" and replaces it +;; with the C#'s "base". +(c-lang-defconst c-operators + csharp `((prefix "base"))) + + +;; C# uses CPP-like prefixes to mark #define, #region/endregion, +;; #if/else/endif, and #pragma. This regexp matches the prefix, not +;; including the beginning-of-line (BOL), and not including the term +;; after the prefix (define, pragma, region, etc). This regexp says +;; whitespace, followed by the prefix, followed by maybe more +;; whitespace. + +(c-lang-defconst c-opt-cpp-prefix + csharp "\\s *#\\s *") + + +;; there are no message directives in C# +(c-lang-defconst c-cpp-message-directives + csharp nil) + +(c-lang-defconst c-cpp-expr-directives + csharp '("if")) + +(c-lang-defconst c-opt-cpp-macro-define + csharp "define") + +;; $ is not a legal char in an identifier in C#. So we need to +;; create a csharp-specific definition of this constant. +(c-lang-defconst c-symbol-chars + csharp (concat c-alnum "_")) + +;; c-identifier-syntax-modifications by default defines $ as a word +;; syntax, which is not legal in C#. So, define our own lang-specific +;; value. +(c-lang-defconst c-identifier-syntax-modifications + csharp '((?_ . "w"))) + + + +(c-lang-defconst c-colon-type-list-kwds + csharp '("class")) + +(c-lang-defconst c-block-prefix-disallowed-chars + + ;; Allow ':' for inherit list starters. + csharp (set-difference (c-lang-const c-block-prefix-disallowed-chars) + '(?: ?,))) + + +(c-lang-defconst c-assignment-operators + csharp '("=" "*=" "/=" "%=" "+=" "-=" ">>=" "<<=" "&=" "^=" "|=")) + +(c-lang-defconst c-primitive-type-kwds + ;; ECMA-344, S8 + csharp '("object" "string" "sbyte" "short" "int" "long" "byte" + "ushort" "uint" "ulong" "float" "double" "bool" "char" + "decimal" "void")) + +;; The keywords that define that the following is a type, such as a +;; class definition. +(c-lang-defconst c-type-prefix-kwds + ;; ECMA-344, S? + csharp '("class" "interface" "struct")) ;; no enum here. + ;; we want enum to be a brace list. + + +;; Type modifier keywords. They appear anywhere in types, but modify +;; instead of create one. +(c-lang-defconst c-type-modifier-kwds + ;; EMCA-344, S? + csharp '("readonly" "const")) + + +;; Tue, 20 Apr 2010 16:02 +;; need to verify that this works for lambdas... +(c-lang-defconst c-special-brace-lists + csharp '((?{ . ?}) )) + + + +;; dinoch +;; Thu, 22 Apr 2010 18:54 +;; +;; No idea why this isn't getting set properly in the first place. +;; In cc-langs.el, it is set to the union of a bunch of things, none +;; of which include "new", or "enum". +;; +;; But somehow both of those show up in the resulting derived regexp. +;; This breaks indentation of instance initializers, such as +;; +;; var x = new Foo { ... }; +;; +;; Based on my inspection, the existing c-lang-defconst should work! +;; I don't know how to fix this c-lang-defconst, so I am re-setting this +;; variable here, to provide the regex explicitly. +;; +(c-lang-defconst c-decl-block-key + csharp '"\\(namespace\\)\\([^[:alnum:]_]\\|$\\)\\|\\(class\\|interface\\|struct\\)\\([^[:alnum:]_]\\|$\\)" ) + + +;; Thu, 22 Apr 2010 14:29 +;; I want this to handle var x = new Foo[] { ... }; +;; not sure if necessary. +(c-lang-defconst c-inexpr-brace-list-kwds + csharp '("new")) + + +;; ;;(c-lang-defconst c-inexpr-class-kwds +;; ;; csharp '("new")) + + + +(c-lang-defconst c-class-decl-kwds + ;; EMCA-344, S? + ;; don't include enum here, because we want it to be fontified as a brace + ;; list, with commas delimiting the values. see c-brace-list-decl-kwds + ;; below. + csharp '("class" "interface" "struct" )) ;; no "enum"!! + + +;; The various modifiers used for class and method descriptions. +(c-lang-defconst c-modifier-kwds + csharp '("public" "partial" "private" "const" "abstract" "sealed" + "protected" "ref" "out" "static" "virtual" + "override" "params" "internal")) + + +;; Thu, 22 Apr 2010 23:02 +;; Based on inspection of the cc-mode code, the c-protection-kwds +;; c-lang-const is used only for objective-c. So the value is +;; irrelevant for csharp. +(c-lang-defconst c-protection-kwds + csharp nil + ;; csharp '("private" "protected" "public" "internal") +) + + +;; Define the keywords that can have something following after them. +(c-lang-defconst c-type-list-kwds + csharp '("struct" "class" "interface" "is" "as" + "delegate" "event" "set" "get" "add" "remove")) + + +;; This allows the classes after the : in the class declartion to be +;; fontified. +(c-lang-defconst c-typeless-decl-kwds + csharp '(":")) + +;; Sets up the enum to handle the list properly, and also the new +;; keyword to handle object initializers. This requires a modified +;; c-basic-matchers-after (see above) in order to correctly fontify C# +;; 3.0 object initializers. +(c-lang-defconst c-brace-list-decl-kwds + csharp '("enum" "new")) + + +;; Statement keywords followed directly by a substatement. +;; catch is not one of them, because catch has a paren (typically). +(c-lang-defconst c-block-stmt-1-kwds + csharp '("do" "try" "finally" "unsafe")) + + +;; Statement keywords followed by a paren sexp and then by a substatement. +(c-lang-defconst c-block-stmt-2-kwds + csharp '("for" "if" "switch" "while" "catch" "foreach" "using" + "checked" "unchecked" "lock")) + + +;; Statements that break out of braces +(c-lang-defconst c-simple-stmt-kwds + csharp '("return" "continue" "break" "throw" "goto" )) + +;; Statements that allow a label +;; TODO? +(c-lang-defconst c-before-label-kwds + csharp nil) + +;; Constant keywords +(c-lang-defconst c-constant-kwds + csharp '("true" "false" "null")) + +;; Keywords that start "primary expressions." +(c-lang-defconst c-primary-expr-kwds + csharp '("this" "base")) + +;; Treat namespace as an outer block so class indenting +;; works properly. +(c-lang-defconst c-other-block-decl-kwds + csharp '("namespace")) + +(c-lang-defconst c-other-kwds + csharp '("sizeof" "typeof" "is" "as" "yield" + "where" "select" "in" "from")) + +(c-lang-defconst c-overloadable-operators + ;; EMCA-344, S14.2.1 + csharp '("+" "-" "*" "/" "%" "&" "|" "^" + "<<" ">>" "==" "!=" ">" "<" ">=" "<=")) + + +;; This c-cpp-matchers stuff is used for fontification. +;; see cc-font.el +;; + +;; There's no preprocessor in C#, but there are still compiler +;; directives to fontify: "#pragma", #region/endregion, #define, #undef, +;; #if/else/endif. (The definitions for the extra keywords above are +;; enough to incorporate them into the fontification regexps for types +;; and keywords, so no additional font-lock patterns are required for +;; keywords.) + +(c-lang-defconst c-cpp-matchers + csharp (cons + ;; Use the eval form for `font-lock-keywords' to be able to use + ;; the `c-preprocessor-face-name' variable that maps to a + ;; suitable face depending on the (X)Emacs version. + '(eval . (list "^\\s *\\(#pragma\\|undef\\|define\\)\\>\\(.*\\)" + (list 1 c-preprocessor-face-name) + '(2 font-lock-string-face))) + ;; There are some other things in `c-cpp-matchers' besides the + ;; preprocessor support, so include it. + (c-lang-const c-cpp-matchers))) + + + +;; Custom variables +;;;###autoload +(defcustom csharp-mode-hook nil + "*Hook called by `csharp-mode'." + :type 'hook + :group 'csharp) + + ;; The following fn allows this: + ;; (csharp-log 3 "scan result...'%s'" state) + +(defcustom csharp-log-level 0 + "The current log level for CSharp-mode-specific operations. +This is used in particular by the verbatim-literal +string scanning. + +Most other csharp functions are not instrumented. +0 = NONE, 1 = Info, 2 = VERBOSE, 3 = DEBUG, 4 = SHUTUP ALREADY. " + :type 'integer + :group 'csharp) + + +;;;###autoload +(defcustom csharp-want-flymake-fixup t + "*Whether to enable the builtin C# support for flymake. This is meaningful +only if flymake is loaded." + :type 'boolean :group 'csharp) + +;;;###autoload +(defcustom csharp-want-yasnippet-fixup t + "*Whether to enable the builtin C# support for yasnippet. This is meaningful +only if flymake is loaded." + :type 'boolean :group 'csharp) + + +;;;###autoload +(defcustom csharp-want-imenu t + "*Whether to generate a buffer index via imenu for C# buffers." + :type 'boolean :group 'csharp) + + +;;;###autoload +(defcustom csharp-make-tool "nmake.exe" + "*The make tool to use. Defaults to nmake, found on path. Specify +a full path or alternative program name, to tell csharp-mode to use +a different make tool in compile commands. + +See also, `csharp-msbuild-tool'. + +" + :type 'string :group 'csharp) + + +;;;###autoload +(defcustom csharp-msbuild-tool "msbuild.exe" + "*The tool to use to build .csproj files. Defaults to msbuild, found on +path. Specify a full path or alternative program name, to tell csharp-mode +to use a different make tool in compile commands. + +See also, `csharp-make-tool'. + +" + :type 'string :group 'csharp) + + +;;;###autoload +(defcustom csharp-cmd-line-limit 28 + "The number of lines at the top of the file to look in, to find +the command that csharp-mode will use to compile the current +buffer, or the command \"stub\" that csharp-mode will use to +check the syntax of the current buffer via flymake. + +If the value of this variable is zero, then csharp-mode looks +everywhere in the file. If the value is positive, then only in +the first N lines. If negative, then only in the final N lines. + +The line should appear in a comment inside the C# buffer. + + +Compile +-------- + +In the case of compile, the compile command must be prefixed with +\"compile:\". For example, + + // compile: csc.exe /r:Hallo.dll Arfie.cs + + +This command will be suggested as the compile command when the +user invokes `compile' for the first time. + + +Flymake +-------- + +In the case of flymake, the command \"stub\" string must be +prefixed with \"flymake:\". For example, + + // flymake: DOTNETDIR\csc.exe /target:netmodule /r:foo.dll @@FILE@@ + +In the case of flymake, the string should NOT include the name of +the file for the buffer being checked. Instead, use the token +@@FILE@@ . csharp-mode will replace this token with the name of +the source file to compile, before passing the command to flymake +to run it. + +If for some reason the command is invalid or illegal, flymake +will report an error and disable itself. + +It might be handy to run fxcop, for example, via flymake. + + // flymake: fxcopcmd.exe /c /f:MyLibrary.dll + + + +In all cases +------------ + +Be sure to specify the proper path for your csc.exe, whatever +version that might be, or no path if you want to use the system +PATH search. + +If the buffer depends on external libraries, then you will want +to include /R arguments to that csc.exe command. + +To be clear, this variable sets the number of lines to search for +the command. This cariable is an integer. + +If the marker string (either \"compile:\" or \"flymake:\" +is present in the given set of lines, csharp-mode will take +anything after the marker string as the command to run. + +" + :type 'integer :group 'csharp) + + + +(defconst csharp-font-lock-keywords-1 (c-lang-const c-matchers-1 csharp) + "Minimal highlighting for C# mode.") + +(defconst csharp-font-lock-keywords-2 (c-lang-const c-matchers-2 csharp) + "Fast normal highlighting for C# mode.") + +(defconst csharp-font-lock-keywords-3 (c-lang-const c-matchers-3 csharp) + "Accurate normal highlighting for C# mode.") + +(defvar csharp-font-lock-keywords csharp-font-lock-keywords-3 + "Default expressions to highlight in C# mode.") + + +(defvar csharp-mode-syntax-table nil + "Syntax table used in csharp-mode buffers.") +(or csharp-mode-syntax-table + (setq csharp-mode-syntax-table + (funcall (c-lang-const c-make-mode-syntax-table csharp)))) + +(defvar csharp-mode-abbrev-table nil + "Abbreviation table used in csharp-mode buffers.") +(c-define-abbrev-table 'csharp-mode-abbrev-table + ;; Keywords that if they occur first on a line might alter the + ;; syntactic context, and which therefore should trig reindentation + ;; when they are completed. + '(("else" "else" c-electric-continued-statement 0) + ("while" "while" c-electric-continued-statement 0) + ("catch" "catch" c-electric-continued-statement 0) + ("finally" "finally" c-electric-continued-statement 0))) + +(defvar csharp-mode-map (let ((map (c-make-inherited-keymap))) + ;; Add bindings which are only useful for C# + map) + "Keymap used in csharp-mode buffers.") + + +(defvar csharp--yasnippet-has-been-fixed nil + "indicates whether yasnippet has been patched for use with csharp. +Intended for internal use only.") + +(defvar csharp--flymake-has-been-installed nil + "one-time use boolean, to check whether csharp tweaks for flymake (advice +etc) have been installed.") + +(defvar csharp-flymake-csc-arguments + (list "/t:module" "/nologo") + "A list of arguments to use with the csc.exe +compiler, when using flymake with a +direct csc.exe build for syntax checking purposes.") + + +(defvar csharp-flymake-aux-error-info nil + "a list of auxiliary flymake error info items. Each item in the +list is a pair, consisting of a line number and a column number. +This info is set by advice to flymake-parse-line, and used by +advice attached to flymake-goto-line, to navigate to the proper +error column when possible. ") + + +(defvar csharp-flymake-csc-error-pattern + "^[ \t]*\\([_A-Za-z0-9][^(]+\\.cs\\)(\\([0-9]+\\)[,]\\([0-9]+\\)) ?: \\(\\(error\\|warning\\) +:? *C[SA][0-9]+ *:[ \t\n]*\\(.+\\)\\)" + "The regex pattern for C# compiler error messages. Follows +the same form as an entry in `flymake-err-line-patterns'. The +value is a STRING, a regex.") + +;; TODO +;; Defines our constant for finding attributes. +;;(defconst csharp-attribute-regex "\\[\\([XmlType]+\\)(") +;;(defconst csharp-attribute-regex "\\[\\(.\\)") +;; This doesn't work because the string regex happens before this point +;; and getting the font-locking to work before and after is fairly difficult +;;(defconst csharp-attribute-regex +;; (concat +;; "\\[[a-zA-Z][ \ta-zA-Z0-9.]+" +;; "\\((.*\\)?" +;;)) + + +;; ================================================================== +;; end of c# values for "language constants" defined in cc-langs.el +;; ================================================================== + + + + + +;; ======================================================================== +;; Flymake integration + +(defun csharp-flymake-init () + (csharp-flymake-init-impl + 'flymake-create-temp-inplace t t 'csharp-flymake-get-cmdline)) + +(defun csharp-flymake-init-impl (create-temp-f use-relative-base-dir use-relative-source get-cmdline-f) + "Create syntax check command line for a directly checked source file. +Use CREATE-TEMP-F for creating temp copy." + (let* ((args nil) + (temp-source-file-name (flymake-init-create-temp-buffer-copy create-temp-f))) + (setq args (flymake-get-syntax-check-program-args + temp-source-file-name "." + use-relative-base-dir use-relative-source + get-cmdline-f)) + args)) + + +(defun csharp-flymake-cleanup () + "Delete the temporary .netmodule file created in syntax checking +a C# buffer, then call through to flymake-simple-cleanup." + + (if flymake-temp-source-file-name + (progn + (let* ((netmodule-name + (concat (file-name-sans-extension flymake-temp-source-file-name) + ".netmodule")) + (expanded-netmodule-name (expand-file-name netmodule-name "."))) + (if (file-exists-p expanded-netmodule-name) + (flymake-safe-delete-file expanded-netmodule-name))) + )) + (flymake-simple-cleanup)) + + +(defun csharp-split-string-respecting-quotes (s) + "splits a string into tokens, respecting double quotes +For example, the string 'This is \"a string\"' will be split into 3 tokens. + +More pertinently, the string + 'csc /t:module /R:\"c:\abba dabba\dooo\Foo.dll\"' + +...will be split into 3 tokens. + +This fn also removes quotes from the tokens that have them. This is for +compatibility with flymake and the process-start fn. + +" + (let ((local-s s) + (my-re-1 "[^ \"]*\"[^\"]+\"\\|[^ \"]+") + (my-re-2 "\\([^ \"]*\\)\"\\([^\"]+\\)\"") + (tokens)) + (while (string-match my-re-1 local-s) + (let ((token (match-string 0 local-s)) + (remainder (substring local-s (match-end 0)))) + (if (string-match my-re-2 token) + (setq token (concat (match-string 1 token) (match-string 2 token)))) + ;;(message "token: %s" token) + (setq tokens (append tokens (list token))) + (setq local-s remainder))) + tokens)) + + +(defun csharp-get-value-from-comments (marker-string line-limit) + "gets a string from the header comments in the current buffer. + +This is used to extract the flymake command and the compile +command from the comments. + +It looks for \"marker-string:\" and returns the string that +follows it, or returns nil if that string is not found. + +eg, when marker-string is \"flymake\", and the following +string is found at the top of the buffer: + + flymake: csc.exe /r:Hallo.dll + +...then this command will return the string + + \"csc.exe /r:Hallo.dll\" + +It's ok to have whitespace between the marker and the following +colon. + +" + + (let (start search-limit found) + ;; determine what lines to look in + (save-excursion + (save-restriction + (widen) + (cond ((> line-limit 0) + (goto-char (setq start (point-min))) + (forward-line line-limit) + (setq search-limit (point))) + ((< line-limit 0) + (goto-char (setq search-limit (point-max))) + (forward-line line-limit) + (setq start (point))) + (t ;0 => no limit (use with care!) + (setq start (point-min)) + (setq search-limit (point-max)))))) + + ;; look in those lines + (save-excursion + (save-restriction + (widen) + (let ((re-string + (concat "\\b" marker-string "[ \t]*:[ \t]*\\(.+\\)$"))) + (if (and start + (< (goto-char start) search-limit) + (re-search-forward re-string search-limit 'move)) + + (buffer-substring-no-properties + (match-beginning 1) + (match-end 1)))))))) + + + + +(defun csharp-replace-command-tokens (explicitly-specified-command) + "Replace tokens in the flymake or compile command extracted from the +buffer, to allow specification of the original and modified +filenames. + + @@ORIG@@ - gets replaced with the original filename + @@FILE@@ - gets replaced with the name of the temporary file + created by flymake + +" + (let ((massaged-command explicitly-specified-command)) + (if (string-match "@@SRC@@" massaged-command) + (setq massaged-command + (replace-match + (file-relative-name flymake-temp-source-file-name) t t massaged-command))) + (if (string-match "@@ORIG@@" massaged-command) + (setq massaged-command + (replace-match + (file-relative-name buffer-file-name) t t massaged-command))) + massaged-command)) + + +;;(setq flymake-log-level 3) + +(defun csharp-flymake-get-final-csc-arguments (initial-arglist) + "Gets the command used by csc.exe for flymake runs. +This may inject a /t:module into an arglist, where it is not +present. + +This fn burps if a different /t: argument is found. + +" + (interactive) + (let ((args initial-arglist) + arg + (found nil)) + (while args + (setq arg (car args)) + (cond + ((string-equal arg "/t:module") (setq found t)) + ((string-match "^/t:" arg) + (setq found t) + (message "csharp-mode: WARNING /t: option present in arglist, and not /t:module; fix this."))) + + (setq args (cdr args))) + + (setq args + (if found + initial-arglist + (append (list "/t:module") initial-arglist))) + + (if (called-interactively-p 'any) + (message "result: %s" (prin1-to-string args))) + + args)) + + +(defun csharp-flymake-get-cmdline (source base-dir) + "Gets the cmd line for running a flymake session in a C# buffer. +This gets called by flymake itself. + +The fn looks in the buffer for a line that looks like: + + flymake: + + (It should be embedded into a comment) + +Typically the command will be a line that runs nmake.exe, +msbuild.exe, or csc.exe, with various options. It should +eventually run the CSC.exe compiler, or something else that emits +error messages in the same form as the C# compiler, like FxCopCmd.exe + +Some notes on implementation: + + 1. csharp-mode copies the buffer to a temporary file and + compiles *that*. This temporary file has a different name + than the actual file name for the buffer - _flymake gets + appended to the basename. Therefore, you should specify + Foo_flymake.cs for the filename, if you want to explicitly + refer to it. + + If you want to refer to it implicitly, you can use the special + token \"@@SRC@@\" in the command. It will get replaced with the + name of the temporary file at runtime. If you want to refer to + the original name of the buffer, use @@ORIG@@. + + 2. In general, when running the compiler, you should use a + target type of \"module\" (eg, /t:module) to allow + csharp-mode to clean up the products of the build. + + 3. See `csharp-cmd-line-limit' for a way to restrict where + csharp-mode will search for the command. + + 4. If this string is not found, then this fn will fallback to + a generic, generated csc.exe command. + +" + (let ((explicitly-specified-command + (csharp-get-value-from-comments "flymake" csharp-cmd-line-limit))) + + (cond + (explicitly-specified-command + + ;; the marker string was found in the buffer + (let ((tokens (csharp-split-string-respecting-quotes + (csharp-replace-command-tokens explicitly-specified-command)))) + + (list (car tokens) (cdr tokens)))) + + ;; ;; implicitly append? the name of the temporary source file + ;; (list (car tokens) (append (cdr tokens) (list flymake-temp-source-file-name))))) + + (t + ;; fallback + (list "csc.exe" + (append (csharp-flymake-get-final-csc-arguments + csharp-flymake-csc-arguments) + (list source))))))) + + +;; (defun csharp-flymake-get-cmdline (source base-dir) +;; "Gets the cmd line for running a flymake session in a C# buffer. +;; This gets called by flymake itself. +;; +;; The fn looks in the buffer for a line that looks like: +;; +;; flymake: +;; +;; (It should be embedded into a comment) +;; +;; Typically the command will be a line that runs nmake.exe, +;; msbuild.exe, or cscc.exe, with various options. It should +;; eventually run the CSC.exe compiler, or something else that emits +;; error messages in the same form as the C# compiler. +;; +;; In general, when running the compiler, you should use a target +;; type of \"module\" (eg, /t:module) to allow csharp-mode to +;; clean up the products of the build. +;; +;; See `csharp-cmd-line-limit' for a way to restrict where +;; csharp-mode will search for the command. +;; +;; If this string is not found, then this fn will fallback to a +;; generic, generated csc.exe command. +;; +;; " +;; (let ((explicitly-specified-command +;; (let ((line-limit csharp-cmd-line-limit) +;; start search-limit found) +;; ;; determine what lines to look in +;; (save-excursion +;; (save-restriction +;; (widen) +;; (cond ((> line-limit 0) +;; (goto-char (setq start (point-min))) +;; (forward-line line-limit) +;; (setq search-limit (point))) +;; ((< line-limit 0) +;; (goto-char (setq search-limit (point-max))) +;; (forward-line line-limit) +;; (setq start (point))) +;; (t ;0 => no limit (use with care!) +;; (setq start (point-min)) +;; (setq search-limit (point-max)))))) +;; +;; ;; look in those lines +;; (save-excursion +;; (save-restriction +;; (widen) +;; (if (and start +;; (< (goto-char start) search-limit) +;; (re-search-forward "\\bflymake-command[ \t]*:[ \t]*\\(.+\\)$" search-limit 'move)) +;; +;; (buffer-substring-no-properties +;; (match-beginning 1) +;; (match-end 1)))))))) +;; +;; (cond +;; (explicitly-specified-command +;; ;; the marker string was found in the buffer +;; (let ((tokens (csharp-split-string-respecting-quotes +;; explicitly-specified-command))) +;; ;; implicitly append the name of the temporary source file +;; (list (car tokens) (append (cdr tokens) (list flymake-temp-source-file-name))))) +;; +;; (t +;; ;; fallback +;; (list "csc.exe" +;; (append (csharp-flymake-get-final-csc-arguments +;; csharp-flymake-csc-arguments) +;; (list source))))))) + + + + + +(defun csharp-flymake-install () + "Change flymake variables and fns to work with C#. + +This fn does these things: + +1. add a C# entry to the flymake-allowed-file-name-masks, + or replace it if it already exists. + +2. add a C# entry to flymake-err-line-patterns. + This isn't strictly necessary because of item #4. + +3. override the definition for flymake-process-sentinel + to NOT check the process status on exit. MSBuild.exe + sets a non-zero status code when compile errors occur, + which causes flymake to disable itself with the regular + flymake-process-sentinel. + +4. redefine flymake-start-syntax-check-process to unset the + query-on-exit flag for flymake processes. This allows emacs to + exit even if flymake is currently running. + +5. provide advice to flymake-parse-line and + flymake-parse-err-lines, specifically set up for C# + buffers. This allows optimized searching for errors in csc.exe + output, and storing column numbers, for use in #6. + +6. define advice to flymake-goto-line , to allow it to goto the + appropriate column for the error on a given line. This advice + looks in flymake-er-info, a list, and uses the heuristic that + the first error that matches the given line number, is the error + we want. This will break if there is more than one error on a + single line. + +" + + (flymake-log 2 "csharp-flymake-install") + + (or csharp--flymake-has-been-installed + (progn + + ;; 1. add a C# entry to the flymake-allowed-file-name-masks + (let* ((key "\\.cs\\'") + (csharpentry (assoc key flymake-allowed-file-name-masks))) + (if csharpentry + (setcdr csharpentry '(csharp-flymake-init csharp-flymake-cleanup)) + (add-to-list + 'flymake-allowed-file-name-masks + (list key 'csharp-flymake-init 'csharp-flymake-cleanup)))) + + + ;; 2. add a C# entry to flymake-err-line-patterns + ;; + ;; The value of each entry is a list, (STRING IX1 IX2 IX3 IX4), where + ;; STRING is the regex, and the other 4 values are indexes into the + ;; regex captures for the filename, line, column, and error text, + ;; respectively. + (add-to-list + 'flymake-err-line-patterns + (list csharp-flymake-csc-error-pattern 1 2 3 4)) + + + + ;; 3. override the definition for flymake-process-sentinel + ;; + ;; DPC - 2011 Feb 26 + ;; Redefining a function is a bit unusual, but I think it is necessary + ;; to remove the check on process exit status. For VBC.exe, it gives + ;; a 1 status when compile errors result. Likewise msbuild.exe. This + ;; means flymake turns itself off, which we don't want. This really + ;; ought to be tunable in flymake, but I guess no one asked for that + ;; feature yet. + (defun flymake-process-sentinel (process event) + "Sentinel for syntax check buffers." + (when (memq (process-status process) '(signal exit)) + (let* ((exit-status (process-exit-status process)) + (command (process-command process)) + (source-buffer (process-buffer process)) + (cleanup-f (flymake-get-cleanup-function (buffer-file-name source-buffer)))) + + (flymake-log 2 "process %d exited with code %d" + (process-id process) exit-status) + (condition-case err + (progn + (flymake-log 3 "cleaning up using %s" cleanup-f) + (when (buffer-live-p source-buffer) + (with-current-buffer source-buffer + (funcall cleanup-f))) + + (delete-process process) + (setq flymake-processes (delq process flymake-processes)) + + (when (buffer-live-p source-buffer) + (with-current-buffer source-buffer + + (flymake-parse-residual) + ;;(flymake-post-syntax-check exit-status command) + (flymake-post-syntax-check 0 command) + (setq flymake-is-running nil)))) + (error + (let ((err-str (format "Error in process sentinel for buffer %s: %s" + source-buffer (error-message-string err)))) + (flymake-log 0 err-str) + (with-current-buffer source-buffer + (setq flymake-is-running nil)))))))) + + + ;; 4. redefine this fn - the reason is to allow exit without query on + ;; flymake processes. Not sure why this is not the default. + (defun flymake-start-syntax-check-process (cmd args dir) + "Start syntax check process." + (let* ((process nil)) + (condition-case err + (progn + (when dir + (let ((default-directory dir)) + (flymake-log 3 "starting process on dir %s" default-directory))) + (setq process (apply 'start-process "flymake-proc" (current-buffer) cmd args)) + + ;; dino - exit without query on active flymake processes + (set-process-query-on-exit-flag process nil) + + (set-process-sentinel process 'flymake-process-sentinel) + (set-process-filter process 'flymake-process-filter) + (push process flymake-processes) + + (setq flymake-is-running t) + (setq flymake-last-change-time nil) + (setq flymake-check-start-time (flymake-float-time)) + + (flymake-report-status nil "*") + (flymake-log 2 "started process %d, command=%s, dir=%s" + (process-id process) (process-command process) + default-directory) + process) + (error + (let* ((err-str (format "Failed to launch syntax check process '%s' with args %s: %s" + cmd args (error-message-string err))) + (source-file-name buffer-file-name) + (cleanup-f (flymake-get-cleanup-function source-file-name))) + (flymake-log 0 err-str) + (funcall cleanup-f) + (flymake-report-fatal-status "PROCERR" err-str)))))) + + + ;; 5. define some advice for the error parsing + (defadvice flymake-parse-err-lines (before + csharp-flymake-parse-line-patch-1 + activate compile) + (if (string-match "\\.[Cc][Ss]$" (file-relative-name buffer-file-name)) + ;; clear the auxiliary line information list, when a new parse + ;; starts. + (setq csharp-flymake-aux-error-info nil))) + + (defadvice flymake-parse-line (around + csharp-flymake-parse-line-patch-2 + activate compile) + ;; This advice will run in all buffers. Let's may sure we + ;; actually execute the important stiff only when a C# buffer is active. + (if (string-match "\\.[Cc][Ss]$" (file-relative-name buffer-file-name)) + + (let (raw-file-name + e-text + result + (pattern (list csharp-flymake-csc-error-pattern 1 2 3 4)) + (line-no 0) + (col-no 0) + (err-type "e")) + (if (string-match (car pattern) line) + (let* ((file-idx (nth 1 pattern)) + (line-idx (nth 2 pattern)) + (col-idx (nth 3 pattern)) + (e-idx (nth 4 pattern))) + (flymake-log 3 "parse line: fx=%s lx=%s ex=%s" + file-idx line-idx e-idx) + (setq raw-file-name (if file-idx (match-string file-idx line) nil)) + (setq line-no (if line-idx (string-to-number (match-string line-idx line)) 0)) + (setq col-no (if col-idx (string-to-number (match-string col-idx line)) 0)) + (setq e-text (if e-idx + (match-string e-idx line) + (flymake-patch-e-text (substring line (match-end 0))))) + (or e-text (setq e-text "")) + (if (and e-text (string-match "^[wW]arning" e-text)) + (setq err-type "w")) + (flymake-log 3 "parse line: fx=%s/%s lin=%s/%s col=%s/%s text=%s" + file-idx raw-file-name + line-idx line-no + col-idx (prin1-to-string col-no) + e-text) + + ;; add one entry to the list of auxiliary error information. + (add-to-list 'csharp-flymake-aux-error-info + (list line-no col-no)) + + (setq ad-return-value + (flymake-ler-make-ler raw-file-name line-no err-type e-text nil)) + ))) + + ;; else - not in a C# buffer + ad-do-it)) + + + ;; 6. finally, define some advice for the line navigation. It moves + ;; to the proper column, given the line number containing the + ;; error. It first calls the normal `flymake-goto-line', and assumes + ;; that the result is that the cursor is on the line that contains the + ;; error. At exit from that fn, the column is not important. This advice + ;; sets the column. + (defadvice flymake-goto-line (around + csharp-flymake-goto-line-patch + activate compile) + ;; This advice will run in all buffers. Let's may sure we + ;; actually execute the important stuff only when a C# buffer is active. + ad-do-it + (if (string-match "\\.[Cc][Ss]$" (file-relative-name buffer-file-name)) + (let* ((lno (ad-get-arg 0)) + (epair (assoc lno csharp-flymake-aux-error-info))) + (if epair + (forward-char (- (cadr epair) (current-column) 1)))))) + + + ;; 7. finally, set the flag + (setq csharp--flymake-has-been-installed t)))) + + + +;; Need to temporarily turn off flymake while reverting. +;; There' some kind of race-condition where flymake is trying +;; to compile while the buffer is being changed, and that +;; causes flymake to choke. +(defadvice revert-buffer (around + csharp-advise-revert-buffer + activate compile) + (let ((is-flymake-enabled + (and (fboundp 'flymake-mode) + flymake-mode))) + ;; disable + (if is-flymake-enabled + (flymake-mode-off)) + + ;; revert + ad-do-it + + ;; enable + (if is-flymake-enabled + (flymake-mode-on)))) + +;; ++++++++++++++++++++++ + + + + +;; ======================================================================== +;; moving + +;; alist of regexps for various structures in a csharp source file. +(eval-and-compile + (defconst csharp--regexp-alist + (list + + `(func-start + ,(concat + "^[ \t\n\r\f\v]*" ;; leading whitespace + "\\(" + "public\\(?: static\\)?\\|" ;; 1. access modifier + "private\\(?: static\\)?\\|" + "protected\\(?: internal\\)?\\(?: static\\)?\\|" + "static\\|" + "\\)" + "[ \t\n\r\f\v]+" + "\\(?:override[ \t\n\r\f\v]+\\)?" ;; optional + "\\([[:alpha:]_][^\t\(\n]+\\)" ;; 2. return type - possibly generic + "[ \t\n\r\f\v]+" + "\\([[:alpha:]_][[:alnum:]_]*\\)" ;; 3. name of func + "[ \t\n\r\f\v]*" + "\\(\([^\)]*\)\\)" ;; 4. params w/parens + "[ \t\n\r\f\v]*" + )) + + `(ctor-start + ,(concat + "^[ \t\n\r\f\v]*" ;; leading whitespace + "\\(" + "public\\|" ;; 1. access modifier + "private\\|" + "protected\\(?: internal\\)?\\|" + "static\\|" + "\\)" + "[ \t\n\r\f\v]+" + "\\([[:alpha:]_][[:alnum:]_]*\\)" ;; 2. name of ctor + "[ \t\n\r\f\v]*" + "\\(\([^\)]*\)\\)" ;; 3. parameter list (with parens) + "\\(" ;; 4. ctor dependency + "[ \t\n]*:[ \t\n]*" ;; colon + "\\(?:this\\|base\\)" ;; this or base + "[ \t\n\r\f\v]*" + "\\(?:\([^\)]*\)\\)" ;; parameter list (with parens) + "\\)?" ;; possibly + "[ \t\n\r\f\v]*" + )) + + + `(using-stmt + ,(concat + ;;"^[ \t\n\r\f\v]*" + "\\(\\, ]*\\)" ;; type name (generic) + "\\(" + "[ \t\n]*:[ \t\n]*" ;; colon + "\\([[:alpha:]_][^\t\(\n]+\\)" ;; base / intf - poss generic + "\\(" + "[ \t\n]*,[ \t\n]*" + "\\([[:alpha:]_][^\t\(\n]+\\)" ;; addl interface - poss generic + "\\)*" + "\\)?" ;; possibly + "[ \t\n\r\f\v]*" + )) + + `(enum-start + ,(concat + "^[ \t\f\v]*" ;; leading whitespace + "\\(" + "public[ \t]+enum\\|" ;; enum keyword + "enum" + "\\)" + "[ \t\n\r\f\v]+" + "\\([[:alpha:]_][[:alnum:]_]*\\)" ;; name of enum + "[ \t\n\r\f\v]*" + "\\(:[ \t\n\r\f\v]*" + "\\(" + "sbyte\\|byte\\|short\\|ushort\\|int\\|uint\\|long\\|ulong" + "\\)" + "[ \t\n\r\f\v]*" + "\\)?" ;; possibly + "[ \t\n\r\f\v]*" + )) + + + `(intf-start + ,(concat + "^[ \t\f\v]*" ;; leading whitespace + "\\(?:" + "public\\|internal\\|" ;; access modifier + "\\)" + "[ \t\n\r\f\v]+" + "\\(interface\\)" + "[ \t\n\r\f\v]+" + "\\([[:alpha:]_][[:alnum:]_]*\\)" ;; name of interface + "[ \t\n\r\f\v]*" + )) + + `(prop-start + ,(concat + "^[ \t\f\v]*" ;; leading whitespace + "\\(" + "public\\|" ;; 1: access modifier + "private\\|" + "protected internal\\|" + "internal protected\\|" + "internal\\|" + "\\)" + "[ \t\n\r\f\v]+" + "\\([[:alpha:]_][^\t\(\n]+\\)" ;; 2: return type - possibly generic + "[ \t\n\r\f\v]+" + "\\(" + "\\(?:[A-Za-z_][[:alnum:]_]*\\.\\)*" ;; possible prefix interface + "[[:alpha:]_][[:alnum:]_]*" ;; 3: name of prop + "\\)" + "[ \t\n\r\f\v]*" + )) + + `(indexer-start + ,(concat + "^[ \t\f\v]*" ;; leading whitespace + "\\(" + "public\\|" ;; 1: access modifier + "private\\|" + "protected internal\\|" + "internal protected\\|" + "internal\\|" + "\\)" + "[ \t\n\r\f\v]+" + "\\([[:alpha:]_][^\t\(\n]+\\)" ;; 2: return type - possibly generic + "[ \t\n\r\f\v]+" + "\\(this\\)" ;; 3: 'this' keyword + "[ \t\n\r\f\v]*" + "\\[" ;; open square bracket + "[ \t\n\r\f\v]*" + "\\([^\]]+\\)" ;; 4: index type + "[ \t\n\r\f\v]+" + "[[:alpha:]_][[:alnum:]_]*" ;; index name - a simple identifier + "\\]" ;; closing sq bracket + "[ \t\n\r\f\v]*" + )) + + `(namespace-start + ,(concat + "^[ \t\f\v]*" ;; leading whitespace + "\\(namespace\\)" + "[ \t\n\r\f\v]+" + "\\(" + "\\(?:[A-Za-z_][[:alnum:]_]*\\.\\)*" ;; name of namespace + "[A-Za-z_][[:alnum:]]*" + "\\)" + "[ \t\n\r\f\v]*" + )) + + ))) + + +(defun csharp--regexp (symbol) + "Retrieves a regexp from the `csharp--regexp-alist' corresponding +to the given symbol. +" + (let ((elt (assoc symbol csharp--regexp-alist))) + (if elt (cadr elt) nil))) + + +(defun csharp-move-back-to-beginning-of-block () + "Moves to the previous open curly. +" + (interactive) + (re-search-backward "{" (point-min) t)) + + +(defun csharp--move-back-to-beginning-of-something (must-match &optional must-not-match) + "Moves back to the open-curly that defines the beginning of *something*, +defined by the given MUST-MATCH, a regexp which must match immediately +preceding the curly. If MUST-NOT-MATCH is non-nil, it is treated +as a regexp that must not match immediately preceding the curly. + +This is a helper fn for `csharp-move-back-to-beginning-of-defun' and +`csharp-move-back-to-beginning-of-class' + +" + (interactive) + (let (done + (found (point)) + (need-to-backup (not (looking-at "{")))) + (while (not done) + (if need-to-backup + (setq found (csharp-move-back-to-beginning-of-block))) + (if found + (setq done (and (looking-back must-match) + (or (not must-not-match) + (not (looking-back must-not-match)))) + need-to-backup t) + (setq done t))) + found)) + + + +(defun csharp-move-back-to-beginning-of-defun () + "Moves back to the open-curly that defines the beginning of the +enclosing method. If point is outside a method, then move back to the +beginning of the prior method. + +See also, `csharp-move-fwd-to-end-of-defun'. +" + (interactive) + (cond + + ((bobp) nil) + + (t + (let (found) + (save-excursion + ;; handle the case where we're at the top of a fn now. + ;; if the user is asking to move back, then obviously + ;; he wants to move back to a *prior* defun. + (if (and (looking-at "{") + (looking-back (csharp--regexp 'func-start)) + (not (looking-back (csharp--regexp 'namespace-start)))) + (forward-char -1)) + + ;; now do the real work + (setq found (csharp--move-back-to-beginning-of-something + (csharp--regexp 'func-start) + (csharp--regexp 'namespace-start)))) + (if found + (goto-char found)))))) + + +(defun csharp--on-defun-close-curly-p () + "return t when point is on the close-curly of a method." + (and (looking-at "}") + (save-excursion + (and + (progn (forward-char) (forward-sexp -1) t) + (not (looking-back (csharp--regexp 'class-start))) + (not (looking-back (csharp--regexp 'namespace-start))) + (looking-back (csharp--regexp 'func-start)))))) + +(defun csharp--on-ctor-close-curly-p () + "return t when point is on the close-curly of a constructor." + (and (looking-at "}") + (save-excursion + (and + (progn (forward-char) (forward-sexp -1) t) + (looking-back (csharp--regexp 'ctor-start)))))) + +(defun csharp--on-class-close-curly-p () + "return t when point is on the close-curly of a class or struct." + (and (looking-at "}") + (save-excursion + (and + (progn (forward-char) (forward-sexp -1) t) + (not (looking-back (csharp--regexp 'namespace-start))) + (looking-back (csharp--regexp 'class-start)))))) + +(defun csharp--on-intf-close-curly-p () + "return t when point is on the close-curly of an interface." + (and (looking-at "}") + (save-excursion + (and + (progn (forward-char) (forward-sexp -1) t) + (looking-back (csharp--regexp 'intf-start)))))) + +(defun csharp--on-enum-close-curly-p () + "return t when point is on the close-curly of an enum." + (and (looking-at "}") + (save-excursion + (and + (progn (forward-char) (forward-sexp -1) t) + (looking-back (csharp--regexp 'enum-start)))))) + +(defun csharp--on-namespace-close-curly-p () + "return t when point is on the close-curly of a namespace." + (and (looking-at "}") + (save-excursion + (and + (progn (forward-char) (forward-sexp -1) t) + (looking-back (csharp--regexp 'namespace-start)))))) + +(defun csharp--on-defun-open-curly-p () + "return t when point is on the open-curly of a method." + (and (looking-at "{") + (not (looking-back (csharp--regexp 'class-start))) + (not (looking-back (csharp--regexp 'namespace-start))) + (looking-back (csharp--regexp 'func-start)))) + +(defun csharp--on-class-open-curly-p () + "return t when point is on the open-curly of a class." + (and (looking-at "{") + (not (looking-back (csharp--regexp 'namespace-start))) + (looking-back (csharp--regexp 'class-start)))) + +(defun csharp--on-genclass-open-curly-p () + "return t when point is on the open-curly of a generic class." + (and (looking-at "{") + (looking-back (csharp--regexp 'genclass-start)))) + +(defun csharp--on-namespace-open-curly-p () + "return t when point is on the open-curly of a namespace." + (and (looking-at "{") + (looking-back (csharp--regexp 'namespace-start)))) + +(defun csharp--on-ctor-open-curly-p () + "return t when point is on the open-curly of a ctor." + (and (looking-at "{") + (looking-back (csharp--regexp 'ctor-start)))) + +(defun csharp--on-intf-open-curly-p () + "return t when point is on the open-curly of a interface." + (and (looking-at "{") + (looking-back (csharp--regexp 'intf-start)))) + +(defun csharp--on-prop-open-curly-p () + "return t when point is on the open-curly of a property." + (and (looking-at "{") + (not (looking-back (csharp--regexp 'class-start))) + (looking-back (csharp--regexp 'prop-start)))) + +(defun csharp--on-indexer-open-curly-p () + "return t when point is on the open-curly of a C# indexer." + (and (looking-at "{") + (looking-back (csharp--regexp 'indexer-start)))) + +(defun csharp--on-enum-open-curly-p () + "return t when point is on the open-curly of a interface." + (and (looking-at "{") + (looking-back (csharp--regexp 'enum-start)))) + + + +(defun csharp-move-fwd-to-end-of-defun () + "Moves forward to the close-curly that defines the end of the enclosing +method. If point is outside a method, moves forward to the close-curly that +defines the end of the next method. + +See also, `csharp-move-back-to-beginning-of-defun'. +" + (interactive) + + (let ((really-move + (lambda () + (let ((start (point)) + dest-char) + (save-excursion + (csharp-move-back-to-beginning-of-defun) + (forward-sexp) + (if (>= (point) start) + (setq dest-char (point)))) + (if dest-char + (goto-char dest-char)))))) + + (cond + + ;; case 1: end of buffer. do nothing. + ((eobp) nil) + + ;; case 2: we're at the top of a class + ((csharp--on-class-open-curly-p) + (let (found-it) + (save-excursion + (forward-char 1) ;; get off the curly + (setq found-it + (and ;; look for next open curly + (re-search-forward "{" (point-max) t) + (funcall really-move)))) + (if found-it + (goto-char found-it)))) + + + ;; case 3: we're at the top of a fn now. + ((csharp--on-defun-open-curly-p) + (forward-sexp)) + + + ;; case 4: we're at the bottom of a fn now (possibly + ;; after just calling csharp-move-fwd-to-end-of-defun. + ((and (looking-back "}") + (save-excursion + (forward-sexp -1) + (csharp--on-defun-open-curly-p))) + + (let (found-it) + (save-excursion + (setq found-it + (and (re-search-forward "{" (point-max) t) + (funcall really-move)))) + (if found-it + (goto-char found-it)))) + + + ;; case 5: we're at none of those places. + (t + (funcall really-move))))) + + + + +(defun csharp-move-back-to-beginning-of-class () + "Moves back to the open-curly that defines the beginning of the +enclosing class. If point is outside a class, then move back to the +beginning of the prior class. + +See also, `csharp-move-fwd-to-end-of-defun'. +" + (interactive) + + (cond + ((bobp) nil) + + (t + (let (found) + (save-excursion + ;; handle the case where we're at the top of a class now. + ;; if the user is asking to move back, then obviously + ;; he wants to move back to a *prior* defun. + (if (and (looking-at "{") + (looking-back (csharp--regexp 'class-start)) + (not (looking-back (csharp--regexp 'namespace-start)))) + (forward-char -1)) + + ;; now do the real work + (setq found (csharp--move-back-to-beginning-of-something + (csharp--regexp 'class-start) + (csharp--regexp 'namespace-start)))) + (if found + (goto-char found)))))) + + + + +(defun csharp-move-fwd-to-end-of-class () + "Moves forward to the close-curly that defines the end of the +enclosing class. + +See also, `csharp-move-back-to-beginning-of-class'. +" + (interactive) + (let ((start (point)) + dest-char) + (save-excursion + (csharp-move-back-to-beginning-of-class) + (forward-sexp) + (if (>= (point) start) + (setq dest-char (point)))) + + (if dest-char + (goto-char dest-char)))) + + + +(defun csharp-move-back-to-beginning-of-namespace () + "Moves back to the open-curly that defines the beginning of the +enclosing namespace. If point is outside a namespace, then move back +to the beginning of the prior namespace. + +" + (interactive) + (cond + + ((bobp) nil) + + (t + (let (found) + (save-excursion + ;; handle the case where we're at the top of a namespace now. + ;; if the user is asking to move back, then obviously + ;; he wants to move back to a *prior* defun. + (if (and (looking-at "{") + (looking-back (csharp--regexp 'namespace-start))) + (forward-char -1)) + + ;; now do the real work + (setq found (csharp--move-back-to-beginning-of-something + (csharp--regexp 'namespace-start)))) + (if found + (goto-char found)))))) + +;; moving +;; ======================================================================== + + + + +;; ================================================================== +;;; imenu stuff + +;; define some advice for menu construction. + +;; The way imenu constructs menus from the index alist, in +;; `imenu--split-menu', is ... ah ... perplexing. If the csharp +;; create-index fn returns an ordered menu, and the imenu "sort" fn has +;; been set to nil, imenu still sorts the menu, according to the rule +;; that all submenus must appear at the top of any menu. Why? I don't +;; know. This advice disables that weirdness in C# buffers. + +(defadvice imenu--split-menu (around + csharp--imenu-split-menu-patch + activate compile) + ;; This advice will run in all buffers. Let's may sure we + ;; actually execute the important bits only when a C# buffer is active. + (if (and (string-match "\\.[Cc][Ss]$" (file-relative-name buffer-file-name)) + (boundp 'csharp-want-imenu) + csharp-want-imenu) + (let ((menulist (copy-sequence menulist)) + keep-at-top) + (if (memq imenu--rescan-item menulist) + (setq keep-at-top (list imenu--rescan-item) + menulist (delq imenu--rescan-item menulist))) + ;; This is the part from the original imenu code + ;; that puts submenus at the top. huh? why? + ;; -------------------------------------------- + ;; (setq tail menulist) + ;; (dolist (item tail) + ;; (when (imenu--subalist-p item) + ;; (push item keep-at-top) + ;; (setq menulist (delq item menulist)))) + (if imenu-sort-function + (setq menulist (sort menulist imenu-sort-function))) + (if (> (length menulist) imenu-max-items) + (setq menulist + (mapcar + (lambda (menu) + (cons (format "From: %s" (caar menu)) menu)) + (imenu--split menulist imenu-max-items)))) + (setq ad-return-value + (cons title + (nconc (nreverse keep-at-top) menulist)))) + ;; else + ad-do-it)) + + +;; +;; I used this to examine the performance of the imenu scanning. +;; It's not necessary during normal operation. +;; +;; (defun csharp-imenu-begin-profile () +;; "turn on profiling" +;; (interactive) +;; (let ((fns '(csharp--on-class-open-curly-p +;; csharp--on-namespace-open-curly-p +;; csharp--on-ctor-open-curly-p +;; csharp--on-enum-open-curly-p +;; csharp--on-intf-open-curly-p +;; csharp--on-prop-open-curly-p +;; csharp--on-indexer-open-curly-p +;; csharp--on-defun-open-curly-p +;; csharp--imenu-create-index-helper +;; looking-back +;; looking-at))) +;; (if (fboundp 'elp-reset-all) +;; (elp-reset-all)) +;; (mapc 'elp-instrument-function fns))) + + + +(defun csharp--imenu-remove-param-names-from-paramlist (s) + "The input string S is a parameter list, of the form seen in a +C# method. TYPE1 NAME1 [, TYPE2 NAME2 ...] + +This fn returns a string of the form TYPE1 [, TYPE2...] + +Upon entry, it's assumed that the parens included in S. + +" + (if (string= s "()") + s + (save-match-data + (let* (new + (state 0) ;; 0 => ws, 1=>slurping param... + c + cs + nesting + need-type + ix2 + (s2 (substring s 1 -1)) + (len (length s2)) + (i (1- len))) + + (while (> i 0) + (setq c (aref s2 i) ;; current character + cs (char-to-string c)) ;; s.t. as a string + + (cond + + ;; backing over whitespace "after" the param + ((= state 0) + (cond + ;; more ws + ((string-match "[ \t\f\v\n\r]" cs) + t) + ;; a legal char for an identifier + ((string-match "[A-Za-z_0-9]" cs) + (setq state 1)) + (t + (error "unexpected char (A)")))) + + + ;; slurping param name + ((= state 1) + (cond + ;; ws signifies the end of the param + ((string-match "[ \t\f\v\n\r]" cs) + (setq state 2)) + ;; a legal char for an identifier + ((string-match "[A-Za-z_0-9]" cs) + t) + (t + (error "unexpected char (B)")))) + + + ;; ws between typespec and param name + ((= state 2) + (cond + ((string-match "[ \t\f\v\n\r]" cs) + t) + ;; non-ws indicates the type spec is beginning + (t + (incf i) + (setq state 3 + need-type nil + nesting 0 + ix2 i)))) + + + ;; slurping type + ((= state 3) + (cond + ((= ?> c) (incf nesting)) + ((= ?< c) + (decf nesting) + (setq need-type t)) + + ;; ws or comma maybe signifies the end of the typespec + ((string-match "[ \t\f\v\n\r,]" cs) + (if (and (= nesting 0) (not need-type)) + (progn + (setq new (cons (substring s2 (1+ i) ix2) new)) + (setq state + (if (= c ?,) 0 4))))) + + ((string-match "[A-Za-z_0-9]" cs) + (setq need-type nil)))) + + + ;; awaiting comma or b-o-s + ((= state 4) + (cond + + ((= ?, c) + (if (= nesting 0) + (setq state 0))) + + ((string-match "[ \t\f\v\n\r]" cs) + t) + + ((= 93 c) (incf nesting)) ;; sq brack + ((= 91 c) ;; open sq brack + (decf nesting)) + + ;; handle this (extension methods), out, ref, params + ((and (>= i 5) + (string= (substring s2 (- i 5) (1+ i)) "params")) + (setf (car new) (concat "params " (car new))) + (setq i (- i 5))) + + ((and (>= i 3) + (string= (substring s2 (- i 3) (1+ i)) "this")) + (setf (car new) (concat "this " (car new))) + (setq i (- i 3))) + + ((and (>= i 2) + (string= (substring s2 (- i 2) (1+ i)) "ref")) + (setf (car new) (concat "ref " (car new))) + (setq i (- i 2))) + + ((and (>= i 2) + (string= (substring s2 (- i 2) (1+ i)) "out")) + (setf (car new) (concat "out " (car new))) + (setq i (- i 2))) + + (t + (error "unexpected char (C)")))) + ) + + (decf i)) + + (if (and (= state 3) (= nesting 0)) + (setq new (cons (substring s2 i ix2) new))) + + (concat "(" + (if new + (mapconcat 'identity new ", ") + "") + ")"))))) + + +(defun csharp--imenu-item-basic-comparer (a b) + "Compares the car of each element, assumed to be a string." + (string-lessp (car a) (car b))) + + +(defun csharp--imenu-get-method-name-from-sig (sig) + "Extract a method name with its parameter list from a method +signature, SIG. This is used to aid in sorting methods by name, +and secondarily by parameter list. + +For this input: + + private Dict DoSomething(int, string) + +...the output is: + + DoSomething(int, string) + +" + (let* (c + result + (state 0) + (len (length sig)) + (i (1- len))) + (while (> i 0) + (setq c (aref sig i)) + + (cond + ((and (= state 0) (= c 40)) + (setq state 1)) + + ((and (= state 1) (or (= c 9) (= c 32))) + (setq result (substring sig (1+ i)) + i 0))) + (decf i)) + result)) + + + +(defun csharp--imenu-item-method-name-comparer (a b) + "Compares the method names in the respective cars of each element. + +The car of each element is assumed to be a string with multiple +tokens in it, representing a method signature, including access +modifier, return type, and parameter list (surrounded by parens). +If the method takes no params, then it's just an empty pair of +parens. + +This fn extracts the method name and param list from that +signature and compares *that*. + +" + (let ((methoda (csharp--imenu-get-method-name-from-sig (car a))) + (methodb (csharp--imenu-get-method-name-from-sig (car b)))) + ;;(csharp-log -1 "compare '%s' <> '%s'" methoda methodb) + (string-lessp methoda methodb))) + + + +(defun csharp--imenu-create-index-helper (&optional parent-ns indent-level + consider-usings consider-namespaces) + "Helper fn for `csharp-imenu-create-index'. + +Scans a possibly narrowed section of a c# buffer. It finds +namespaces, classes, structs, enums, interfaces, and methods +within classes and structs. + +The way it works: it looks for an open-curly. If the open-curly +is a namespace or a class, it narrows to whatever is inside the +curlies, then recurses. + +Otherwise (the open-curly is neither of those things), this fn +tries to recognize the open-curly as the beginning of an enum, +method, or interface. + +If it succeeds, then a menu item is created for the thing. Then +it jumps to the matching close-curly, and continues. Stop when no +more open-curlies are found. + +" + + ;; A C# module consists of zero of more explicitly denoted (and + ;; possibly nested) namespaces. In the absence of an + ;; explicitly-denoted namespace, the global namespace is implicitly + ;; applied. Within each namespace there can be zero or more + ;; "container" things - like class, struct, or interface; each with + ;; zero or more indexable items - like methods, constructors. + ;; and so on. + + ;; This fn parses the module and indexes those items, creating a + ;; hierarchically organized list to describe them. Each container + ;; (ns/class/struct/etc) is represented on a separate submenu. + + ;; It works like this: + ;; (start at the top of the module) + ;; + ;; 1. look for a using clause + ;; yes - insert an item in the menu; move past all using clauses. + ;; + ;; 2. go to next open curly + ;; + ;; 2. beginning of a container? (a class or namespace) + ;; + ;; yes - narrow, and recurse + ;; + ;; no - create a menu item for the thing, whatever it is. add to + ;; the submenu. Go to the end of the thing (to the matching + ;; close curly) then goto step 1. + ;; + + (let (container-name + (pos-last-curly -1) + this-flavor + this-item + this-menu + found-usings + done) + + (while (not done) + + ;; move to the next thing + (c-forward-syntactic-ws) + (cond + ((and consider-usings + (re-search-forward (csharp--regexp 'using-stmt) (point-max) t)) + (goto-char (match-beginning 1)) + (setq found-usings t + done nil)) + + ((re-search-forward "{" (point-max) t) + (if (= pos-last-curly (point)) + (progn + ;;(csharp-log -1 "imenu: No advance? quitting (%d)" (point)) + (setq done t)) ;; haven't advanced- likely a loop + + (setq pos-last-curly (point)) + (let ((literal (csharp-in-literal))) + ;; skip over comments? + (cond + + ((memq literal '(c c++)) + (while (memq literal '(c c++)) + (end-of-line) + (forward-char 1) + (setq literal (csharp-in-literal))) + (if (re-search-forward "{" (point-max) t) + (forward-char -1) + ;;(csharp-log -1 "imenu: No more curlies (A) (%d)" (point)) + (setq done t))) + + ((eq literal 'string) + (if (re-search-forward "\"" (point-max) t) + (forward-char 1) + ;;(csharp-log -1 "imenu: Never-ending string? posn(%d)" (point)) + (setq done t))) + + (t + (forward-char -1)))))) ;; backup onto the curly + + (t + ;;(csharp-log -1 "imenu: No more curlies (B) posn(%d)" (point)) + (setq done t))) + + + (if (not done) + (cond + + ;; case 1: open curly for an array initializer + ((looking-back "\\[\\][ \t\n\r]*") + (forward-sexp 1)) + + ;; case 2: just jumped over a string + ((looking-back "\"") + (forward-char 1)) + + ;; case 3: at the head of a block of using statements + (found-usings + (setq found-usings nil + consider-usings nil) ;; only one batch + (let ((first-using (match-beginning 1)) + (count 0) + marquis + ;; don't search beyond next open curly + (limit (1- + (save-excursion + (re-search-forward "{" (point-max) t))))) + + ;; count the using statements + (while (re-search-forward (csharp--regexp 'using-stmt) limit t) + (incf count)) + + (setq marquis (if (eq count 1) "using (1)" + (format "usings (%d)" count))) + (push (cons marquis first-using) this-menu))) + + + ;; case 4: an interface or enum inside the container + ;; (must come before class / namespace ) + ((or (csharp--on-intf-open-curly-p) + (csharp--on-enum-open-curly-p)) + (setq consider-namespaces nil + consider-usings nil + this-menu + (append this-menu + (list + (cons (concat + (match-string-no-properties 1) ;; thing flavor + " " + (match-string-no-properties 2)) ;; intf name + (match-beginning 1))))) + (forward-sexp 1)) + + + ;; case 5: at the start of a container (class, namespace) + ((or (and consider-namespaces (csharp--on-namespace-open-curly-p)) + (csharp--on-class-open-curly-p) + (csharp--on-genclass-open-curly-p)) + + ;; produce a fully-qualified name for this thing + (if (string= (match-string-no-properties 1) "namespace") + (setq this-flavor (match-string-no-properties 1) + this-item (match-string-no-properties 2)) + (setq this-flavor (match-string-no-properties 2) + this-item (match-string-no-properties 3) + consider-usings nil + consider-namespaces nil)) + + (setq container-name (if parent-ns + (concat parent-ns "." this-item) + this-item)) + + ;; create a submenu + (let (submenu + (top (match-beginning 1)) + (open-curly (point)) + (close-curly (save-excursion + (forward-sexp 1) + (point)))) + (setq submenu + (list + (concat this-flavor " " container-name) + (cons "(top)" top))) + + ;; find all contained items + (save-restriction + (narrow-to-region (1+ open-curly) (1- close-curly)) + + (let* ((yok (string= this-flavor "namespace")) + (child-menu + (csharp--imenu-create-index-helper container-name + (concat indent-level " ") + yok yok))) + (if child-menu + (setq submenu + (append submenu + (sort child-menu + 'csharp--imenu-item-basic-comparer)))))) + (setq submenu + (append submenu + (list (cons "(bottom)" close-curly)))) + + (setq this-menu + (append this-menu (list submenu))) + + (goto-char close-curly))) + + + ;; case 6: a property + ((csharp--on-prop-open-curly-p) + (setq consider-namespaces nil + consider-usings nil + this-menu + (append this-menu + (list + (cons (concat + "prop " + (match-string-no-properties 3)) ;; prop name + (match-beginning 1))))) + (forward-sexp 1)) + + + ;; case 7: an indexer + ((csharp--on-indexer-open-curly-p) + (setq consider-namespaces nil + consider-usings nil + this-menu + (append this-menu + (list + (cons (concat + "indexer " + (match-string-no-properties 4)) ;; index type + (match-beginning 1))))) + (forward-sexp 1)) + + + ;; case 8: a constructor inside the container + ((csharp--on-ctor-open-curly-p) + (setq consider-namespaces nil + consider-usings nil + this-menu + (append this-menu + (list + (cons (concat + "ctor " + (match-string-no-properties 2) ;; ctor name + (csharp--imenu-remove-param-names-from-paramlist + (match-string-no-properties 3))) ;; ctor params + (match-beginning 1))))) + (forward-sexp 1)) + + + ;; case 9: a method inside the container + ((csharp--on-defun-open-curly-p) + (setq consider-namespaces nil + consider-usings nil + this-menu + (append this-menu + (list + (cons (concat + "method " + (match-string-no-properties 2) ;; return type + " " + (match-string-no-properties 3) ;; func name + (csharp--imenu-remove-param-names-from-paramlist + (match-string-no-properties 4))) ;; fn params + (match-beginning 1))))) + (forward-sexp 1)) + + + ;; case 10: unknown open curly - just jump over it. + ((looking-at "{") + (forward-sexp 1)) + + ;; case 11: none of the above. shouldn't happen? + (t + (forward-char 1))))) + + this-menu)) + + +;; ======================================================= +;; DPC Thu, 19 May 2011 11:25 +;; There are two challenges with the imenu support: generating the +;; index, and generating a reasonable display for the index. The index +;; generation is pretty straightforward: use regexi to locate +;; interesting stuff in the buffer. +;; +;; The menu generation is a little trickier. Long lists of methods +;; mixed with properties and interfaces (etc) will be displayed in the +;; menu but will look Very Bad. Better to organize the menu into +;; submenus, organized primarily by category. Also the menus should be +;; sorted, for ease of human scanning. The next section of logic is +;; designed to do the stuff for the menu generation. + + +(defcustom csharp-imenu-max-similar-items-before-extraction 6 + "The maximum number of things of a particular +category (constructor, property, method, etc) that will be +separely displayed on an imenu without factoring them into a +separate submenu. + +For example, if a module has 3 consructors, 5 methods, and 7 +properties, and the value of this variable is 4, then upon +refactoring, the constructors will remain in the toplevel imenu +and the methods and properties will each get their own +category-specific submenu. + +See also `csharp-imenu-min-size-for-sub-submenu'. + +For more information on how csharp-mode uses imenu, +see `csharp-want-imenu', and `csharp-mode'. +" + :type 'integer + :group 'csharp) + + +(defcustom csharp-imenu-min-size-for-sub-submenu 18 + "The minimum number of imenu items of a particular +category (constructor, property, method, etc) that will be +broken out into sub-submenus. + +For example, if a module has 28 properties, then the properties will +be placed in a submenu, and then that submenu with be further divided +into smaller submenus. + +See also `csharp-imenu-max-similar-items-before-extraction' + +For more information on how csharp-mode uses imenu, +see `csharp-want-imenu', and `csharp-mode'. +" + :type 'integer + :group 'csharp) + + +(defun csharp--first-word (s) + "gets the first word from the given string. +It had better be a string!" + (car (split-string s nil t))) + + +(defun csharp--make-plural (s) + "make a word plural. For use within the generated imenu." + (cond + ((string= s "prop") "properties") + ((string= s "class") "classes") + ((string= s "ctor") "constructors") + (t (concat s "s")))) + + +(defun csharp--imenu-counts (list) + "Returns an alist, each item is a cons cell where the car is a +unique first substring of an element of LIST, and the cdr is the +number of occurrences of that substring in elements in the +list. + +For a complicated imenu generated for a large C# module, the result of +this fn will be something like this: + + ((\"(top)\" . 1) + (\"properties\" . 38) + (\"methods\" . 12) + (\"constructors\" . 7) + (\"(bottom)\" . 1)) + +" + (flet ((helper (list new) + (if (null list) new + (let* ((elt (car list)) + (topic (csharp--make-plural (csharp--first-word (car elt)))) + (xelt (assoc topic new))) + (helper (cdr list) + (if xelt + (progn (incf (cdr xelt)) new) + (cons (cons topic 1) new))))))) + (nreverse (helper list nil)))) + + + +(defun csharp--imenu-get-submenu-size (n) + "Gets the preferred size of submenus given N, the size of the +flat, unparceled menu. + +Suppose there are 50 properties in a given C# module. This fn maps +from that number, to the maximum size of the submenus into which the +large set of properties should be broken. + +Currently the submenu size for 50 is 12. To change this, change +the lookup table. + +The reason it's a lookup table and not a simple arithmetic +function: I think it would look silly to have 2 submenus each +with 24 items. Sixteen or 18 items on a submenu seems fine when +you're working through 120 items total. But if you have only 28 +items, better to have 3 submenus with 10 and 9 items each. So +it's not a linear function. That's what this lookup tries to do. + +" + (let ((size-pairs '((100 . 22) + (80 . 20) + (60 . 18) + (40 . 15) + (30 . 14) + (24 . 11) + (0 . 9))) + elt + (r 0)) + + (while (and size-pairs (eq r 0)) + (setq elt (car size-pairs)) + (if (> n (car elt)) + (setq r (cdr elt))) + (setq size-pairs (cdr size-pairs))) + r)) + + + +(defun csharp--imenu-remove-category-names (menu-list) + "Input is a list, each element is (LABEL . LOCATION). This fn +returns a modified list, with the first word - the category name +- removed from each label. + +" + (mapcar (lambda (elt) + (let ((tokens (split-string (car elt) "[ \t]" t))) + (cons (mapconcat 'identity (cdr tokens) " ") + (cdr elt)))) + menu-list)) + +(defun string-indexof (s c) + "Returns the index of the first occurrence of character C in string S. +Returns nil if not found. + +See also, `string-lastindexof' + +" + (let ((len (length s)) + (i 0) ix c2) + (while (and (< i len) (not ix)) + (setq c2 (aref s i)) + (if (= c c2) + (setq ix i)) + (incf i)) + ix)) + +(defun string-lastindexof (s c) + "Returns the index of the last occurrence of character C in string S. +Returns nil if not found. + +See also, `string-indexof' + +" + (let ((i (length s)) + ix c2) + (while (and (>= i 0) (not ix)) + (setq c2 (aref s i)) + (if (= c c2) + (setq ix i)) + (decf i)) + ix)) + + +(defun csharp--imenu-submenu-label (sig flavor) + "generate a submenu label from the given signature, SIG. +The sig is a method signature, property type-and-name, +constructor, and so on, indicated by FLAVOR. + +This fn returns a simple name that can be used in the label for a +break out submenu. + +" + (if (string= flavor "method") + (let ((method-name (csharp--imenu-get-method-name-from-sig sig))) + (substring method-name 0 (string-indexof method-name 40))) + (substring sig (1+ (string-lastindexof sig 32))))) + + + + +(defun csharp--imenu-break-one-menu-into-submenus (menu-list) + "Parcels a flat list MENU-LIST up into smaller sublists. It tries +to balance the number of sublists and the size of each sublist. + +The max size of any sublist will be about 20 (arbitrary) and the +min size will be 7 or so. See `csharp--imenu-get-submenu-size' +for how this is done. + +It does this destructively, using `nbutlast'. + +Returns a new list, containing sublists. +" + + (let ((len (length menu-list)) + (counts (csharp--imenu-counts menu-list))) + + (cond + ;; a small number, and all the same flavor + ((and (< len csharp-imenu-min-size-for-sub-submenu) (= (length counts) 1)) + (csharp--imenu-remove-category-names + (sort menu-list + (if (string= (caar counts) "methods") + 'csharp--imenu-item-method-name-comparer + 'csharp--imenu-item-basic-comparer)))) + + ;; is the length already pretty short? + ((< len csharp-imenu-min-size-for-sub-submenu) + menu-list) + + ((/= (length counts) 1) + menu-list) + + (t + (let* ((lst (sort menu-list + (if (string= (caar counts) "methods") + 'csharp--imenu-item-method-name-comparer + 'csharp--imenu-item-basic-comparer))) + new + (sz (csharp--imenu-get-submenu-size len)) ;; goal max size of sublist + (n (ceiling (/ (* 1.0 len) sz))) ;; total number of sublists + (adj-sz (ceiling (/ (* 1.0 len) n))) ;; maybe a little less than sz + (nsmall (mod (- adj-sz (mod len adj-sz)) adj-sz)) ;; num of (n-1) lists + (i 0) + (base-name (csharp--first-word (caar lst))) + label + chunksz + this-chunk) + + (while lst + (setq chunksz (if (> nsmall i) (1- adj-sz) adj-sz) + this-chunk (csharp--imenu-remove-category-names + (nthcdr (- len chunksz) lst)) + lst (nbutlast lst chunksz) + ;;label (format "%s %d" plural-name (- n i)) + label (concat "from " (csharp--imenu-submenu-label (caar this-chunk) base-name)) + new (cons (cons label this-chunk) new) + len (- len chunksz)) + (incf i)) + new))))) + + + +(defun csharp--imenu-break-into-submenus (menu-list) + "For an imenu menu-list with category-based submenus, +possibly break a submenu into smaller sublists, based on size. + +" + (mapcar (lambda (elt) + (if (imenu--subalist-p elt) + (cons (car elt) + (csharp--imenu-break-one-menu-into-submenus (cdr elt))) + elt)) + menu-list)) + + + + + +(defun csharp--imenu-reorg-alist-intelligently (menu-alist) + "Accepts an imenu alist. Returns an alist, reorganized. +Things get sorted, factored out into category submenus, +and split into multiple submenus, where conditions warrant. + +For example, suppose this imenu alist is generated from a scan: + + ((\"usings (4)\" . 1538) + (\"namespace Ionic.Zip\" + (\"(top)\" . 1651) + (\"partial class Ionic.Zip.ZipFile\" + (\"(top)\" . 5473) + (\"prop FullScan\" . 8036) + ... + (\"prop Comment\" . 21118) + (\"prop Verbose\" . 32278) + (\"method override String ToString\" . 96577) + (\"method internal void NotifyEntryChanged\" . 97608) + .... + (\"method internal void Reset\" . 98231) + (\"ctor ZipFile\" . 103598) + ... + (\"ctor ZipFile\" . 109723) + (\"ctor ZipFile\" . 116487) + (\"indexer int\" . 121232) + (\"indexer String\" . 124933) + (\"(bottom)\" . 149777)) + (\"public enum Zip64Option\" . 153839) + (\"enum AddOrUpdateAction\" . 154815) + (\"(bottom)\" . 154893))) + + +This is displayed as a toplevel menu with 2 items; the namespace +menu has 5 items (top, bottom, the 2 enums, and the class). The +class menu has 93 items. It needs to be reorganized to be more usable. + +After transformation of the alist through this fn, the result is: + + ((\"usings (4)\" . 1538) + (\"namespace Ionic.Zip\" + (\"(top)\" . 1651) + (\"partial class Ionic.Zip.ZipFile\" + (\"(top)\" . 5473) + (\"properties\" + (\"WriteStream\" . 146489) + (\"Count\" . 133827) + .... + (\"BufferSize\" . 12837) + (\"FullScan\" . 8036)) + (\"methods\" + (\"virtual void Dispose\" . 144389) + (\"void RemoveEntry\" . 141027) + .... + (\"method override String ToString\" . 96577) + (\"method bool ContainsEntry\" . 32517)) + (\"constructors\" + (\"ZipFile\" . 116487) + .... + (\"ZipFile\" . 105698) + (\"ZipFile\" . 103598)) + (\"indexer int\" . 121232) + (\"indexer String\" . 124933) + (\"(bottom)\" . 149777)) + (\"public enum Zip64Option\" . 153839) + (\"enum AddOrUpdateAction\" . 154815) + (\"(bottom)\" . 154893))) + +All menus are the same except the class menu, which has been +organized into subtopics, each of which gets its own cascaded +submenu. If the submenu itself holds more than +`csharp-imenu-max-similar-items-before-extraction' items that are +all the same flavor (properties, methods, etc), thos get split +out into multiple submenus. + +" + (let ((counts (csharp--imenu-counts menu-alist))) + (flet ((helper + (list new) + (if (null list) + new + (let* ((elt (car list)) + (topic (csharp--make-plural (csharp--first-word (car elt)))) + (xelt (assoc topic new))) + (helper + (cdr list) + (if xelt + (progn + (rplacd xelt (cons elt (cdr xelt))) + new) + (cons + + (cond + ((> (cdr (assoc topic counts)) + csharp-imenu-max-similar-items-before-extraction) + (cons topic (list elt))) + + ((imenu--subalist-p elt) + (cons (car elt) + (csharp--imenu-reorg-alist-intelligently (cdr elt)))) + (t + elt)) + + new))))))) + + (csharp--imenu-break-into-submenus + (nreverse (helper menu-alist nil)))))) + + + + +(defun csharp-imenu-create-index () + "This function is called by imenu to create an index for the +current C# buffer, conforming to the format specified in +`imenu--index-alist' . + +See `imenu-create-index-function' for background information. + +To produce the index, which lists the classes, functions, +methods, and properties for the current buffer, this function +scans the entire buffer. + +This can take a long time for a large buffer. The scan uses +regular expressions that attempt to match on the general-case C# +syntax, for classes and functions, generic types, base-classes, +implemented interfaces, and so on. This can be time-consuming. +For a large source file, say 160k, it can take 10 seconds or more. +The UI hangs during the scan. + +imenu calls this fn when it feels like it, I suppose when it +thinks the buffer has been updated. The user can also kick it off +explicitly by selecting *Rescan* from the imenu menu. + +After generating the hierarchical list of props, methods, +interfaces, classes, and namespaces, csharp-mode re-organizes the +list as appropriate: + + - it extracts sets of like items into submenus. All properties + will be placed on a submenu. See + `csharp-imenu-max-similar-items-before-extraction' for a way + to tune this. + + - it converts those submenus into sub-submenus, if there are more than + `csharp-imenu-min-size-for-sub-submenu' items. + + - it sorts each set of items on the outermost menus lexicographically. + +The result of these transformations is what is provided to imenu +to generate the visible menus. Just FYI - the reorganization of +the scan results is much much faster than the actual generation +of the scan results. If you're looking to save time, the re-org +logic is not where the cost is. + +imenu itself likes to sort the menus. See `imenu--split-menu' and +also `csharp--imenu-split-menu-patch', which is advice that +attempts to disable the weird re-jiggering that imenu performs. + +" + ;; I think widen/narrow causes the buffer to be marked as + ;; modified. This is a bit surprising, but I have no other + ;; explanation for the source of the problem. + ;; So I use `c-save-buffer-state' so that the buffer is not + ;; marked modified when the scan completes. + + (c-save-buffer-state () + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + + (let ((index-alist + (csharp--imenu-create-index-helper nil "" t t))) + + (csharp--imenu-reorg-alist-intelligently index-alist) + + ;;index-alist + + ;; What follows is No longer used. + ;; ======================================================= + + ;; If the index menu contains exactly one element, and it is + ;; a namespace menu, then remove it. This simplifies the + ;; menu, and results in no loss of information: all types + ;; get fully-qualified names anyway. This will probably + ;; cover the majority of cases; often a C# source module + ;; defines either one class, or a set of related classes + ;; inside a single namespace. + + ;; To remove that namespace, we need to prune & graft the tree. + ;; Remove the ns hierarchy level, but also remove the 1st and + ;; last elements in the sub-menu, which represent the top and + ;; bottom of the namespace. + + ;; (if (and + ;; (= 1 (length index-alist)) + ;; (consp (car index-alist)) + ;; (let ((tokens (split-string + ;; (car (car index-alist)) + ;; "[ \t]" t))) + ;; (and (<= 1 (length tokens)) + ;; (string= (downcase + ;; (nth 0 tokens)) "namespace")))) + ;; + ;; (let (elt + ;; (newlist (cdar index-alist))) + ;; (setf (car (car newlist)) (car (car index-alist))) + ;; newlist) + ;; + ;; index-alist) + + ))))) + + +;; ================================================================== + + + + +;; ================================================================== +;; C# code-doc insertion magic +;; ================================================================== +;; +;; In Visual Studio, if you type three slashes, it immediately expands into +;; an inline code-documentation fragment. The following method does the +;; same thing. +;; +;; This is the kind of thing that could be handled by YASnippet or +;; another similarly flexible snippet framework. But I don't want to +;; introduce a dependency on yasnippet to csharp-mode. So the capability +;; must live within csharp-mode itself. + +(defun csharp-maybe-insert-codedoc (arg) + + "Insert an xml code documentation template as appropriate, when +typing slashes. This fn gets bound to / (the slash key), in +csharp-mode. If the slash being inserted is not the third +consecutive slash, the slash is inserted as normal. If it is the +third consecutive slash, then a xml code documentation template +may be inserted in some cases. For example, + + a template is inserted if the prior line is empty, + or contains only an open curly brace; + a template is inserted if the prior word + closes the element; + a template is inserted if the prior word + closes the element; + an template is inserted if the prior word closes + the element; + a template is inserted if the prior word closes + a element. + +In all other cases the slash is inserted as normal. + +If you want the default cc-mode behavior, which implies no automatic +insertion of xml code documentation templates, then use this in +your `csharp-mode-hook' function: + + (local-set-key (kbd \"/\") 'c-electric-slash) + + " + (interactive "*p") + ;;(message "csharp-maybe-insert-codedoc") + (let ( + (cur-point (point)) + (char last-command-event) + (cb0 (char-before (- (point) 0))) + (cb1 (char-before (- (point) 1))) + is-first-non-whitespace + did-auto-insert + ) + + ;; check if two prior chars were slash, in other words, + ;; check if this is the third slash in a row. + (if (and (= char ?/) cb0 (= ?/ cb0) cb1 (= ?/ cb1)) + + (progn + ;;(message "yes - this is the third consecutive slash") + (setq is-first-non-whitespace + (save-excursion + (back-to-indentation) + (= cur-point (+ (point) 2)))) + + (if is-first-non-whitespace + ;; This is a 3-slash sequence. It is the first non-whitespace text + ;; on the line. Now we need to examine the surrounding context + ;; in order to determine which xml cod doc template to insert. + (let (word-back char0 char1 + word-fore char-0 char-1 + text-to-insert ;; text to insert in lieu of slash + fn-to-call ;; func to call after inserting text + (preceding-line-is-empty (or + (= (line-number-at-pos) 1) + (save-excursion + (forward-line -1) + (beginning-of-line) + (looking-at "[ \t]*$\\|[ \t]*{[ \t]*$")))) + (flavor 0) ;; used only for diagnostic purposes + ) + + ;;(message "starting a 3-slash comment") + ;; get the prior word, and the 2 chars preceding it. + (backward-word) + + (setq word-back (thing-at-point 'word) + char0 (char-before (- (point) 0)) + char1 (char-before (- (point) 1))) + + ;; restore prior position + (goto-char cur-point) + + ;; get the following word, and the 2 chars preceding it. + (forward-word) + (backward-word) + (setq word-fore (thing-at-point 'word) + char-0 (char-before (- (point) 0)) + char-1 (char-before (- (point) 1))) + + ;; restore prior position again + (goto-char cur-point) + + (cond + ;; The preceding line is empty, or all whitespace, or + ;; contains only an open-curly. In this case, insert a + ;; summary element pair. + (preceding-line-is-empty + (setq text-to-insert "/ \n/// \n/// " + flavor 1) ) + + ;; The preceding word closed a summary element. In this case, + ;; if the forward word does not open a remarks element, then + ;; insert a remarks element. + ((and (string-equal word-back "summary") (eq char0 ?/) (eq char1 ?<)) + (if (not (and (string-equal word-fore "remarks") (eq char-0 ?<))) + (setq text-to-insert "/ \n/// \n/// \n/// \n/// " + flavor 2))) + + ;; The preceding word closed the remarks section. In this case, + ;; insert an example element. + ((and (string-equal word-back "remarks") (eq char0 ?/) (eq char1 ?<)) + (setq text-to-insert "/ \n/// \n/// " + flavor 3)) + + ;; The preceding word closed the example section. In this + ;; case, insert an returns element. This isn't always + ;; correct, because sometimes the xml code doc is attached to + ;; a class or a property, neither of which has a return + ;; value. A more intelligent implementation would inspect the + ;; syntax state and only inject a returns element if + ;; appropriate. + ((and (string-equal word-back "example") (eq char0 ?/) (eq char1 ?<)) + (setq text-to-insert "/ " + fn-to-call (lambda () + (backward-word) + (backward-char) + (backward-char) + (c-indent-line-or-region) + ) + flavor 4)) + + ;; The preceding word opened the remarks section, or it + ;; closed a para section. In this case, insert a para + ;; element, using appropriate indentation with respect to the + ;; prior tag. + ((or + (and (string-equal word-back "remarks") (eq char0 ?<) (or (eq char1 32) (eq char1 9))) + (and (string-equal word-back "para") (eq char0 ?/) (eq char1 ?<))) + + (let (prior-point spacer) + (save-excursion + (backward-word) + (backward-char) + (backward-char) + (setq prior-point (point)) + (skip-chars-backward "\t ") + (setq spacer (buffer-substring (point) prior-point)) + ;;(message (format "pt(%d) prior(%d) spacer(%s)" (point) prior-point spacer)) + ) + + (if (string-equal word-back "remarks") + (setq spacer (concat spacer " "))) + + (setq text-to-insert (format "/%s\n///%s \n///%s" + spacer spacer spacer) + flavor 6))) + + ;; The preceding word opened a para element. In this case, if + ;; the forward word does not close the para element, then + ;; close the para element. + ;; -- + ;; This is a nice idea but flawed. Suppose I have a para element with some + ;; text in it. If I position the cursor at the first line, then type 3 slashes, + ;; I get a close-element, and that would be inappropriate. Not sure I can + ;; easily solve that problem, so the best thing might be to simply punt, and + ;; require people to close their own elements. + ;; + ;; ( (and (string-equal word-back "para") (eq char0 60) (or (eq char1 32) (eq char1 9))) + ;; (if (not (and (string-equal word-fore "para") (eq char-0 47) (eq char-1 60) )) + ;; (setq text-to-insert "/ \n/// \n///" + ;; fn-to-call (lambda () + ;; (previous-line) + ;; (end-of-line) + ;; ) + ;; flavor 7) ) + ;; ) + + ;; the default case - do nothing + (t nil)) + + (if text-to-insert + (progn + ;;(message (format "inserting special text (f(%d))" flavor)) + + ;; set the flag, that we actually inserted text + (setq did-auto-insert t) + + ;; save point of beginning of insertion + (setq cur-point (point)) + + ;; actually insert the text + (insert text-to-insert) + + ;; indent the inserted string, and re-position point, either through + ;; the case-specific fn, or via the default progn. + (if fn-to-call + (funcall fn-to-call) + + (let ((newline-count 0) (pos 0) ix) + + ;; count the number of newlines in the inserted string + (while (string-match "\n" text-to-insert pos) + (setq pos (match-end 0) + newline-count (+ newline-count 1) ) + ) + + ;; indent what we just inserted + (c-indent-region cur-point (point) t) + + ;; move up n/2 lines. This assumes that the + ;; inserted text is ~symmetric about the halfway point. + ;; The assumption holds if the xml code doc uses a + ;; begin-elt and end-elt on a new line all by themselves, + ;; and a blank line in between them where the point should be. + ;; A more intelligent implementation would use a specific + ;; marker string, like @@DOT, to note the desired point. + (forward-line (- 0 (/ newline-count 2))) + (end-of-line))))))))) + + (if (not did-auto-insert) + (self-insert-command (prefix-numeric-value arg))))) + +;; ================================================================== +;; end of c# code-doc insertion magic +;; ================================================================== + + + + +;; ================================================================== +;; c# fontification extensions +;; ================================================================== +;; Commentary: +;; +;; The purpose of the following code is to fix font-lock for C#, +;; specifically for the verbatim-literal strings. C# is a cc-mode +;; language and strings are handled mostly like other c-based +;; languages. The one exception is the verbatim-literal string, which +;; uses the syntax @"...". +;; +;; `parse-partial-sexp' treats those strings as just regular strings, +;; with the @ a non-string character. This is fine, except when the +;; verblit string ends in a slash, in which case, font-lock breaks from +;; that point onward in the buffer. +;; +;; This is an attempt to fix that. +;; +;; The idea is to scan the buffer in full for verblit strings, and apply the +;; appropriate syntax-table text properties for verblit strings. Also setting +;; `parse-sexp-lookup-properties' to t tells `parse-partial-sexp' +;; to use the syntax-table text properties set up by the scan as it does +;; its parse. +;; +;; Also need to re-scan after any changes in the buffer, but on a more +;; limited region. +;; + + +;; ;; I don't remember what this is supposed to do, +;; ;; or how I figured out the value. +;; ;; +;; (defconst csharp-font-lock-syntactic-keywords +;; '(("\\(@\\)\\(\"\\)[^\"]*\\(\"\\)\\(\"\\)[^\"]*\\(\"\\)[^\"]" +;; (1 '(6)) (2 '(7)) (3 '(1)) (4 '(1)) (5 '(7)) +;; )) +;; "Highlighting of verbatim literal strings. See also the variable +;; `font-lock-keywords'.") + + + +(defun csharp-time () + "returns the time of day as a string. Used in the `csharp-log' function." + (substring (current-time-string) 11 19)) ;24-hr time + + +(defun csharp-log (level text &rest args) + "Log a message at level LEVEL. +If LEVEL is higher than `csharp-log-level', the message is +ignored. Otherwise, it is printed using `message'. +TEXT is a format control string, and the remaining arguments ARGS +are the string substitutions (see `format')." + (if (<= level csharp-log-level) + (let* ((msg (apply 'format text args))) + (message "C# %s %s" (csharp-time) msg)))) + + + +(defun csharp-max-beginning-of-stmt () + "Return the greater of `c-beginning-of-statement-1' and +`c-beginning-of-statement' . I don't understand why both of +these methods are necessary or why they differ. But they do." + + (let (dash + nodash + (curpos (point))) + + ;; I think this may need a save-excursion... + ;; Calling c-beginning-of-statement-1 resets the point! + + (setq dash (progn (c-beginning-of-statement-1) (point))) + (csharp-log 3 "max-bostmt dash(%d)" dash) + (goto-char curpos) + + (setq nodash (progn (c-beginning-of-statement 1) (point))) + (csharp-log 3 "max-bostmt nodash(%d)" nodash) + (goto-char curpos) + + (max dash nodash))) + + + + + +(defun csharp-set-vliteral-syntax-table-properties (beg end) + "Scan the buffer text between BEG and END, a verbatim literal +string, setting and clearing syntax-table text properties where +necessary. + +We need to modify the default syntax-table text property in these cases: + (backslash) - is not an escape inside a verbatim literal string. + (double-quote) - can be a literal quote, when doubled. + +BEG is the @ delimiter. END is the 'old' position of the ending quote. + +see http://www.sunsite.ualberta.ca/Documentation/Gnu/emacs-lisp-ref-21-2.7/html_node/elisp_592.html +for the list of syntax table numeric codes. + +" + + (csharp-log 3 "set-vlit-syntax-table: beg(%d) end(%d)" beg end) + + (if (and (> beg 0) (> end 0)) + + (let ((curpos beg) + (state 0)) + + (c-clear-char-properties beg end 'syntax-table) + + (while (<= curpos end) + + (cond + ((= state 0) + (if (= (char-after curpos) ?@) + (progn + (c-put-char-property curpos 'syntax-table '(6)) ; (6) = expression prefix, (3) = symbol + ;;(message (format "set-s-t: prefix pos(%d) chr(%c)" beg (char-after beg))) + ) + ) + (setq state (+ 1 state))) + + ((= state 1) + (if (= (char-after curpos) ?\") + (progn + (c-put-char-property curpos 'syntax-table '(7)) ; (7) = string quote + ;;(message (format "set-s-t: open quote pos(%d) chr(%c)" + ;; curpos (char-after curpos))) + )) + (setq state (+ 1 state))) + + ((= state 2) + (cond + ;; handle backslash inside the string + ((= (char-after curpos) ?\\) + (c-put-char-property curpos 'syntax-table '(2)) ; (1) = punctuation, (2) = word + ;;(message (format "set-s-t: backslash word pos(%d) chr(%c)" curpos (char-after curpos))) + ) + + ;; doubled double-quote + ((and + (= (char-after curpos) ?\") + (= (char-after (+ 1 curpos)) ?\")) + (c-put-char-property curpos 'syntax-table '(2)) ; (1) = punctuation, (2) = word + (c-put-char-property (+ 1 curpos) 'syntax-table '(2)) ; (1) = punctuation + ;;(message (format "set-s-t: double doublequote pos(%d) chr(%c)" curpos (char-after curpos))) + (setq curpos (+ curpos 1)) + ) + + ;; a single double-quote, which should be a string terminator + ((= (char-after curpos) ?\") + (c-put-char-property curpos 'syntax-table '(7)) ; (7) = string quote + ;;(message (format "set-s-t: close quote pos(%d) chr(%c)" curpos (char-after curpos))) + ;;go no further + (setq state (+ 1 state))) + + ;; everything else + (t + ;;(message (format "set-s-t: none pos(%d) chr(%c)" curpos (char-after curpos))) + nil)))) + ;; next char + (setq curpos (+ curpos 1)))))) + + + +(defun csharp-end-of-verbatim-literal-string (&optional lim) + "Moves to and returns the position of the end quote of the verbatim literal +string. When calling, point should be on the @ of the verblit string. +If it is not, then no movement is performed and `point' is returned. + +This function ignores text properties. In fact it is the +underlying scanner used to set the text properties in a C# buffer. +" + + (csharp-log 3 "end-of-vlit-string: point(%d) c(%c)" (point) (char-after)) + + (let (curpos + (max (or lim (point-max)))) + + (if (not (looking-at "@\"")) + (point) + (forward-char 2) ;; pass up the @ sign and first quote + (setq curpos (point)) + + ;; Within a verbatim literal string, a doubled double-quote + ;; escapes the double-quote." + (while (and ;; process characters... + (or ;; while... + (not (eq (char-after curpos) ?\")) ;; it's not a quote + (eq (char-after (+ curpos 1)) ?\")) ;; or, its a double (double) quote + (< curpos max)) ;; and we're not done yet + + (cond + ((and (eq (char-after curpos) ?\") ;; it's a double-quote. + (eq (char-after (+ curpos 1)) ?\")) + (setq curpos (+ 2 curpos))) ;; Skip 2 + (t ;; anything else + (setq curpos (+ 1 curpos))))) ;; skip fwd 1 + curpos))) + + + + +(defun csharp-scan-for-verbatim-literals-and-set-props (&optional beg end) + "Scans the buffer, between BEG and END, for verbatim literal +strings, and sets override text properties on each string to +allow proper syntax highlighting, indenting, and cursor movement. + +BEG and END define the limits of the scan. When nil, they +default to `point-min' and `point-max' respectively. + +Setting text properties generally causes the buffer to be marked +as modified, but this fn suppresses that via the +`c-buffer-save-state' macro, for any changes in text properties +that it makes. This fn also ignores the read-only setting on a +buffer, using the same macro. + +This fn is called when a csharp-mode buffer is loaded, with BEG +and END set to nil, to do a full scan. It is also called on +every buffer change, with the BEG and END set to the values for +the change. + +The return value is nil if the buffer was not a csharp-mode +buffer. Otherwise it is the last cursor position examined by the +scan. +" + + (if (not (c-major-mode-is 'csharp-mode)) ;; don't scan if not csharp mode + nil + (save-excursion + (c-save-buffer-state + ((curpos (or beg (point-min))) + (lastpos (or end (point-max))) + (state 0) (start 0) (cycle 0) + literal eos limits) + + (csharp-log 3 "verblit scan") + (goto-char curpos) + + (while (and (< curpos lastpos) (< cycle 10000)) + (cond + + ;; Case 1: current char is a @ sign + ;; -------------------------------------------- + ;; Check to see if it demarks the beginning of a verblit + ;; string. + ((= ?@ (char-after curpos)) + + ;; are we in a comment? a string? Maybe the @ is a prefix + ;; to allow the use of a reserved word as a symbol. Let's find out. + + ;; not sure why I need both of the following. + (syntax-ppss-flush-cache 1) + (parse-partial-sexp 1 curpos) + (goto-char curpos) + (setq literal (csharp-in-literal)) + (cond + + ;; Case 1.A: it's a @ within a string. + ;; -------------------------------------------- + ;; This should never happen, because this scanner hops over strings. + ;; But it might happen if the scan starts at an odd place. + ((eq literal 'string) nil) + + ;; Case 1.B: The @ is within a comment. Hop over it. + ((and (memq literal '(c c++)) + ;; This is a kludge for XEmacs where we use + ;; `buffer-syntactic-context', which doesn't correctly + ;; recognize "\*/" to end a block comment. + ;; `parse-partial-sexp' which is used by + ;; `c-literal-limits' will however do that in most + ;; versions, which results in that we get nil from + ;; `c-literal-limits' even when `c-in-literal' claims + ;; we're inside a comment. + ;;(setq limits (c-literal-limits start))) + (setq limits (c-literal-limits))) + + ;; advance to the end of the comment + (if limits + (progn + (csharp-log 4 "scan: jump end comment A (%d)" (cdr limits)) + (setq curpos (cdr limits))))) + + + ;; Case 1.B: curpos is at least 2 chars before the last + ;; position to examine, and, the following char is a + ;; double-quote (ASCII 34). + ;; -------------------------------------------- + ;; This looks like the beginning of a verbatim string + ;; literal. + ((and (< (+ 2 curpos) lastpos) + (= ?\" (char-after (+ 1 curpos)))) + + (setq eos (csharp-end-of-verbatim-literal-string)) + ;; set override syntax properties on the verblit string + (csharp-set-vliteral-syntax-table-properties curpos eos) + + (csharp-log 4 "scan: jump end verblit string (%d)" eos) + (setq curpos eos)))) + + + ;; Case 2: current char is a double-quote. + ;; -------------------------------------------- + ;; If this is a string, we hop over it, on the assumption that + ;; this scanner need not bother with regular literal strings, which + ;; get the proper syntax with the generic approach. + ;; If in a comment, hop over the comment. + ((= ?\" (char-after curpos)) + (goto-char curpos) + (setq literal (c-in-literal)) + (cond + + ;; Case 2.A: a quote within a string + ;; -------------------------------------------- + ;; This shouldn't happen, because we hop over strings. + ;; But it might. + ((eq literal 'string) nil) + + ;; Case 2.B: a quote within a comment + ;; -------------------------------------------- + ((and (memq literal '(c c++)) + ;; This is a kludge for XEmacs where we use + ;; `buffer-syntactic-context', which doesn't correctly + ;; recognize "\*/" to end a block comment. + ;; `parse-partial-sexp' which is used by + ;; `c-literal-limits' will however do that in most + ;; versions, which results in that we get nil from + ;; `c-literal-limits' even when `c-in-literal' claims + ;; we're inside a comment. + ;;(setq limits (c-literal-limits start))) + (setq limits (c-literal-limits))) + + ;; advance to the end of the comment + (if limits + (progn + (setq curpos (cdr limits)) + (csharp-log 3 "scan: jump end comment B (%s)" curpos)))) + + + ;; Case 2.C: Not in a comment, and not in a string. + ;; -------------------------------------------- + ;; This is the beginning of a literal (but not verbatim) string. + (t + (forward-char 1) ;; pass up the quote + (if (consp (setq limits (c-literal-limits))) + (progn + (csharp-log 4 "scan: jump end literal (%d)" (cdr limits)) + (setq curpos (cdr limits)))))))) + + (setq cycle (+ 1 cycle)) + (setq curpos (+ 1 curpos)) + (c-safe (goto-char curpos))))))) + + + +(defun csharp--before-font-lock (beg end old-len) + "Adjust`syntax-table' properties on the region affected by the change +in a csharp-mode buffer. + +This function is the C# value for `c-before-font-lock-function'. +It intended to be called only by the cc-mode runtime. + +It prepares the buffer for font locking, hence must get called +before `font-lock-after-change-function'. + +It does hidden buffer changes. + +BEG, END and OLD-LEN have the same meaning here as for any +after-change function. + +Point is undefined both before and after this function call. +The return value is meaningless, and is ignored by cc-mode. +" + (csharp-log 2 "before font lock %d %d %d %d" beg end old-len (point)) + (let ((start-scan (progn + ;; is this right? I think + (c-beginning-of-statement 1) + (point)))) + (csharp-scan-for-verbatim-literals-and-set-props start-scan end))) + + + +(c-lang-defconst c-before-font-lock-function + csharp 'csharp--before-font-lock) + +;; ================================================================== +;; end of c# fontification extensions +;; ================================================================== + + + + + +;; ================================================================== +;; C#-specific optimizations of cc-mode funcs +;; ================================================================== + +;; There's never a need to move over an Obj-C directive in csharp-mode. +(defadvice c-forward-objc-directive (around + csharp-mode-advice-2 + compile activate) + (if (c-major-mode-is 'csharp-mode) + nil + ad-do-it) + ) + +;; ================================================================== +;; end of C#-specific optimizations of cc-mode funcs +;; ================================================================== + + + + + + + + +;; ================================================================== +;; c# - monkey-patching of basic parsing logic +;; ================================================================== +;; +;; The following 2 defuns redefine functions from cc-mode, to add +;; special cases for C#. These primarily deal with indentation of +;; instance initializers, which are somewhat unique to C#. I couldn't +;; figure out how to get cc-mode to do what C# needs, without modifying +;; these defuns. +;; + +(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end) + ;; Return non-nil if we're looking at the beginning of a block + ;; inside an expression. The value returned is actually a cons of + ;; either 'inlambda, 'inexpr-statement or 'inexpr-class and the + ;; position of the beginning of the construct. + ;; + ;; LIM limits the backward search. CONTAINING-SEXP is the start + ;; position of the closest containing list. If it's nil, the + ;; containing paren isn't used to decide whether we're inside an + ;; expression or not. If both LIM and CONTAINING-SEXP are used, LIM + ;; needs to be farther back. + ;; + ;; If CHECK-AT-END is non-nil then extra checks at the end of the + ;; brace block might be done. It should only be used when the + ;; construct can be assumed to be complete, i.e. when the original + ;; starting position was further down than that. + ;; + ;; This function might do hidden buffer changes. + + (save-excursion + (let ((res 'maybe) passed-paren + (closest-lim (or containing-sexp lim (point-min))) + ;; Look at the character after point only as a last resort + ;; when we can't disambiguate. + (block-follows (and (eq (char-after) ?{) (point)))) + + (while (and (eq res 'maybe) + (progn (c-backward-syntactic-ws) + (> (point) closest-lim)) + (not (bobp)) + (progn (backward-char) + (looking-at "[\]\).]\\|\w\\|\\s_")) + (c-safe (forward-char) + (goto-char (scan-sexps (point) -1)))) + + (setq res + (if (looking-at c-keywords-regexp) + (let ((kw-sym (c-keyword-sym (match-string 1)))) + (cond + ((and block-follows + (c-keyword-member kw-sym 'c-inexpr-class-kwds)) + (and (not (eq passed-paren ?\[)) + + ;; dinoch Thu, 22 Apr 2010 18:20 + ;; ============================================ + ;; looking at new MyType() { ... } + ;; means this is a brace list, so, return nil, + ;; implying NOT looking-at-inexpr-block + (not + (and (c-major-mode-is 'csharp-mode) + (looking-at "new[ \t\n\f\v\r]+\\([[:alnum:]_]+\\)\\b"))) + + (or (not (looking-at c-class-key)) + ;; If the class instantiation is at the start of + ;; a statement, we don't consider it an + ;; in-expression class. + (let ((prev (point))) + (while (and + (= (c-backward-token-2 1 nil closest-lim) 0) + (eq (char-syntax (char-after)) ?w)) + (setq prev (point))) + (goto-char prev) + (not (c-at-statement-start-p))) + ;; Also, in Pike we treat it as an + ;; in-expression class if it's used in an + ;; object clone expression. + (save-excursion + (and check-at-end + (c-major-mode-is 'pike-mode) + (progn (goto-char block-follows) + (zerop (c-forward-token-2 1 t))) + (eq (char-after) ?\()))) + (cons 'inexpr-class (point)))) + ((c-keyword-member kw-sym 'c-inexpr-block-kwds) + (when (not passed-paren) + (cons 'inexpr-statement (point)))) + ((c-keyword-member kw-sym 'c-lambda-kwds) + (when (or (not passed-paren) + (eq passed-paren ?\()) + (cons 'inlambda (point)))) + ((c-keyword-member kw-sym 'c-block-stmt-kwds) + nil) + (t + 'maybe))) + + (if (looking-at "\\s(") + (if passed-paren + (if (and (eq passed-paren ?\[) + (eq (char-after) ?\[)) + ;; Accept several square bracket sexps for + ;; Java array initializations. + 'maybe) + (setq passed-paren (char-after)) + 'maybe) + 'maybe)))) + + (if (eq res 'maybe) + (when (and c-recognize-paren-inexpr-blocks + block-follows + containing-sexp + (eq (char-after containing-sexp) ?\()) + (goto-char containing-sexp) + (if (or (save-excursion + (c-backward-syntactic-ws lim) + (and (> (point) (or lim (point-min))) + (c-on-identifier))) + (and c-special-brace-lists + (c-looking-at-special-brace-list))) + nil + (cons 'inexpr-statement (point)))) + + res)))) + + + + + +(defun c-inside-bracelist-p (containing-sexp paren-state) + ;; return the buffer position of the beginning of the brace list + ;; statement if we're inside a brace list, otherwise return nil. + ;; CONTAINING-SEXP is the buffer pos of the innermost containing + ;; paren. PAREN-STATE is the remainder of the state of enclosing + ;; braces + ;; + ;; N.B.: This algorithm can potentially get confused by cpp macros + ;; placed in inconvenient locations. It's a trade-off we make for + ;; speed. + ;; + ;; This function might do hidden buffer changes. + (or + ;; This will pick up brace list declarations. + (c-safe + (save-excursion + (goto-char containing-sexp) + (c-safe (c-forward-sexp -1)) + (let (bracepos) + (if (and (or (looking-at c-brace-list-key) + + (progn + (c-safe (c-forward-sexp -1)) + (looking-at c-brace-list-key)) + + ;; dinoch Thu, 22 Apr 2010 18:20 + ;; ============================================ + ;; looking enum Foo : int + ;; means this is a brace list, so, return nil, + ;; implying NOT looking-at-inexpr-block + + (and (c-major-mode-is 'csharp-mode) + (progn + (c-safe (c-forward-sexp -1)) + (looking-at csharp-enum-decl-re)))) + + (setq bracepos (c-down-list-forward (point))) + (not (c-crosses-statement-barrier-p (point) + (- bracepos 2)))) + (point))))) + + ;; this will pick up array/aggregate init lists, even if they are nested. + (save-excursion + (let ((class-key + ;; Pike can have class definitions anywhere, so we must + ;; check for the class key here. + (and (c-major-mode-is 'pike-mode) + c-decl-block-key)) + bufpos braceassignp lim next-containing) + (while (and (not bufpos) + containing-sexp) + (when paren-state + (if (consp (car paren-state)) + (setq lim (cdr (car paren-state)) + paren-state (cdr paren-state)) + (setq lim (car paren-state))) + (when paren-state + (setq next-containing (car paren-state) + paren-state (cdr paren-state)))) + (goto-char containing-sexp) + (if (c-looking-at-inexpr-block next-containing next-containing) + ;; We're in an in-expression block of some kind. Do not + ;; check nesting. We deliberately set the limit to the + ;; containing sexp, so that c-looking-at-inexpr-block + ;; doesn't check for an identifier before it. + (setq containing-sexp nil) + ;; see if the open brace is preceded by = or [...] in + ;; this statement, but watch out for operator= + (setq braceassignp 'dontknow) + (c-backward-token-2 1 t lim) + ;; Checks to do only on the first sexp before the brace. + (when (and c-opt-inexpr-brace-list-key + (eq (char-after) ?\[)) + ;; In Java, an initialization brace list may follow + ;; directly after "new Foo[]", so check for a "new" + ;; earlier. + (while (eq braceassignp 'dontknow) + (setq braceassignp + (cond ((/= (c-backward-token-2 1 t lim) 0) nil) + ((looking-at c-opt-inexpr-brace-list-key) t) + ((looking-at "\\sw\\|\\s_\\|[.[]") + ;; Carry on looking if this is an + ;; identifier (may contain "." in Java) + ;; or another "[]" sexp. + 'dontknow) + (t nil))))) + ;; Checks to do on all sexps before the brace, up to the + ;; beginning of the statement. + (while (eq braceassignp 'dontknow) + (cond ((eq (char-after) ?\;) + (setq braceassignp nil)) + ((and class-key + (looking-at class-key)) + (setq braceassignp nil)) + ((eq (char-after) ?=) + ;; We've seen a =, but must check earlier tokens so + ;; that it isn't something that should be ignored. + (setq braceassignp 'maybe) + (while (and (eq braceassignp 'maybe) + (zerop (c-backward-token-2 1 t lim))) + (setq braceassignp + (cond + ;; Check for operator = + ((and c-opt-op-identifier-prefix + (looking-at c-opt-op-identifier-prefix)) + nil) + ;; Check for `= in Pike. + ((and (c-major-mode-is 'pike-mode) + (or (eq (char-after) ?`) + ;; Special case for Pikes + ;; `[]=, since '[' is not in + ;; the punctuation class. + (and (eq (char-after) ?\[) + (eq (char-before) ?`)))) + nil) + ((looking-at "\\s.") 'maybe) + ;; make sure we're not in a C++ template + ;; argument assignment + ((and + (c-major-mode-is 'c++-mode) + (save-excursion + (let ((here (point)) + (pos< (progn + (skip-chars-backward "^<>") + (point)))) + (and (eq (char-before) ?<) + (not (c-crosses-statement-barrier-p + pos< here)) + (not (c-in-literal)) + )))) + nil) + (t t)))))) + (if (and (eq braceassignp 'dontknow) + (/= (c-backward-token-2 1 t lim) 0)) + (setq braceassignp nil))) + (if (not braceassignp) + (if (eq (char-after) ?\;) + ;; Brace lists can't contain a semicolon, so we're done. + (setq containing-sexp nil) + ;; Go up one level. + (setq containing-sexp next-containing + lim nil + next-containing nil)) + ;; we've hit the beginning of the aggregate list + (c-beginning-of-statement-1 + (c-most-enclosing-brace paren-state)) + (setq bufpos (point)))) + ) + bufpos)) + )) + +;; ================================================================== +;; end of monkey-patching of basic parsing logic +;; ================================================================== + + + + +;;(easy-menu-define csharp-menu csharp-mode-map "C# Mode Commands" +;; ;; Can use `csharp' as the language for `c-mode-menu' +;; ;; since its definition covers any language. In +;; ;; this case the language is used to adapt to the +;; ;; nonexistence of a cpp pass and thus removing some +;; ;; irrelevant menu alternatives. +;; (cons "C#" (c-lang-const c-mode-menu csharp))) + +;;; Autoload mode trigger +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.cs$" . csharp-mode)) + + +(c-add-style "C#" + '("Java" + (c-basic-offset . 4) + (c-comment-only-line-offset . (0 . 0)) + (c-offsets-alist . ( + (access-label . -) + (arglist-close . c-lineup-arglist) + (arglist-cont . 0) + (arglist-cont-nonempty . c-lineup-arglist) + (arglist-intro . c-lineup-arglist-intro-after-paren) + (block-close . 0) + (block-open . 0) + (brace-entry-open . 0) + (brace-list-close . 0) + (brace-list-entry . 0) + (brace-list-intro . +) + (brace-list-open . +) + (c . c-lineup-C-comments) + (case-label . +) + (catch-clause . 0) + (class-close . 0) + (class-open . 0) + (comment-intro . c-lineup-comment) + (cpp-macro . 0) + (cpp-macro-cont . c-lineup-dont-change) + (defun-block-intro . +) + (defun-close . 0) + (defun-open . 0) + (do-while-closure . 0) + (else-clause . 0) + (extern-lang-close . 0) + (extern-lang-open . 0) + (friend . 0) + (func-decl-cont . +) + (inclass . +) + (inexpr-class . +) + (inexpr-statement . 0) + (inextern-lang . +) + (inher-cont . c-lineup-multi-inher) + (inher-intro . +) + (inlambda . c-lineup-inexpr-block) + (inline-close . 0) + (inline-open . 0) + (innamespace . +) + (knr-argdecl . 0) + (knr-argdecl-intro . 5) + (label . 0) + (lambda-intro-cont . +) + (member-init-cont . c-lineup-multi-inher) + (member-init-intro . +) + (namespace-close . 0) + (namespace-open . 0) + (statement . 0) + (statement-block-intro . +) + (statement-case-intro . +) + (statement-case-open . +) + (statement-cont . +) + (stream-op . c-lineup-streamop) + (string . c-lineup-dont-change) + (substatement . +) + (substatement-open . 0) + (template-args-cont c-lineup-template-args +) + (topmost-intro . 0) + (topmost-intro-cont . +) + )) + )) + + + +(defun csharp-guess-compile-command () + "set `compile-command' intelligently depending on the +current buffer, or the contents of the current directory. +" + (interactive) + (set (make-local-variable 'compile-command) + + (cond + ((or (file-expand-wildcards "*.csproj" t) + (file-expand-wildcards "*.vcproj" t) + (file-expand-wildcards "*.vbproj" t) + (file-expand-wildcards "*.shfbproj" t) + (file-expand-wildcards "*.sln" t)) + (concat csharp-msbuild-tool " ")) + + ;; sometimes, not sure why, the buffer-file-name is + ;; not set. Can use it only if set. + (buffer-file-name + (let ((filename (file-name-nondirectory buffer-file-name))) + (cond + + ;; editing a c# file - check for an explicitly-specified command + ((string-equal (substring buffer-file-name -3) ".cs") + (let ((explicitly-specified-command + (csharp-get-value-from-comments "compile" csharp-cmd-line-limit))) + + + (if explicitly-specified-command + (csharp-replace-command-tokens explicitly-specified-command) + (concat csharp-make-tool " " ;; assume a makefile exists + (file-name-sans-extension filename) + ".exe")))) + + ;; something else - do a typical .exe build + (t + (concat csharp-make-tool " " + (file-name-sans-extension filename) + ".exe"))))) + (t + ;; punt + (concat csharp-make-tool " "))))) + + + +(defun csharp-invoke-compile-interactively () + "fn to wrap the `compile' function. This simply +checks to see if `compile-command' has been previously set, and +if not, invokes `csharp-guess-compile-command' to set the value. +Then it invokes the `compile' function, interactively. + +The effect is to guess the compile command only once, per buffer. + +I tried doing this with advice attached to the `compile' +function, but because of the interactive nature of the fn, it +didn't work the way I wanted it to. So this fn should be bound to +the key sequence the user likes for invoking compile, like ctrl-c +ctrl-e. + +" + (interactive) + (cond + ((not (boundp 'csharp-local-compile-command-has-been-set)) + (csharp-guess-compile-command) + (set (make-local-variable 'csharp-local-compile-command-has-been-set) t))) + ;; local compile command has now been set + (call-interactively 'compile)) + + + + +;;; The entry point into the mode +;;;###autoload + (defun csharp-mode () + "Major mode for editing C# code. This mode is derived from CC Mode to +support C#. + +Normally, you'd want to autoload this mode by setting `auto-mode-alist' with +an entry for csharp, in your .emacs file: + + (autoload 'csharp-mode \"csharp-mode\" \"Major mode for editing C# code.\" t) + (setq auto-mode-alist + (append '((\"\\.cs$\" . csharp-mode)) auto-mode-alist)) + +The mode provides fontification and indent for C# syntax, as well +as some other handy features. + +At mode startup, there are two interesting hooks that run: +`c-mode-common-hook' is run with no args, then `csharp-mode-hook' is run after +that, also with no args. + +To run your own logic after csharp-mode starts, do this: + + (defun my-csharp-mode-fn () + \"my function that runs when csharp-mode is initialized for a buffer.\" + (turn-on-font-lock) + (turn-on-auto-revert-mode) ;; helpful when also using Visual Studio + (setq indent-tabs-mode nil) ;; tabs are evil + (flymake-mode 1) + (yas/minor-mode-on) + (require 'rfringe) ;; handy for flymake + (require 'flymake-cursor) ;; also handy for flymake + ....your own code here... + ) + (add-hook 'csharp-mode-hook 'my-csharp-mode-fn t) + + +The function above is just a suggestion. + + +Compile integration: +======================== + +csharp-mode binds the function `csharp-invoke-compile-interactively' to +\"\C-x\C-e\" . This function attempts to intellgently guess the format of the +compile command to use for a buffer. It looks in the comments at the head of +the buffer for a line that begins with compile: . For exammple: + + // compile: csc.exe /t:library /r:Mylib.dll Foo.cs + +If csharp-mode finds a line like this, it will suggest the text that follows +as the compilation command when running `compile' for the first time. If such +a line is not found, csharp-mode falls back to a msbuild or nmake command. +See the documentation on `csharp-cmd-line-limit' for further information. If +you don't want this magic, then you can just run `compile' directly, rather +than `csharp-invoke-compile-interactively' . + +This mode will also automatically add a symbol and regexp to the +`compilation-error-regexp-alist' and`compilation-error-regexp-alist-alist' +respectively, for Csc.exe error and warning messages. If you invoke `compile', +then `next-error' should work properly for error messages produced by csc.exe. + + +Flymake Integraiton +======================== + +You can use flymake with csharp mode to automatically check the syntax of your +csharp code, and highlight errors. To do so, add a comment line like this to +each .cs file that you use flymake with: + + // flymake: csc.exe /t:module /R:Foo.dll @@FILE@@ + +csharp-mode replaces special tokens in the command with different values: + + @@ORIG@@ - gets replaced with the original filename + @@FILE@@ - gets replaced with the name of the temporary file + created by flymake. This is usually what you want in place of the + name of the file to be compiled. + +See the documentation on `csharp-cmd-line-limit' for further information. + +You may also want to run a syntax checker, like fxcop: + + // flymake: fxcopcmd.exe /c /F:MyLibrary.dll + +In this case you don't need either of the tokens described above. + +If the module has no external dependencies, then you need not specify any +flymake command at all. csharp-mode will implicitly act as if you had +specified the command: + + // flymake: csc.exe /t:module /nologo @@FILE@@ + +It looks for the EXE on the path. You can specify a full path if you like. + + +YASnippet and IMenu Integraiton +=============================== + +Check the menubar for menu entries for YASnippet and Imenu; the latter +is labelled \"Index\". + +The Imenu index gets computed when the file is .cs first opened and loaded. +This may take a moment or two. If you don't like this delay and don't +use imenu, you can turn this off with the variable `csharp-want-imenu'. + + + +Key bindings: +\\{csharp-mode-map}" + (interactive) + (kill-all-local-variables) + (make-local-variable 'beginning-of-defun-function) + (make-local-variable 'end-of-defun-function) + (c-initialize-cc-mode t) + (set-syntax-table csharp-mode-syntax-table) + + ;; define underscore as part of a word in the Csharp syntax table + (modify-syntax-entry ?_ "w" csharp-mode-syntax-table) + + ;; define @ as an expression prefix in Csharp syntax table + (modify-syntax-entry ?@ "'" csharp-mode-syntax-table) + + (setq major-mode 'csharp-mode + mode-name "C#" + local-abbrev-table csharp-mode-abbrev-table + abbrev-mode t) + (use-local-map csharp-mode-map) + + ;; `c-init-language-vars' is a macro that is expanded at compile + ;; time to a large `setq' with all the language variables and their + ;; customized values for our language. + (c-init-language-vars csharp-mode) + + ;; `c-common-init' initializes most of the components of a CC Mode + ;; buffer, including setup of the mode menu, font-lock, etc. + ;; There's also a lower level routine `c-basic-common-init' that + ;; only makes the necessary initialization to get the syntactic + ;; analysis and similar things working. + (c-common-init 'csharp-mode) + + ;; compile + (local-set-key "\C-x\C-e" 'csharp-invoke-compile-interactively) + + ;; to allow next-error to work with csc.exe: + (setq compilation-scroll-output t) + + ;; csc.exe, the C# Compiler, produces errors like this: + ;; file.cs(6,18): error CS1006: Name of constructor must match name of class + (if (boundp 'compilation-error-regexp-alist-alist) + (progn + (add-to-list + 'compilation-error-regexp-alist-alist + '(ms-csharp "^[ \t]*\\([-_:A-Za-z0-9][^\n(]*\\.\\(?:cs\\|xaml\\)\\)(\\([0-9]+\\)[,]\\([0-9]+\\)) ?: \\(error\\|warning\\) CS[0-9]+:" 1 2 3)) + (add-to-list + 'compilation-error-regexp-alist + 'ms-csharp))) + + ;; flymake + (eval-after-load "flymake" + '(progn + (if csharp-want-flymake-fixup + (csharp-flymake-install)))) + + (eval-after-load "yasnippet" + '(progn + (if csharp-want-yasnippet-fixup + (csharp-yasnippet-fixup)))) + + + (local-set-key (kbd "/") 'csharp-maybe-insert-codedoc) + (local-set-key (kbd "{") 'csharp-insert-open-brace) + + ;; Need the following for parse-partial-sexp to work properly with + ;; verbatim literal strings Setting this var to non-nil tells + ;; `parse-partial-sexp' to pay attention to the syntax text + ;; properties on the text in the buffer. If csharp-mode attaches + ;; text syntax to @"..." then, `parse-partial-sexp' will treat those + ;; strings accordingly. + (set (make-local-variable 'parse-sexp-lookup-properties) t) + + ;; scan the entire buffer for verblit strings + ;; This will happen on font; it's necessary only + ;; if font-lock is disabled. But it won't hurt. + (csharp-scan-for-verbatim-literals-and-set-props nil nil) + + ;; Allow fill-paragraph to work on xml code doc + ;; This setting gets overwritten quietly by c-run-mode-hooks, + ;; so I put it afterwards to make it stick. + (make-local-variable 'paragraph-separate) + + ;;(message "C#: set paragraph-separate") + + ;; Speedbar handling + (if (fboundp 'speedbar-add-supported-extension) + (speedbar-add-supported-extension '(".cs"))) ;; idempotent + + (c-update-modeline) + (c-run-mode-hooks 'c-mode-common-hook 'csharp-mode-hook) + + ;; maybe do imenu scan after hook returns + (if csharp-want-imenu + (progn + ;; There are two ways to do imenu indexing. One is to provide a + ;; function, via `imenu-create-index-function'. The other is to + ;; provide imenu with a list of regexps via + ;; `imenu-generic-expression'; imenu will do a "generic scan" for you. + ;; csharp-mode uses the former method. + ;; + (setq imenu-create-index-function 'csharp-imenu-create-index) + (imenu-add-menubar-index))) + + ;; The paragraph-separate variable was getting stomped by + ;; other hooks, so it must reside here. + (setq paragraph-separate + "[ \t]*\\(//+\\|\\**\\)\\([ \t]+\\|[ \t]+<.+?>\\)$\\|^\f") + + (setq beginning-of-defun-function 'csharp-move-back-to-beginning-of-defun) + ;; end-of-defun-function can remain forward-sexp !! + + (set (make-local-variable 'comment-auto-fill-only-comments) t) + ) + + + + + ;; ======================================================= + ;; + ;; This section attempts to workaround an anomalous display behavior + ;; for tooltips. It's not strictly necessary, only for aesthetics. The + ;; issue is that tooltips can get clipped. This is the topic of Emacs + ;; bug #5908, unfixed in v23 and present in v22. + + + (defadvice tooltip-show (before + flymake-for-csharp-fixup-tooltip + (arg &optional use-echo-area) + activate compile) + (progn + (if ;;(and (not use-echo-area) (eq major-mode 'csharp-mode)) + (not use-echo-area) + (let ((orig (ad-get-arg 0))) + (ad-set-arg 0 (concat " " (cheeso-string-trim (cheeso-reform-string 74 orig) ?\ ))) + )))) + + + + +;; ======================================================================== +;; YA-snippet integration + +(defun csharp-yasnippet-fixup () + "Sets snippets into ya-snippet for C#, if yasnippet is loaded, +and if the snippets do not already exist. +" + (if (not csharp--yasnippet-has-been-fixed) + (if (fboundp 'yas/snippet-table-fetch) + ;; yasnippet is present + (let ((snippet-table (yas/snippet-table 'csharp-mode)) + (keymap (if yas/use-menu + (yas/menu-keymap-for-mode 'csharp-mode) + nil)) + (yas/require-template-condition nil) + (builtin-snips + '( + ("xmls" "{ + XmlSerializer s1 = new XmlSerializer(typeof(${1:type})); + + // use this to \"suppress\" the default xsd and xsd-instance namespaces + XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); + ns.Add(\"\", \"\"); + + s1.Serialize(new XTWFND(System.Console.Out), object, ns); + System.Console.WriteLine(\"\\n\"); +} + + $0 + /// XmlTextWriterFormattedNoDeclaration + /// helper class : eliminates the XML Documentation at the + /// start of a XML doc. + /// XTWFND = XmlTextWriterFormattedNoDeclaration + /// usage: s1.Serialize(new XTWFND(System.Console.Out), thing, ns); + + public class XTWFND : System.Xml.XmlTextWriter + { + public XTWFND(System.IO.StringWriter w) : base(w) { Formatting=System.Xml.Formatting.Indented; } + public XTWFND(System.IO.TextWriter w) : base(w) { Formatting = System.Xml.Formatting.Indented; } + public XTWFND(System.IO.Stream s) : base(s, null) { Formatting = System.Xml.Formatting.Indented; } + public XTWFND(string filename) : base(filename, null) { Formatting = System.Xml.Formatting.Indented; } + public override void WriteStartDocument() { } + } + +" "xmlserializer { ... }" nil) + ("wl" "System.Console.WriteLine(${0://thing to do}); +" "WriteLine( ... );" nil) + ("while" "while (${1:condition}) +{ + ${0://thing to do} +}" "while (...) { ... }" nil) + ("using" "using (${1:type} ${2:var} = new ${1:type}(${4:ctor args})) +{ + ${5:// body...} +}" "using ... { ... }" nil) + ("try" "try +{ + $0 +} +catch (System.Exception exc1) +{ + throw new Exception(\"uncaught exception\", exc1); +}" "try { ... } catch { ... }" nil) + ("sum" "/// +/// ${1:description} +/// +/// +/// +/// ${2:comments} +/// +" "/// ..." nil) + ("sing" "#region Singleton ${1:className} +public sealed class $1 +{ + private readonly static $1 _instance = new $1(); + public static $1 Instance { get { return _instance; } } + static $1() { /* required for lazy init */ } + private $1() + { + // implementation here + } +} + +#endregion +" "public sealed class Singleton {...}" nil) + ("setting" " #region Property${1:PropName} + + private string default$1 = ${2:defaultValue}; + private string _$1; + public string $1 + { + get + { + if (_$1 == null) + { + _$1 = System.Configuration.ConfigurationManager.AppSettings[\"$1\"]; + + if (string.IsNullOrEmpty(_$1)) + { + _$1 = default$1; + } + } + return this._$1; + } + set + { + string new$1 = value; + // optional validation: + //Validation.EnforceXxxx(new$1, \"$1\"); + _$1 = new$1; + } + } + +#endregion +" "config setting" nil) + ("prop" "private ${1:Type} _${2:Name}; +public ${1:Type} ${2:Name} +{ + get + { + ${3://get impl} + } + + set + { + ${4://get impl} + } + +}" "property ... { ... }" nil) + ("pa" " for (int i=0; i < args.Length; i++) + { + switch (args[i]) + { + case \"-?\": + case \"-help\": + throw new ArgumentException(args[i]); + + default: // positional args + if ($2 != 0) + // we have all the args we need + throw new ArgumentException(args[i]); + + if ($1 == null) + $1 = args[i]; + + else + $2 = System.Int32.Parse(args[i]); + + break; + } + } + + // check values + if ($1 == null) + throw new ArgumentException(); + + if ($2 == 0) + throw new ArgumentException(); + + +" "switch(args[0]) {...}" nil) + ("openread" " using(Stream src = File.OpenRead($1)) + { + using(Stream dest= File.Create($2)) + { + if (compress) + Compress(src, dest); + else + Decompress(src, dest); + } + } +" "File.OpenRead(...)" nil) + ("ofd" "var dlg = new System.Windows.Forms.OpenFileDialog(); +dlg.Filter = \"${1:filter string}\"; // ex: \"C# (*.cs)|*.cs|Text (*.txt)|*.txt\"; +if (dlg.ShowDialog() == DialogResult.OK) +{ + string fileName = dlg.FileName; + $0 +} +" "new OpenFileDialog; if (DialogResult.OK) { ... }" nil) + ("ife" "if (${1:predicate}) +{ + ${2:// then clause} +} +else +{ + ${3:// else clause} +}" "if (...) { ... } else { ... }" nil) + ("fore" "foreach (${1:type} ${2:var} in ${3:IEnumerable}) +{ + ${4:// body...} +}" "foreach ... { ... }" nil) + ("for" "for (int ${1:index}=0; $1 < ${2:Limit}; $1++) +{ + ${3:// body...} +}" "for (...) { ... }" nil) + ("fbd" "using (FolderBrowserDialog dialog = new FolderBrowserDialog()) +{ + dialog.Description = \"Open a folder which contains the xml output\"; + dialog.ShowNewFolderButton = false; + dialog.RootFolder = Environment.SpecialFolder.MyComputer; + if(dialog.ShowDialog() == DialogResult.OK) + { + string folder = dialog.SelectedPath; + foreach (string fileName in Directory.GetFiles(folder, \"*.xml\", SearchOption.TopDirectoryOnly)) + { + SQLGenerator.GenerateSQLTransactions(Path.GetFullPath(fileName)); + } + } +} + +" "new FolderBrowserDialog; if (DialogResult.OK) { ... }" nil) + ("doc" "/// +/// ${1:summary} +/// +/// +/// +/// ${2:remarks} +/// +$0" "XML Documentation" nil) + ("conv" " List Values = new List() { \"7\", \"13\", \"41\", \"3\" }; + + // ConvertAll maps the given delegate across all the List elements + var foo = Values.ConvertAll((s) => { return System.Convert.ToInt32(s); }) ; + + System.Console.WriteLine(\"typeof(foo) = {0}\", foo.GetType().ToString()); + + Array.ForEach(foo.ToArray(),Console.WriteLine); +" "ConvertAll((s) => { ... });" nil) + ("cla" "public class ${1:Classname} +{ + // default ctor + public ${1:Classname}() + { + } + + ${2:// methods here} +}" "class ... { ... }" nil) + ("ca" " List Values = new List() { \"7\", \"13\", \"41\", \"3\" }; + + // ConvertAll maps the given delegate across all the List elements + var foo = Values.ConvertAll((s) => { return System.Convert.ToInt32(s); }) ; + + System.Console.WriteLine(\"typeof(foo) = {0}\", foo.GetType().ToString()); + + Array.ForEach(foo.ToArray(),Console.WriteLine); +" "ConvertAll((s) => { ... });" nil) + ("ass" " + +[assembly: AssemblyTitle(\"$1\")] +[assembly: AssemblyCompany(\"${2:YourCoName}\")] +[assembly: AssemblyProduct(\"${3}\")] +[assembly: AssemblyCopyright(\"Copyright © ${4:Someone} 2011\")] +[assembly: AssemblyTrademark(\"\")] +[assembly: AssemblyCulture(\"\")] +[assembly: AssemblyConfiguration(\"\")] +[assembly: AssemblyDescription(\"${5}\")] +[assembly: AssemblyVersion(\"${6:1.0.1.0}\")] +[assembly: AssemblyFileVersion(\"${7:1.0.1.0}\")] + +" "assembly info" nil) + ))) + + (setq csharp--yasnippet-has-been-fixed t) + + (add-to-list 'yas/known-modes 'csharp-mode) + + ;; It's possible that Csharp-mode is not on the yasnippet menu + ;; Install it here. + (when yas/use-menu + (define-key + yas/menu-keymap + (vector 'csharp-mode) + `(menu-item "C#" ,keymap))) + + ;; Insert the snippets from above into the table if they + ;; are not already defined. + (mapcar + '(lambda (item) + (let* ((full-key (car item)) + (existing-snip + (yas/snippet-table-fetch snippet-table full-key))) + (if (not existing-snip) + (let* ((key (file-name-sans-extension full-key)) + (name (caddr item)) + (condition (nth 3 item)) + (template (yas/make-template (cadr item) + (or name key) + condition))) + (yas/snippet-table-store snippet-table + full-key + key + template) + (when yas/use-menu + (define-key keymap (vector (make-symbol full-key)) + `(menu-item ,(yas/template-name template) + ,(yas/make-menu-binding (yas/template-content template)) + :keys ,(concat key yas/trigger-symbol)))))))) + builtin-snips))))) + + + + +(message (concat "Done loading " load-file-name)) + + +(provide 'csharp-mode) + +;;; csharp-mode.el ends here