diff options
author | peter <peter@FreeBSD.org> | 1995-12-30 19:02:48 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1995-12-30 19:02:48 +0000 |
commit | 01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5 (patch) | |
tree | 77047335c1af0f3052c97a3b3ca7dc8630a5b313 | |
parent | 9be81c20f22dbeec5c8b19756b1f3a0110c7761a (diff) | |
download | FreeBSD-src-01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5.zip FreeBSD-src-01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5.tar.gz |
recording cvs-1.6 file death
-rw-r--r-- | gnu/usr.bin/cvs/contrib/pcl-cvs/pcl-cvs.info | 1659 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/cvs/config.h | 217 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/cvs/version.c | 11 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/doc/cvs.ms | 1073 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/lib/Makefile.in | 91 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/lib/regex.c | 4948 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/lib/y.tab.h | 18 | ||||
-rw-r--r-- | gnu/usr.bin/cvs/mkmodules/xxx | 5320 |
8 files changed, 0 insertions, 13337 deletions
diff --git a/gnu/usr.bin/cvs/contrib/pcl-cvs/pcl-cvs.info b/gnu/usr.bin/cvs/contrib/pcl-cvs/pcl-cvs.info deleted file mode 100644 index 060d932..0000000 --- a/gnu/usr.bin/cvs/contrib/pcl-cvs/pcl-cvs.info +++ /dev/null @@ -1,1659 +0,0 @@ -This is Info file pcl-cvs, produced by Makeinfo-1.49 from the input -file pcl-cvs.texinfo. - - Copyright (C) 1992 Per Cederqvist - - Permission is granted to make and distribute verbatim copies of -this manual provided the copyright notice and this permission notice -are preserved on all copies. - - Permission is granted to copy and distribute modified versions of -this manual under the conditions for verbatim copying, provided also -that the section entitled "GNU General Public License" is included -exactly as in the original, and provided that the entire resulting -derived work is distributed under the terms of a permission notice -identical to this one. - - Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that the section entitled "GNU General Public -License" and this permission notice may be included in translations -approved by the Free Software Foundation instead of in the original -English. - - -File: pcl-cvs, Node: Top, Next: Copying, Prev: (dir), Up: (dir) - - This info manual describes pcl-cvs which is a GNU Emacs front-end -to CVS. It works with CVS version 1.3. This manual is updated to -release 1.05 of pcl-cvs. - -* Menu: - -* Copying:: GNU General Public License -* Installation:: How to install pcl-cvs on your system. -* About pcl-cvs:: Authors and ftp sites. - -* Getting started:: An introduction with a walk-through example. -* Buffer contents:: An explanation of the buffer contents. -* Commands:: All commands, grouped by type. - -* Customization:: How you can tailor pcl-cvs to suit your needs. -* Future enhancements:: Future enhancements of pcl-cvs. -* Bugs:: Bugs (known and unknown). -* Function and Variable Index:: List of functions and variables. -* Concept Index:: List of concepts. -* Key Index:: List of keystrokes. - - -- The Detailed Node Listing -- - -Installation - -* Pcl-cvs installation:: How to install pcl-cvs on your system. -* On-line manual installation:: How to install the on-line manual. -* Typeset manual installation:: How to create typeset documentation - about pcl-cvs. - -About pcl-cvs - -* Contributors:: Contributors to pcl-cvs. -* Archives:: Where can I get a copy of Pcl-Cvs? - -Buffer contents - -* File status:: The meaning of the second field. -* Selected files:: How selection works. - -Commands - -* Updating the directory:: Commands to update the local directory -* Movement commands:: How to move up and down in the buffer -* Marking files:: How to mark files that other commands - will later operate on. -* Committing changes:: Checking in your modifications to the - CVS repository. -* Editing files:: Loading files into Emacs. -* Getting info about files:: Display the log and status of files. -* Adding and removing files:: Adding and removing files -* Undoing changes:: Undoing changes -* Removing handled entries:: Uninteresting lines can easily be removed. -* Ignoring files:: Telling CVS to ignore generated files. -* Viewing differences:: Commands to `diff' different versions. -* Emerge:: -* Reverting your buffers:: Reverting your buffers -* Miscellaneous commands:: Miscellaneous commands - - -File: pcl-cvs, Node: Copying, Next: Installation, Prev: Top, Up: Top - -GNU GENERAL PUBLIC LICENSE -************************** - - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -Preamble -======== - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if -you distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, -and (2) offer you this license which gives you legal permission to -copy, distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make -certain that everyone understands that there is no warranty for this -free software. If the software is modified by someone else and -passed on, we want its recipients to know that what they have is not -the original, so that any problems introduced by others will not -reflect on the original authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at -all. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 1. This License applies to any program or other work which contains - a notice placed by the copyright holder saying it may be - distributed under the terms of this General Public License. The - "Program", below, refers to any such program or work, and a - "work based on the Program" means either the Program or any - derivative work under copyright law: that is to say, a work - containing the Program or a portion of it, either verbatim or - with modifications and/or translated into another language. - (Hereinafter, translation is included without limitation in the - term "modification".) Each licensee is addressed as "you". - - Activities other than copying, distribution and modification are - not covered by this License; they are outside its scope. The - act of running the Program is not restricted, and the output - from the Program is covered only if its contents constitute a - work based on the Program (independent of having been made by - running the Program). Whether that is true depends on what the - Program does. - - 2. You may copy and distribute verbatim copies of the Program's - source code as you receive it, in any medium, provided that you - conspicuously and appropriately publish on each copy an - appropriate copyright notice and disclaimer of warranty; keep - intact all the notices that refer to this License and to the - absence of any warranty; and give any other recipients of the - Program a copy of this License along with the Program. - - You may charge a fee for the physical act of transferring a - copy, and you may at your option offer warranty protection in - exchange for a fee. - - 3. You may modify your copy or copies of the Program or any portion - of it, thus forming a work based on the Program, and copy and - distribute such modifications or work under the terms of Section - 1 above, provided that you also meet all of these conditions: - - a. You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any - change. - - b. You must cause any work that you distribute or publish, - that in whole or in part contains or is derived from the - Program or any part thereof, to be licensed as a whole at - no charge to all third parties under the terms of this - License. - - c. If the modified program normally reads commands - interactively when run, you must cause it, when started - running for such interactive use in the most ordinary way, - to print or display an announcement including an - appropriate copyright notice and a notice that there is no - warranty (or else, saying that you provide a warranty) and - that users may redistribute the program under these - conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive - but does not normally print such an announcement, your work - based on the Program is not required to print an - announcement.) - - These requirements apply to the modified work as a whole. If - identifiable sections of that work are not derived from the - Program, and can be reasonably considered independent and - separate works in themselves, then this License, and its terms, - do not apply to those sections when you distribute them as - separate works. But when you distribute the same sections as - part of a whole which is a work based on the Program, the - distribution of the whole must be on the terms of this License, - whose permissions for other licensees extend to the entire - whole, and thus to each and every part regardless of who wrote - it. - - Thus, it is not the intent of this section to claim rights or - contest your rights to work written entirely by you; rather, the - intent is to exercise the right to control the distribution of - derivative or collective works based on the Program. - - In addition, mere aggregation of another work not based on the - Program with the Program (or with a work based on the Program) - on a volume of a storage or distribution medium does not bring - the other work under the scope of this License. - - 4. You may copy and distribute the Program (or a work based on it, - under Section 2) in object code or executable form under the - terms of Sections 1 and 2 above provided that you also do one of - the following: - - a. Accompany it with the complete corresponding - machine-readable source code, which must be distributed - under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - b. Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than - your cost of physically performing source distribution, a - complete machine-readable copy of the corresponding source - code, to be distributed under the terms of Sections 1 and 2 - above on a medium customarily used for software - interchange; or, - - c. Accompany it with the information you received as to the - offer to distribute corresponding source code. (This - alternative is allowed only for noncommercial distribution - and only if you received the program in object code or - executable form with such an offer, in accord with - Subsection b above.) - - The source code for a work means the preferred form of the work - for making modifications to it. For an executable work, - complete source code means all the source code for all modules - it contains, plus any associated interface definition files, - plus the scripts used to control compilation and installation of - the executable. However, as a special exception, the source - code distributed need not include anything that is normally - distributed (in either source or binary form) with the major - components (compiler, kernel, and so on) of the operating system - on which the executable runs, unless that component itself - accompanies the executable. - - If distribution of executable or object code is made by offering - access to copy from a designated place, then offering equivalent - access to copy the source code from the same place counts as - distribution of the source code, even though third parties are - not compelled to copy the source along with the object code. - - 5. You may not copy, modify, sublicense, or distribute the Program - except as expressly provided under this License. Any attempt - otherwise to copy, modify, sublicense or distribute the Program - is void, and will automatically terminate your rights under this - License. However, parties who have received copies, or rights, - from you under this License will not have their licenses - terminated so long as such parties remain in full compliance. - - 6. You are not required to accept this License, since you have not - signed it. However, nothing else grants you permission to - modify or distribute the Program or its derivative works. These - actions are prohibited by law if you do not accept this License. - Therefore, by modifying or distributing the Program (or any - work based on the Program), you indicate your acceptance of this - License to do so, and all its terms and conditions for copying, - distributing or modifying the Program or works based on it. - - 7. Each time you redistribute the Program (or any work based on the - Program), the recipient automatically receives a license from the - original licensor to copy, distribute or modify the Program - subject to these terms and conditions. You may not impose any - further restrictions on the recipients' exercise of the rights - granted herein. You are not responsible for enforcing compliance - by third parties to this License. - - 8. If, as a consequence of a court judgment or allegation of patent - infringement or for any other reason (not limited to patent - issues), conditions are imposed on you (whether by court order, - agreement or otherwise) that contradict the conditions of this - License, they do not excuse you from the conditions of this - License. If you cannot distribute so as to satisfy - simultaneously your obligations under this License and any other - pertinent obligations, then as a consequence you may not - distribute the Program at all. For example, if a patent license - would not permit royalty-free redistribution of the Program by - all those who receive copies directly or indirectly through you, - then the only way you could satisfy both it and this License - would be to refrain entirely from distribution of the Program. - - If any portion of this section is held invalid or unenforceable - under any particular circumstance, the balance of the section is - intended to apply and the section as a whole is intended to - apply in other circumstances. - - It is not the purpose of this section to induce you to infringe - any patents or other property right claims or to contest - validity of any such claims; this section has the sole purpose - of protecting the integrity of the free software distribution - system, which is implemented by public license practices. Many - people have made generous contributions to the wide range of - software distributed through that system in reliance on - consistent application of that system; it is up to the - author/donor to decide if he or she is willing to distribute - software through any other system and a licensee cannot impose - that choice. - - This section is intended to make thoroughly clear what is - believed to be a consequence of the rest of this License. - - 9. If the distribution and/or use of the Program is restricted in - certain countries either by patents or by copyrighted - interfaces, the original copyright holder who places the Program - under this License may add an explicit geographical distribution - limitation excluding those countries, so that distribution is - permitted only in or among countries not thus excluded. In such - case, this License incorporates the limitation as if written in - the body of this License. - - 10. The Free Software Foundation may publish revised and/or new - versions of the General Public License from time to time. Such - new versions will be similar in spirit to the present version, - but may differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the - Program specifies a version number of this License which applies - to it and "any later version", you have the option of following - the terms and conditions either of that version or of any later - version published by the Free Software Foundation. If the - Program does not specify a version number of this License, you - may choose any version ever published by the Free Software - Foundation. - - 11. If you wish to incorporate parts of the Program into other free - programs whose distribution conditions are different, write to - the author to ask for permission. For software which is - copyrighted by the Free Software Foundation, write to the Free - Software Foundation; we sometimes make exceptions for this. Our - decision will be guided by the two goals of preserving the free - status of all derivatives of our free software and of promoting - the sharing and reuse of software generally. - - NO WARRANTY - - 12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO - WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE - LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT - HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT - WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, - BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE - QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE - PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY - SERVICING, REPAIR OR CORRECTION. - - 13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN - WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY - MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE - LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, - INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR - INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS - OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY - YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH - ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - -Appendix: How to Apply These Terms to Your New Programs -======================================================= - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these -terms. - - To do so, attach the following notices to the program. It is -safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. - Copyright (C) 19YY NAME OF AUTHOR - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Also add information on how to contact you by electronic and paper -mail. - - If the program is interactive, make it output a short notice like -this when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - - The hypothetical commands `show w' and `show c' should show the -appropriate parts of the General Public License. Of course, the -commands you use may be called something other than `show w' and -`show c'; they could even be mouse-clicks or menu items--whatever -suits your program. - - You should also get your employer (if you work as a programmer) or -your school, if any, to sign a "copyright disclaimer" for the -program, if necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - SIGNATURE OF TY COON, 1 April 1989 - Ty Coon, President of Vice - - This General Public License does not permit incorporating your -program into proprietary programs. If your program is a subroutine -library, you may consider it more useful to permit linking -proprietary applications with the library. If this is what you want -to do, use the GNU Library General Public License instead of this -License. - - -File: pcl-cvs, Node: Installation, Next: About pcl-cvs, Prev: Copying, Up: Top - -Installation -************ - - This section describes the installation of pcl-cvs, the GNU Emacs -CVS front-end. You should install not only the elisp files -themselves, but also the on-line documentation so that your users -will know how to use it. You can create typeset documentation from -the file `pcl-cvs.texinfo' as well as an on-line info file. The -following steps are also described in the file `INSTALL' in the source -directory. - -* Menu: - -* Pcl-cvs installation:: How to install pcl-cvs on your system. -* On-line manual installation:: How to install the on-line manual. -* Typeset manual installation:: How to create typeset documentation - about pcl-cvs. - - -File: pcl-cvs, Node: Pcl-cvs installation, Next: On-line manual installation, Prev: Installation, Up: Installation - -Installation of the pcl-cvs program -=================================== - - 1. Edit the file `Makefile' to reflect the situation at your site. - The only things you have to change is the definition of `lispdir' - and `infodir'. The elisp files will be copied to `lispdir', and - the info file to `infodir'. - - 2. Configure pcl-cvs.el - - There are a couple of paths that you have to check to make sure - that they match you system. They appear early in the file - pcl-cvs.el. - - *NOTE:* If your system is running emacs 18.57 or earlier you - MUST uncomment the line that says: - - (setq delete-exited-processes nil) - - Setting `delete-exited-processes' to `nil' works around a bug in - emacs that causes it to dump core. The bug was fixed in emacs - 18.58. - - 3. Release 1.05 and later of pcl-cvs requires parts of the Elib - library, version 0.07 or later. Elib is available via anonymous - ftp from prep.ai.mit.edu in `pub/gnu/elib-0.07.tar.z', and from - a lot of other sites that mirrors prep. Get Elib, and install - it, before proceeding. - - 4. Type `make install' in the source directory. This will - byte-compile all `.el' files and copy both the `.el' and the - `.elc' into the directory you specified in step 1. - - If you don't want to install the `.el' files but only the `.elc' - files (the byte-compiled files), you can type ``make - install_elc'' instead of ``make install''. - - If you only want to create the compiled elisp files, but don't - want to install them, you can type `make elcfiles' instead. - This is what happens if you only type `make' without parameters. - - 5. Edit the file `default.el' in your emacs lisp directory (usually - `/usr/gnu/emacs/lisp' or something similar) and enter the - contents of the file `pcl-cvs-startup.el' into it. It contains - a couple of `auto-load's that facilitates the use of pcl-cvs. - - - -File: pcl-cvs, Node: On-line manual installation, Next: Typeset manual installation, Prev: Pcl-cvs installation, Up: Installation - -Installation of the on-line manual. -=================================== - - 1. Create the info file `pcl-cvs' from `pcl-cvs.texinfo' by typing - `make info'. If you don't have the program `makeinfo' you can - get it by anonymous ftp from e.g. `ftp.gnu.ai.mit.edu' as - `pub/gnu/texinfo-2.14.tar.Z' (there might be a newer version - there when you read this), or you could use the preformatted - info file `pcl-cvs.info' that is included in the distribution - (type `cp pcl-cvs.info pcl-cvs'). - - 2. Move the info file `pcl-cvs' to your standard info directory. - This might be called something like `/usr/gnu/emacs/info'. - - 3. Edit the file `dir' in the info directory and enter one line to - contain a pointer to the info file `pcl-cvs'. The line can, for - instance, look like this: - - * Pcl-cvs: (pcl-cvs). An Emacs front-end to CVS. - - -File: pcl-cvs, Node: Typeset manual installation, Prev: On-line manual installation, Up: Installation - -How to make typeset documentation from pcl-cvs.texinfo -====================================================== - - If you have TeX installed at your site, you can make a typeset -manual from `pcl-cvs.texinfo'. - - 1. Run TeX by typing ``make pcl-cvs.dvi''. You will not get the - indices unless you have the `texindex' program. - - 2. Convert the resulting device independent file `pcl-cvs.dvi' to a - form which your printer can output and print it. If you have a - postscript printer there is a program, `dvi2ps', which does. - There is also a program which comes together with TeX, `dvips', - which you can use. - - - -File: pcl-cvs, Node: About pcl-cvs, Next: Getting started, Prev: Installation, Up: Top - -About pcl-cvs -************* - - Pcl-cvs is a front-end to CVS version 1.3. It integrates the most -frequently used CVS commands into emacs. - -* Menu: - -* Contributors:: Contributors to pcl-cvs. -* Archives:: Where can I get a copy of Pcl-Cvs? - - -File: pcl-cvs, Node: Contributors, Next: Archives, Prev: About pcl-cvs, Up: About pcl-cvs - -Contributors to pcl-cvs -======================= - - Contributions to the package are welcome. I have limited time to -work on this project, but I will gladly add any code that you -contribute to me to this package (*note Bugs::.). - - The following persons have made contributions to pcl-cvs. - - * Brian Berliner wrote CVS, together with some other contributors. - Without his work on CVS this package would be useless... - - * Per Cederqvist wrote most of the otherwise unattributed - functions in pcl-cvs as well as all documentation. - - * Inge Wallin (`inge@lysator.liu.se') wrote the skeleton to - `pcl-cvs.texinfo', and gave useful comments on it. He also wrote - the files `elib-node.el' and `compile-all.el'. The file - `cookie.el' was inspired by Inge. - - * Linus Tolke (`linus@lysator.liu.se') contributed useful comments - on both the functionality and the documentation. - - * Jamie Zawinski (`jwz@lucid.com') contributed `pcl-cvs-lucid.el'. - - * Leif Lonnblad contributed RCVS support. - - Apart from these, a lot of people have send me suggestions, ideas, -requests, bug reports and encouragement. Thanks a lot! Without your -there would be no new releases of pcl-cvs. - - -File: pcl-cvs, Node: Archives, Prev: Contributors, Up: About pcl-cvs - -Where can I get pcl-cvs? -======================== - - The latest release of pcl-cvs can be fetched via anonymous ftp from -`ftp.lysator.liu.se', (IP no. 130.236.254.1) in the directory -`pub/emacs'. If you don't live in Scandinavia you should probably -check with archie to see if there is a site closer to you that -archives pcl-cvs. - - New releases will be announced to appropriate newsgroups. If you -send your email address to me I will add you to my list of people to -mail when I make a new release. - - -File: pcl-cvs, Node: Getting started, Next: Buffer contents, Prev: About pcl-cvs, Up: Top - -Getting started -*************** - - This document assumes that you know what CVS is, and that you at -least knows the fundamental concepts of CVS. If that is not the case -you should read the man page for CVS. - - Pcl-cvs is only useful once you have checked out a module. So -before you invoke it you must have a copy of a module somewhere in -the file system. - - You invoke pcl-cvs by typing `M-x cvs-update RET'. If your emacs -responds with `[No match]' your system administrator has not -installed pcl-cvs properly. Try `M-x load-library RET pcl-cvs RET'. -If that also fails - talk to your root. If it succeeds you might put -this line in your `.emacs' file so that you don't have to type the -`load-library' command every time you wish to use pcl-cvs: - - (autoload 'cvs-update "pcl-cvs" nil t) - - The function `cvs-update' will ask for a directory. The command -`cvs update' will be run in that directory. (It should contain files -that have been checked out from a CVS archive.) The output from -`cvs' will be parsed and presented in a table in a buffer called -`*cvs*'. It might look something like this: - - PCL-CVS release 1.05. - - In directory /users/ceder/FOO/test: - Updated bar - Updated file.txt - Modified ci namechange - Updated newer - - In directory /users/ceder/FOO/test/sub: - Modified ci ChangeLog - ---------- End ----- - - In this example the three files (`bar', `file.txt' and `newer') -that are marked with `Updated' have been copied from the CVS -repository to `/users/ceder/FOO/test/' since someone else have -checked in newer versions of them. Two files (`namechange' and -`sub/ChangeLog') have been modified locally, and needs to be checked -in. - - You can move the cursor up and down in the buffer with `C-n' and -`C-p' or `n' and `p'. If you press `c' on one of the `Modified' -files that file will be checked in to the CVS repository. *Note -Committing changes::. You can press `x' to get rid of the -"uninteresting" files that have only been `Updated' (and don't -require any further action from you). - - You can also easily get a `diff' between your modified file and the -base version that you started from, and you can get the output from -`cvs log' and `cvs status' on the listed files simply by pressing a -key (*note Getting info about files::.). - - -File: pcl-cvs, Node: Buffer contents, Next: Commands, Prev: Getting started, Up: Top - -Buffer contents -*************** - - The display contains four columns. They contain, from left to -right: - - * An asterisk when the file is "marked" (*note Selected files::.). - - * The status of the file. See *Note File status::, for more - information. - - * A "need to be checked in"-marker (`ci'). - - * The file name. - -* Menu: - -* File status:: The meaning of the second field. -* Selected files:: How selection works. - - -File: pcl-cvs, Node: File status, Next: Selected files, Prev: Buffer contents, Up: Buffer contents - -File status -=========== - - The `file status' field can have the following values: - -`Updated' - The file was brought up to date with respect to the repository. - This is done for any file that exists in the repository but not - in your source, and for files that you haven't changed but are - not the most recent versions available in the repository. - -`Modified' - The file is modified in your working directory, and there was - no modification to the same file in the repository. - -`Merged' - The file is modified in your working directory, and there were - modifications in the repository as well as in your copy, but - they were merged successfully, without conflict, in your working - directory. - -`Conflict' - A conflict was detected while trying to merge your changes to - FILE with changes from the source repository. FILE (the copy in - your working directory) is now the output of the `rcsmerge' - command on the two versions; an unmodified copy of your file is - also in your working directory, with the name `.#FILE.VERSION', - where VERSION is the RCS revision that your modified file started - from. *Note Viewing differences::, for more details. - -`Added' - The file has been added by you, but it still needs to be checked - in to the repository. - -`Removed' - The file has been removed by you, but it needs to be checked in - to the repository. You can resurrect it by typing `a' (*note - Adding and removing files::.). - -`Unknown' - A file that was detected in your directory, but that neither - appears in the repository, nor is present on the list of files - that CVS should ignore. - - There are also a few special cases, that rarely occur, which have -longer strings in the fields: - -`Removed from repository' - The file has been removed from your directory since someone has - removed it from the repository. (It is still present in the - Attic directory, so no permanent loss has occurred). This, - unlike the other entries in this table, is not an error - condition. - -`Removed from repository, changed by you' - You have modified a file that someone have removed from the - repository. You can correct this situation by removing the file - manually (see *note Adding and removing files::.). - -`Removed by you, changed in repository' - You have removed a file, and before you committed the removal - someone committed a change to that file. You could use `a' to - resurrect the file (see *note Adding and removing files::.). - -`Move away FILE - it is in the way' - For some reason CVS does not like the file FILE. Rename or - remove it. - -`This repository is missing! Remove this dir manually.' - It is impossible to remove a directory in the CVS repository in - a clean way. Someone have tried to remove one, and CVS gets - confused. Remove your copy of the directory. - - -File: pcl-cvs, Node: Selected files, Prev: File status, Up: Buffer contents - -Selected files -============== - - Many of the commands works on the current set of "selected" files. - - * If there are any files that are marked they constitute the set of - selected files. - - * Otherwise, if the cursor points to a file, that file is the - selected file. - - * Otherwise, if the cursor points to a directory, all the files in - that directory that appears in the buffer are the selected files. - - This scheme might seem a little complicated, but once one get used -to it, it is quite powerful. - - *Note Marking files:: tells how you mark and unmark files. - - -File: pcl-cvs, Node: Commands, Next: Customization, Prev: Buffer contents, Up: Top - -Commands -******** - - The nodes in this menu contains explanations about all the -commands that you can use in pcl-cvs. They are grouped together by -type. - -* Menu: - -* Updating the directory:: Commands to update the local directory -* Movement commands:: How to move up and down in the buffer -* Marking files:: How to mark files that other commands - will later operate on. -* Committing changes:: Checking in your modifications to the - CVS repository. -* Editing files:: Loading files into Emacs. -* Getting info about files:: Display the log and status of files. -* Adding and removing files:: Adding and removing files -* Undoing changes:: Undoing changes -* Removing handled entries:: Uninteresting lines can easily be removed. -* Ignoring files:: Telling CVS to ignore generated files. -* Viewing differences:: Commands to `diff' different versions. -* Emerge:: -* Reverting your buffers:: Reverting your buffers -* Miscellaneous commands:: Miscellaneous commands - - -File: pcl-cvs, Node: Updating the directory, Next: Movement commands, Prev: Commands, Up: Commands - -Updating the directory -====================== - -`M-x cvs-update' - Run a `cvs update' command. You will be asked for the directory - in which the `cvs update' will be run. The output will be - parsed by pcl-cvs, and the result printed in the `*cvs*' buffer - (see *note Buffer contents::. for a description of the contents). - - By default, `cvs-update' will descend recursively into - subdirectories. You can avoid that behavior by giving a prefix - argument to it (e.g., by typing `C-u M-x cvs-update RET'). - - All other commands in pcl-cvs requires that you have a `*cvs*' - buffer. This is the command that you use to get one. - - CVS uses lock files in the repository to ensure the integrity of - the data files in the repository. They might be left behind - i.e. if a workstation crashes in the middle of a CVS operation. - CVS outputs a message when it is waiting for a lock file to go - away. Pcl-cvs will show the same message in the *cvs* buffer, - together with instructions for deleting the lock files. You - should normally not have to delete them manually -- just wait a - little while and the problem should fix itself. But if the lock - files doesn't disappear you can delete them with `M-x - cvs-delete-lock RET'. - -`g' - This will run `cvs update' again. It will always use the same - buffer that was used with the previous `cvs update'. Give a - prefix argument to avoid descending into subdirectories. This - runs the command `cvs-mode-update-no-prompt'. - - -File: pcl-cvs, Node: Movement commands, Next: Marking files, Prev: Updating the directory, Up: Commands - -Movement Commands -================= - - You can use most normal Emacs commands to move forward and -backward in the buffer. Some keys are rebound to functions that take -advantage of the fact that the buffer is a pcl-cvs buffer: - -`SPC' -`C-n' -`n' - These keys move the cursor one file forward, towards the end of - the buffer (`cookie-next-cookie'). - -`C-p' -`p' - These keys move one file backward, towards the beginning of the - buffer (`cookie-previous-cookie'). - - -File: pcl-cvs, Node: Marking files, Next: Committing changes, Prev: Movement commands, Up: Commands - -Marking files -============= - - Pcl-cvs works on a set of "selected files" (*note Selected -files::.). You can mark and unmark files with these commands: - -`m' - This marks the file that the cursor is positioned on. If the - cursor is positioned on a directory all files in that directory - will be marked. (`cvs-mode-mark'). - -`u' - Unmark the file that the cursor is positioned on. If the cursor - is on a directory, all files in that directory will be unmarked. - (`cvs-mode-unmark'). - -`M' - Mark *all* files in the buffer (`cvs-mode-mark-all-files'). - -`ESC DEL' - Unmark *all* files (`cvs-mode-unmark-all-files'). - -`DEL' - Unmark the file on the previous line, and move point to that line - (`cvs-mode-unmark-up'). - - -File: pcl-cvs, Node: Committing changes, Next: Editing files, Prev: Marking files, Up: Commands - -Committing changes -================== - -`c' - All files that have a "need to be checked in"-marker (*note - Buffer contents::.) can be checked in with the `c' command. It - checks in all selected files (*note Selected files::.) (except - those who lack the "ci"-marker - they are ignored). Pressing - `c' causes `cvs-mode-commit' to be run. - - When you press `c' you will get a buffer called - `*cvs-commit-message*'. Enter the log message for the file(s) in - it. When you are ready you should press `C-c C-c' to actually - commit the files (using `cvs-edit-done'). - - Normally the `*cvs-commit-message*' buffer will retain the log - message from the previous commit, but if the variable - `cvs-erase-input-buffer' is set to a non-`nil' value the buffer - will be erased. Point and mark will always be located around the - entire buffer so that you can easily erase it with `C-w' - (`kill-region'). - - If you are editing the files in your emacs an automatic - `revert-buffer' will be performed. (If the file contains `$Id$' - keywords `cvs commit' will write a new file with the new values - substituted. The auto-revert makes sure that you get them into - your buffer). The revert will not occur if you have modified - your buffer, or if `cvs-auto-revert-after-commit' is set to - `nil'. - - -File: pcl-cvs, Node: Editing files, Next: Getting info about files, Prev: Committing changes, Up: Commands - -Editing files -============= - - There are currently three commands that can be used to find a file -(that is, load it into a buffer and start editing it there). These -commands work on the line that the cursor is situated at. They -ignore any marked files. - -`f' - Find the file that the cursor points to. Run `dired' (*note - Dired: (Emacs)Dired.) if the cursor points to a directory - (`cvs-mode-find-file'). - -`o' - Like `f', but use another window - (`cvs-mode-find-file-other-window'). - -`A' - Invoke `add-change-log-entry-other-window' to edit a `ChangeLog' - file. The `ChangeLog' will be found in the directory of the - file the cursor points to. - (`cvs-mode-add-change-log-entry-other-window'). - - -File: pcl-cvs, Node: Getting info about files, Next: Adding and removing files, Prev: Editing files, Up: Commands - -Getting info about files -======================== - - Both of the following commands can be customized. *Note -Customization::. - -`l' - Run `cvs log' on all selected files, and show the result in a - temporary buffer (`cvs-mode-log'). - -`s' - Run `cvs status' on all selected files, and show the result in a - temporary buffer (`cvs-mode-status'). - - -File: pcl-cvs, Node: Adding and removing files, Next: Undoing changes, Prev: Getting info about files, Up: Commands - -Adding and removing files -========================= - - The following commands are available to make it easy to add and -remove files from the CVS repository. - -`a' - Add all selected files. This command can be used on `Unknown' - files (see *note File status::.). The status of the file will - change to `Added', and you will have to use `c' - (`cvs-mode-commit', see *note Committing changes::.) to really - add the file to the repository. - - This command can also be used on `Removed' files (before you - commit them) to resurrect them. - - Selected files that are neither `Unknown' nor `Removed' will be - ignored by this command. - - The command that is run is `cvs-mode-add'. - -`r' - This command removes the selected files (after prompting for - confirmation). The files are `rm'ed from your directory and - (unless the status was `Unknown'; *note File status::.) they will - also be `cvs remove'd. If the files were `Unknown' they will - disappear from the buffer. Otherwise their status will change to - `Removed', and you must use `c' (`cvs-mode-commit', *note - Committing changes::.) to commit the removal. - - The command that is run is `cvs-mode-remove-file'. - - -File: pcl-cvs, Node: Undoing changes, Next: Removing handled entries, Prev: Adding and removing files, Up: Commands - -Undoing changes -=============== - -`U' - If you have modified a file, and for some reason decide that you - don't want to keep the changes, you can undo them with this - command. It works by removing your working copy of the file and - then getting the latest version from the repository - (`cvs-mode-undo-local-changes'. - - -File: pcl-cvs, Node: Removing handled entries, Next: Ignoring files, Prev: Undoing changes, Up: Commands - -Removing handled entries -======================== - -`x' - This command allows you to remove all entries that you have - processed. More specifically, the lines for `Updated' files - (*note File status::. and files that have been checked in (*note - Committing changes::.) are removed from the buffer. If a - directory becomes empty the heading for that directory is also - removed. This makes it easier to get an overview of what needs - to be done. - - The command is called `cvs-mode-remove-handled'. If - `cvs-auto-remove-handled' is set to non-`nil' this will - automatically be performed after every commit. - -`C-k' - This command can be used for lines that - `cvs-mode-remove-handled' would not delete, but that you want to - delete (`cvs-mode-acknowledge'). - - -File: pcl-cvs, Node: Ignoring files, Next: Viewing differences, Prev: Removing handled entries, Up: Commands - -Ignoring files -============== - -`i' - Arrange so that CVS will ignore the selected files. The file - names are added to the `.cvsignore' file in the corresponding - directory. If the `.cvsignore' doesn't exist it will be created. - - The `.cvsignore' file should normally be added to the repository, - but you could ignore it also if you like it better that way. - - This runs `cvs-mode-ignore'. - - -File: pcl-cvs, Node: Viewing differences, Next: Emerge, Prev: Ignoring files, Up: Commands - -Viewing differences -=================== - -`d' - Display a `cvs diff' between the selected files and the RCS - version that they are based on. *Note Customization:: describes - how you can send flags to `cvs diff'. If CVS-DIFF-IGNORE-MARKS - is set to a non-`nil' value or if a prefix argument is given - (but not both) any marked files will not be considered to be - selected. (`cvs-mode-diff-cvs'). - -`b' - If CVS finds a conflict while merging two versions of a file - (during a `cvs update', *note Updating the directory::.) it will - save the original file in a file called `.#FILE.VERSION' where - FILE is the name of the file, and VERSION is the RCS version - number that your file was based on. - - With the `b' command you can run a `diff' on the files - `.#FILE.VERSION' and `FILE'. You can get a context- or Unidiff - by setting `cvs-diff-flags' - *note Customization::.. This - command only works on files that have status `Conflict' or - `Merged'. - - If CVS-DIFF-IGNORE-MARKS is set to a non-`nil' value or if a - prefix argument is given (but not both) any marked files will - not be considered to be selected. (`cvs-mode-diff-backup'). - - -File: pcl-cvs, Node: Emerge, Next: Reverting your buffers, Prev: Viewing differences, Up: Commands - -Running emerge -============== - -`e' - Invoke `emerge' on one file. This command works slightly - different depending on the file status. - - `Modified' - Run `emerge-files' with your working file as file A, and - the latest revision in the repository as file B. - - `Merged' - `Conflict' - Run `emerge-files-with-ancestor' with your working file (as - it was prior to your invocation of `cvs-update') as file A, - the latest revision in the repository as file B, and the - revision that you based your local modifications on as - ancestor. - - *Note:* CVS has already performed a merge. The resulting file is - not used in any way if you use this command. If you use the `q' - command inside `emerge' (to successfully terminate the merge) the - file that CVS created will be overwritten. - - -File: pcl-cvs, Node: Reverting your buffers, Next: Miscellaneous commands, Prev: Emerge, Up: Commands - -Reverting your buffers -====================== - -`R' - If you are editing (or just viewing) a file in a buffer, and - that file is changed by CVS during a `cvs-update', all you have - to do is type `R' in the *cvs* buffer to read in the new - versions of the files. - - All files that are `Updated', `Merged' or in `Conflict' are - reverted from the disk. Any other files are ignored. Only files - that you were already editing are read. - - An error is signalled if you have modified the buffer since it - was last changed. (`cvs-mode-revert-updated-buffers'). - - -File: pcl-cvs, Node: Miscellaneous commands, Prev: Reverting your buffers, Up: Commands - -Miscellaneous commands -====================== - -`M-x cvs-byte-compile-files' - Byte compile all selected files that end in .el. - -`M-x cvs-delete-lock' - This command can be used in any buffer, and deletes the lock - files that the *cvs* buffer informs you about. You should - normally never have to use this command since CVS tries very - carefully to always remove the lock files itself. - - You can only use this command when a message in the *cvs* buffer - tells you so. You should wait a while before using this command - in case someone else is running a cvs command. - -`q' - Bury the *cvs* buffer. (`bury-buffer'). - - -File: pcl-cvs, Node: Customization, Next: Future enhancements, Prev: Commands, Up: Top - -Customization -************* - - If you have an idea about any customization that would be handy but -isn't present in this list, please tell me! *Note Bugs:: for info on -how to reach me. - -`cvs-erase-input-buffer' - If set to anything else than `nil' the edit buffer will be erased - before you write the log message (*note Committing changes::.). - -`cvs-inhibit-copyright-message' - The copyright message that is displayed on startup can be - annoying after a while. Set this variable to `t' if you want to - get rid of it. (But don't set this to `t' in the system defaults - file - new users should see this message at least once). - -`cvs-diff-flags' - A list of strings to pass as arguments to the `cvs diff' and - `diff' programs. This is used by `cvs-mode-diff-cvs' and - `cvs-mode-diff-backup' (key `b', *note Viewing differences::.). - If you prefer the Unidiff format you could add this line to your - `.emacs' file: - - (setq cvs-diff-flags '("-u")) - -`cvs-diff-ignore-marks' - If this variable is non-`nil' or if a prefix argument is given - (but not both) to `cvs-mode-diff-cvs' or `cvs-mode-diff-backup' - marked files are not considered selected. - -`cvs-log-flags' - List of strings to send to `cvs log'. Used by `cvs-mode-log' - (key `l', *note Getting info about files::.). - -`cvs-status-flags' - List of strings to send to `cvs status'. Used by - `cvs-mode-status' (key `s', *note Getting info about files::.). - -`cvs-auto-remove-handled' - If this variable is set to any non-`nil' value - `cvs-mode-remove-handled' will be called every time you check in - files, after the check-in is ready. *Note Removing handled - entries::. - -`cvs-auto-revert-after-commit' - If this variable is set to any non-`nil' value any buffers you - have that visit a file that is committed will be automatically - reverted. This variable is default `t'. *Note Committing - changes::. - -`cvs-update-prog-output-skip-regexp' - The `-u' flag in the `modules' file can be used to run a command - whenever a `cvs update' is performed (see cvs(5)). This regexp - is used to search for the last line in that output. It is - normally set to `"$"'. That setting is only correct if the - command outputs nothing. Note that pcl-cvs will get very - confused if the command outputs *anything* to `stderr'. - -`cvs-cvsroot' - This variable can be set to override `CVSROOT'. It should be a - string. If it is set then everytime a cvs command is run it will - be called as `cvs -d CVS-CVSROOT...' This can be useful if your - site has several repositories. - -`TMPDIR' - Pcl-cvs uses this *environment variable* to decide where to put - the temporary files it needs. It defaults to `/tmp' if it is - not set. - -`cvs-commit-buffer-require-final-newline' - When you enter a log message in the `*cvs-commit-message*' buffer - pcl-cvs will normally automatically insert a trailing newline, - unless there already is one. This behavior can be controlled via - `cvs-commit-buffer-require-final-newline'. If it is `t' (the - default behavior), a newline will always be appended. If it is - `nil', newlines will never be appended. Any other value causes - pcl-cvs to ask the user whenever there is no trailing newline in - the commit message buffer. - -`cvs-sort-ignore-file' - If this variable is set to any non-`nil' value the `.cvsignore' - will always be sorted whenever you use `cvs-mode-ignore' to add - a file to it. This option is on by default. - - -File: pcl-cvs, Node: Future enhancements, Next: Bugs, Prev: Customization, Up: Top - -Future enhancements -******************* - - Pcl-cvs is still under development and needs a number of -enhancements to be called complete. Below is my current wish-list -for future releases of pcl-cvs. Please, let me know which of these -features you want most. They are listed below in approximately the -order that I currently think I will implement them in. - - * Rewritten parser code. There are many situations where pcl-cvs - will fail to recognize the output from CVS. The situation could - be greatly increased. - - * `cvs-status'. This will run `cvs status' in a directory and - produce a buffer that looks pretty much like the current *cvs* - buffer. That buffer will include information for all - version-controlled files. (There will be a simple keystroke to - remove all "uninteresting" files, that is, files that are - "Up-to-date"). In this new buffer you will be able to update a - file, commit a file, et c. The big win with this is that you - will be able to watch the differences between your current - working file and the head revision in the repository before you - update the file, and you can then choose to update it or let it - wait for a while longer. - - * Log mode. When this mode is finished you will be able to move - around (using `n' and `p') between the revisions of a file, mark - two of them, and run a diff between them. You will be able to - hide branches (similar to the way you can hide sub-paragraphs in - outline-mode) and do merges between revisions. Other ideas - about this are welcome. - - * The current model for marks in the *cvs* buffer seems to be - confusing. I am considering to use the VM model instead, where - marks are normally inactive. To activate the mark, you issue a - command like `cvs-mode-next-command-uses-marks'. I might - implement a flag so that you can use either version. Feedback - on this before I start coding it is very welcome. - - * It should be possible to run commands such as `cvs log', `cvs - status' and `cvs commit' directly from a buffer containing a - file, instead of having to `cvs-update'. If the directory - contains many files the `cvs-update' can take quite some time, - especially on a slow machine. I planed to put these kind of - commands on the prefix `C-c C-v', but that turned out to be used - by for instance c++-mode. If you have any suggestions for a - better prefix key, please let me know. - - * Increased robustness. For instance, you can not currently press - `C-g' when you are entering the description of a file that you - are adding without confusing pcl-cvs. - - * Support for multiple active *cvs* buffers. - - * Dired support. I have an experimental `dired-cvs.el' that works - together with CVS 1.2. Unfortunately I wrote it on top of a - non-standard `dired.el', so it must be rewritten. - - * An ability to send user-supplied options to all the cvs commands. - - * Pcl-cvs is not at all clever about what it should do when `cvs - update' runs a program (due to the `-u' option in the `modules' - file -- see `cvs(5)'). The current release uses a regexp to - search for the end. At the very least that regexp should be - configured for different modules. Tell me if you have any idea - about what is the right thing to do. In a perfect world the - program should also be allowed to print to `stderr' without - causing pcl-cvs to crash. - - If you miss something in this wish-list, let me know! I don't -promise that I will write it, but I will at least try to coordinate -the efforts of making a good Emacs front end to CVS. See *Note -Bugs:: for information about how to reach me. - - So far, I have written most of pcl-cvs in my all-to-rare spare -time. If you want pcl-cvs to be developed faster you can write a -contract with Signum Support to do the extension. You can reach -Signum Support by email to `info@signum.se' or via mail to Signum -Support AB, Box 2044, S-580 02 Linkoping, Sweden. Phone: +46 (0) 13 - -21 46 00. Fax: +46 (0) 13 - 21 47 00. - - -File: pcl-cvs, Node: Bugs, Next: Function and Variable Index, Prev: Future enhancements, Up: Top - -Bugs (known and unknown) -************************ - - If you find a bug or misfeature, don't hesitate to tell me! Send -email to `ceder@lysator.liu.se'. - - If you have ideas for improvements, or if you have written some -extensions to this package, I would like to hear from you. I hope -that you find this package useful! - - Below is a partial list of currently known problems with pcl-cvs -version 1.05. - -Commit causes Emacs to hang - Emacs waits for the `cvs commit' command to finish before you can - do anything. If you start a background job from the loginfo - file you must take care that it closes `stdout' and `stderr' if - you do not want to wait for it. (You do that with - `background-command &>- 2&>- &' if you are starting - `background-command' from a `/bin/sh' shell script). - - Your emacs will also hang if there was a lock file in the - repository. In this case you can type `C-g' to get control over - your emacs again. - -Name clash in Emacs 19 - This is really a bug in Elib or the Emacs 19 distribution. Both - Elib and Emacs 19.6 through at least 19.10 contains a file named - `cookie.el'. One of the files will have to be renamed, and we - are currently negotiating about which of the files to rename. - -Commands while cvs-update is running - It is possible to type commands in the *cvs* buffer while the - update is running, but error messages is all that you will get. - The error messages should be better. - -Unexpected output from CVS - Unexpected output from CVS confuses pcl-cvs. It will currently - create a bug report that you can mail to me. It should do - something more civilized. - - -File: pcl-cvs, Node: Function and Variable Index, Next: Concept Index, Prev: Bugs, Up: Top - -Function and Variable Index -*************************** - -* Menu: - -* bury-buffer: Miscellaneous commands. -* cookie-next-cookie: Movement commands. -* cookie-previous-cookie: Movement commands. -* cvs-auto-remove-handled (variable): Customization. -* cvs-auto-revert-after-commit (variable): Customization. -* cvs-auto-revert-after-commit (variable): Committing changes. -* cvs-byte-compile-files: Miscellaneous commands. -* cvs-commit-buffer-require-final-newline (variable): Customization. -* cvs-cvsroot (variable): Customization. -* cvs-delete-lock: Updating the directory. -* cvs-diff-flags (variable): Customization. -* cvs-diff-ignore-marks (variable): Customization. -* cvs-diff-ignore-marks (variable): Viewing differences. -* cvs-erase-input-buffer (variable): Customization. -* cvs-erase-input-buffer (variable): Committing changes. -* cvs-inhibit-copyright-message (variable): Customization. -* cvs-log-flags (variable): Customization. -* cvs-mode-acknowledge: Removing handled entries. -* cvs-mode-add: Adding and removing files. -* cvs-mode-add-change-log-entry-other-window: Editing files. -* cvs-mode-commit: Committing changes. -* cvs-mode-diff-backup: Viewing differences. -* cvs-mode-diff-cvs: Viewing differences. -* cvs-mode-emerge: Emerge. -* cvs-mode-find-file: Editing files. -* cvs-mode-find-file-other-window: Editing files. -* cvs-mode-ignore: Removing handled entries. -* cvs-mode-log: Getting info about files. -* cvs-mode-mark: Marking files. -* cvs-mode-mark-all-files: Marking files. -* cvs-mode-remove-file: Adding and removing files. -* cvs-mode-remove-handled: Removing handled entries. -* cvs-mode-revert-updated-buffers: Reverting your buffers. -* cvs-mode-status: Getting info about files. -* cvs-mode-undo-local-changes: Undoing changes. -* cvs-mode-unmark: Marking files. -* cvs-mode-unmark-all-files: Marking files. -* cvs-mode-unmark-up: Marking files. -* cvs-mode-update-no-prompt: Updating the directory. -* cvs-sort-ignore-file (variable): Customization. -* cvs-status-flags (variable): Customization. -* cvs-update: Updating the directory. -* cvs-update-prog-output-skip-regexp (variable): Customization. -* TMPDIR (environment variable): Customization. - - -File: pcl-cvs, Node: Concept Index, Next: Key Index, Prev: Function and Variable Index, Up: Top - -Concept Index -************* - -* Menu: - -* -u option in modules file: Customization. -* .cvsignore file, sorting: Customization. -* About pcl-cvs: About pcl-cvs. -* Active files: Selected files. -* Added (file status): File status. -* Adding files: Adding and removing files. -* Archives: Archives. -* Author, how to reach: Bugs. -* Authors: Contributors. -* Automatically inserting newline: Customization. -* Automatically remove handled files: Customization. -* Automatically sorting .cvsignore: Customization. -* Buffer contents: Buffer contents. -* Bugs, how to report them: Bugs. -* Bugs, known: Bugs. -* Byte compilation: Miscellaneous commands. -* Ci: Committing changes. -* Commit buffer: Committing changes. -* Commit message, inserting newline: Customization. -* Committing changes: Committing changes. -* Conflict (file status): File status. -* Conflicts, how to resolve them: Viewing differences. -* Conflicts, resolving: Emerge. -* Context diff, how to get: Customization. -* Contributors: Contributors. -* Copyright message, getting rid of it: Customization. -* Customization: Customization. -* Deleting files: Adding and removing files. -* Diff: Viewing differences. -* Dired: Editing files. -* Edit buffer: Committing changes. -* Editing files: Editing files. -* Email archives: Archives. -* Email to the author: Bugs. -* Emerge: Emerge. -* Enhancements: Future enhancements. -* Erasing commit message: Committing changes. -* Erasing the input buffer: Customization. -* Example run: Getting started. -* Expunging uninteresting entries: Removing handled entries. -* FAQ: Bugs. -* File selection: Selected files. -* File status: File status. -* Finding files: Editing files. -* Flush changes: Undoing changes. -* Ftp-sites: Archives. -* Generating a typeset manual: Typeset manual installation. -* Generating the on-line manual: On-line manual installation. -* Getting pcl-cvs: Archives. -* Getting rid of lock files: Miscellaneous commands. -* Getting rid of the Copyright message.: Customization. -* Getting rid of uninteresting lines: Removing handled entries. -* Getting status: Getting info about files. -* Getting the *cvs* buffer: Updating the directory. -* Handled lines, removing them: Removing handled entries. -* Info-file (how to generate): On-line manual installation. -* Inhibiting the Copyright message.: Customization. -* Installation: Installation. -* Installation of elisp files: Pcl-cvs installation. -* Installation of on-line manual: On-line manual installation. -* Installation of typeset manual: Typeset manual installation. -* Introduction: Getting started. -* Invoking dired: Editing files. -* Invoking emerge: Emerge. -* Known bugs: Bugs. -* Loading files: Editing files. -* Lock files: Miscellaneous commands. -* Log (RCS/cvs command): Getting info about files. -* Manual installation (on-line): On-line manual installation. -* Manual installation (typeset): Typeset manual installation. -* Marked files: Selected files. -* Marking files: Marking files. -* Merged (file status): File status. -* Modified (file status): File status. -* Modules file (-u option): Customization. -* Move away FILE - it is in the way (file status): File status. -* Movement Commands: Movement commands. -* On-line manual (how to generate): On-line manual installation. -* Printing a manual: Typeset manual installation. -* Problems, list of common: Bugs. -* Putting files under CVS control: Adding and removing files. -* Recompiling elisp files: Miscellaneous commands. -* Removed (file status): File status. -* Removed by you, changed in repository (file status): File status. -* Removed from repository (file status): File status. -* Removed from repository, changed by you (file status): File status. -* Removing files: Adding and removing files. -* Removing uninteresting (processed) lines: Removing handled entries. -* Reporting bugs and ideas: Bugs. -* Require final newline: Customization. -* Resolving conflicts: Emerge. -* Resurrecting files: Adding and removing files. -* Reverting buffers: Reverting your buffers. -* Reverting buffers after commit: Committing changes. -* Reverting buffers after commit: Customization. -* Selected files: Selected files. -* Selecting files (commands to mark files): Marking files. -* Sites: Archives. -* Sorting the .cvsignore file: Customization. -* Status (cvs command): Getting info about files. -* Syncing buffers: Reverting your buffers. -* TeX - generating a typeset manual: Typeset manual installation. -* This repository is missing!... (file status): File status. -* Undo changes: Undoing changes. -* Unidiff, how to get: Customization. -* Uninteresting entries, getting rid of them: Removing handled entries. -* Unknown (file status): File status. -* Update program (-u option in modules file): Customization. -* Updated (file status): File status. -* Variables, list of all: Customization. -* Viewing differences: Viewing differences. - - -File: pcl-cvs, Node: Key Index, Prev: Concept Index, Up: Top - -Key Index -********* - -* Menu: - -* a - add a file: Adding and removing files. -* A - add ChangeLog entry: Editing files. -* b - diff backup file: Viewing differences. -* c - commit files: Committing changes. -* C-k - remove selected entries: Removing handled entries. -* C-n - Move down one file: Movement commands. -* C-p - Move up one file: Movement commands. -* d - run cvs diff: Viewing differences. -* DEL - unmark previous file: Marking files. -* e - invoke emerge: Emerge. -* ESC DEL - unmark all files: Marking files. -* f - find file or directory: Editing files. -* g - Rerun cvs update: Updating the directory. -* l - run cvs log: Getting info about files. -* m - marking a file: Marking files. -* M - marking all files: Marking files. -* n - Move down one file: Movement commands. -* o - find file in other window: Editing files. -* p - Move up on file: Movement commands. -* q - bury the *cvs* buffer: Miscellaneous commands. -* r - remove a file: Adding and removing files. -* R - revert buffers: Reverting your buffers. -* s - run cvs status: Getting info about files. -* SPC - Move down one file: Movement commands. -* U - undo changes: Undoing changes. -* u - unmark a file: Marking files. -* x - remove processed entries: Removing handled entries. - - - -Tag Table: -Node: Top1007 -Node: Copying3571 -Node: Installation22803 -Node: Pcl-cvs installation23593 -Node: On-line manual installation25654 -Node: Typeset manual installation26672 -Node: About pcl-cvs27411 -Node: Contributors27780 -Node: Archives29083 -Node: Getting started29662 -Node: Buffer contents32105 -Node: File status32654 -Node: Selected files35679 -Node: Commands36347 -Node: Updating the directory37558 -Node: Movement commands39217 -Node: Marking files39803 -Node: Committing changes40658 -Node: Editing files42124 -Node: Getting info about files42969 -Node: Adding and removing files43448 -Node: Undoing changes44799 -Node: Removing handled entries45259 -Node: Ignoring files46176 -Node: Viewing differences46706 -Node: Emerge48014 -Node: Reverting your buffers48988 -Node: Miscellaneous commands49685 -Node: Customization50427 -Node: Future enhancements54107 -Node: Bugs58298 -Node: Function and Variable Index60079 -Node: Concept Index62872 -Node: Key Index69468 - -End Tag Table diff --git a/gnu/usr.bin/cvs/cvs/config.h b/gnu/usr.bin/cvs/cvs/config.h deleted file mode 100644 index b3bee5f..0000000 --- a/gnu/usr.bin/cvs/cvs/config.h +++ /dev/null @@ -1,217 +0,0 @@ -/* @(#)config.h 1.19 92/03/31 */ - -/* - * Copyright (c) 1992, Brian Berliner and Jeff Polk - * Copyright (c) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS 1.3 kit. - * - * This file holds (most of) the configuration tweaks that can be made to - * customize CVS for your site. CVS comes configured for a typical SunOS 4.x - * environment. The comments for each configurable item are intended to be - * self-explanatory. All #defines are tested first to see if an over-riding - * option was specified on the "make" command line. - * - * If special libraries are needed, you will have to edit the Makefile.in file - * or the configure script directly. Sorry. - */ - -/* - * CVS provides the most features when used in conjunction with the Version-5 - * release of RCS. Thus, it is the default. This also assumes that GNU diff - * Version-1.15 is being used as well -- you will have to configure your RCS - * V5 release separately to make this the case. If you do not have RCS V5 and - * GNU diff V1.15, comment out this define. You should not try mixing and - * matching other combinations of these tools. - */ -#ifndef HAVE_RCS5 -#define HAVE_RCS5 -#endif - -/* - * If, before installing this version of CVS, you were running RCS V4 AND you - * are installing this CVS and RCS V5 and GNU diff 1.15 all at the same time, - * you should turn on the following define. It only exists to try to do - * reasonable things with your existing checked out files when you upgrade to - * RCS V5, since the keyword expansion formats have changed with RCS V5. - * - * If you already have been running with RCS5, or haven't been running with CVS - * yet at all, or are sticking with RCS V4 for now, leave the commented out. - */ -#ifndef HAD_RCS4 -/* #define HAD_RCS4 */ -#endif - -/* - * For portability and heterogeneity reasons, CVS is shipped by default using - * my own text-file version of the ndbm database library in the src/myndbm.c - * file. If you want better performance and are not concerned about - * heterogeneous hosts accessing your modules file, turn this option off. - */ -#ifndef MY_NDBM -#define MY_NDBM -#endif - -/* - * The "diff" program to execute when creating patch output. This "diff" - * must support the "-c" option for context diffing. Specify a full pathname - * if your site wants to use a particular diff. If you are using the GNU - * version of diff (version 1.15 or later), this should be "diff -a". - * - * NOTE: this program is only used for the ``patch'' sub-command. The other - * commands use rcsdiff which will use whatever version of diff was specified - * when rcsdiff was built on your system. - */ -#ifndef DIFF -#define DIFF "diff" -#endif - -/* - * The "grep" program to execute when checking to see if a merged file had - * any conflicts. This "grep" must support the "-s" option and a standard - * regular expression as an argument. Specify a full pathname if your site - * wants to use a particular grep. - */ -#ifndef GREP -#define GREP "grep" -#endif - -/* - * The "rm" program to execute when pruning directories that are not part of - * a release. This "rm" must support the "-fr" options. Specify a full - * pathname if your site wants to use a particular rm. - */ -#ifndef RM -#define RM "rm" -#endif - -/* - * The "sort" program to execute when displaying the module database. Specify - * a full pathname if your site wants to use a particular sort. - */ -#ifndef SORT -#define SORT "sort" -#endif - -/* - * By default, RCS programs are executed with the shell or through execlp(), - * so the user's PATH environment variable is searched. If you'd like to - * bind all RCS programs to a certain directory (perhaps one not in most - * people's PATH) then set the default in RCSBIN_DFLT. Note that setting - * this here will cause all RCS programs to be executed from this directory, - * unless the user overrides the default with the RCSBIN environment variable - * or the "-b" option to CVS. - * - * This define should be either the empty string ("") or a full pathname to the - * directory containing all the installed programs from the RCS distribution. - */ -#ifndef RCSBIN_DFLT -#define RCSBIN_DFLT "" -#endif - -/* - * The default editor to use, if one does not specify the "-e" option to cvs, - * or does not have an EDITOR environment variable. I set this to just "vi", - * and use the shell to find where "vi" actually is. This allows sites with - * /usr/bin/vi or /usr/ucb/vi to work equally well (assuming that your PATH - * is reasonable). - */ -#ifndef EDITOR_DFLT -#define EDITOR_DFLT "vi" -#endif - -/* - * The Repository file holds the path to the directory within the source - * repository that contains the RCS ,v files for each CVS working directory. - * This path is either a full-path or a path relative to CVSROOT. - * - * The only advantage that I can see to having a relative path is that One can - * change the physical location of the master source repository, change one's - * CVSROOT environment variable, and CVS will work without problems. I - * recommend using full-paths. - */ -#ifndef RELATIVE_REPOS -/* #define RELATIVE_REPOS */ -#endif - -/* - * When committing or importing files, you must enter a log message. - * Normally, you can do this either via the -m flag on the command line or an - * editor will be started for you. If you like to use logging templates (the - * rcsinfo file within the $CVSROOT/CVSROOT directory), you might want to - * force people to use the editor even if they specify a message with -m. - * Enabling FORCE_USE_EDITOR will cause the -m message to be appended to the - * temp file when the editor is started. - */ -#ifndef FORCE_USE_EDITOR -/* #define FORCE_USE_EDITOR */ -#endif - -/* - * When locking the repository, some sites like to remove locks and assume - * the program that created them went away if the lock has existed for a long - * time. This used to be the default for previous versions of CVS. CVS now - * attempts to be much more robust, so lock files should not be left around - * by mistake. The new behaviour will never remove old locks (they must now - * be removed by hand). Enabling CVS_FUDGELOCKS will cause CVS to remove - * locks that are older than CVSLCKAGE seconds. - * Use of this option is NOT recommended. - */ -#ifndef CVS_FUDGELOCKS -/* #define CVS_FUDGELOCKS */ -#endif - -/* - * When committing a permanent change, CVS and RCS make a log entry of - * who committed the change. If you are committing the change logged in - * as "root" (not under "su" or other root-priv giving program), CVS/RCS - * cannot determine who is actually making the change. - * - * As such, by default, CVS disallows changes to be committed by users - * logged in as "root". You can disable this option by commenting - * out the lines below. - */ -#ifndef CVS_BADROOT -#define CVS_BADROOT -#endif - -/* - * The "cvs diff" command accepts all the single-character options that GNU - * diff (1.15) accepts. Except -D. GNU diff uses -D as a way to put - * cpp-style #define's around the output differences. CVS, by default, uses - * -D to specify a free-form date (like "cvs diff -D '1 week ago'"). If - * you would prefer that the -D option of "cvs diff" work like the GNU diff - * option, then comment out this define. - */ -#ifndef CVS_DIFFDATE -#define CVS_DIFFDATE -#endif - -/* End of CVS configuration section */ - -/* - * Externs that are included in libc, but are used frequently enough to - * warrant defining here. - */ -#ifndef STDC_HEADERS -extern void exit (); -#endif - -#ifndef getwd -extern char *getwd (); -#endif - -/* - * Some UNIX distributions don't include these in their stat.h Defined here - * because "config.h" is always included last. - */ -#ifndef S_IWRITE -#define S_IWRITE 0000200 /* write permission, owner */ -#endif -#ifndef S_IWGRP -#define S_IWGRP 0000020 /* write permission, grougroup */ -#endif -#ifndef S_IWOTH -#define S_IWOTH 0000002 /* write permission, other */ -#endif diff --git a/gnu/usr.bin/cvs/cvs/version.c b/gnu/usr.bin/cvs/cvs/version.c deleted file mode 100644 index 18a9d14..0000000 --- a/gnu/usr.bin/cvs/cvs/version.c +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 1992, Brian Berliner and Jeff Polk - * Copyright (c) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS 1.3 kit. - * - * version.c - the CVS version number - */ - -char *version_string = "\nConcurrent Versions System (CVS) 1.3\n"; diff --git a/gnu/usr.bin/cvs/doc/cvs.ms b/gnu/usr.bin/cvs/doc/cvs.ms deleted file mode 100644 index 567179b..0000000 --- a/gnu/usr.bin/cvs/doc/cvs.ms +++ /dev/null @@ -1,1073 +0,0 @@ -.\" soelim cvs.ms | pic | tbl | troff -ms -.\" @(#)cvs.ms 1.2 92/01/30 -.\" -.\" troff source to the cvs USENIX article, Winter 1990, Washington, D.C. -.\" Copyright (c) 1989, Brian Berliner -.\" -.\" 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 1, or (at your option) -.\" any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program; if not, write to the Free Software -.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -.\" -.\" The author can be reached at: berliner@prisma.com -.\" -.de SP -.if n .sp -.if t .sp .5 -.. -.de hl -.br -.in +0.5i -\l'\\n(LLu-1i' -.in -0.5i -.sp -.. -.OH "" -.nr PS 11 -.nr PO 1.25i -.pl -0.2i -.TL -.ps 14 -.ft B -.nf -CVS II: -Parallelizing Software Development -.fi -.ft -.ps -.AU -.ps 12 -.ft I -Brian Berliner -.ft -.ps -.AI -.ps 12 -.ft I -Prisma, Inc. -5465 Mark Dabling Blvd. -Colorado Springs, CO 80918 -berliner@prisma.com -.ft -.ps -.AB -The program described in this paper fills a need in the UNIX -community for a freely available tool to manage software revision and -release control in a multi-developer, multi-directory, multi-group -environment. -This tool also addresses the increasing need for tracking third-party vendor -source distributions while trying to maintain local modifications to -earlier releases. -.AE -.NH -Background -.PP -In large software development projects, it is usually necessary for more -than one software developer to be modifying (usually different) modules of the -code at the same time. -Some of these code modifications are done in an -experimental sense, at least until the code functions correctly, and some -testing of the entire program is usually necessary. -Then, the modifications are returned to a master source repository -so that others in the project can -enjoy the new bug-fix or functionality. -In order to manage such a project, some sort of revision control system is -necessary. -.PP -Specifically, UNIX\** -.FS -UNIX is a registered trademark of AT&T. -.FE -kernel development is an excellent example of the -problems that an adequate revision control system must address. -The SunOS\** -.FS -SunOS is a trademark of Sun Microsystems, Inc. -.FE -kernel is composed of over a thousand files spread across a -hierarchy of dozens of directories.\** -.FS -Yes, the SunOS 4.0 kernel is composed of over a \fIthousand\fP files! -.FE -Pieces of the kernel must be edited -by many software developers within an organization. -While undesirable in -theory, it is not uncommon to have two or more people making -modifications to the same file within the kernel sources in -order to facilitate a desired change. -Existing revision control systems like -.SM -RCS -.LG -[Tichy] or -.SM -SCCS -.LG -[Bell] serialize file modifications by -allowing only one developer to have a writable copy of a particular file at -any one point in time. -That developer is said to -have \*Qlocked\*U the file for his exclusive use, and no other developer is -allowed to check out a writable copy of the file until the locking -developer has finished impeding others' productivity. -Development pressures of productivity and deadlines -often force organizations to require that multiple developers be able to -simultaneously edit -copies of the same revision controlled file. -.PP -The necessity for multiple developers to modify the same file concurrently -questions the value of serialization-based policies in traditional revision -control. -This paper discusses the approach that -Prisma took in adapting a standard revision control system, -.SM -RCS\c -.LG -, along with an existing public-domain collection of shell scripts that sits -atop -.SM -RCS -.LG -and provides the basic conflict-resolution algorithms. -The resulting -program, \fBcvs\fP, addresses not only the issue of conflict-resolution in -a multi-developer open-editing environment, but also the issues of -software release control and vendor source support and integration. -.NH -The CVS Program -.PP -\fBcvs\fP -(Concurrent Versions System) -is a front end to the -.SM -RCS -.LG -revision control system which extends -the notion of revision control from a collection of files in a single -directory to a hierarchical collection of directories each containing -revision controlled files. -Directories and files in the \fBcvs\fP system can be combined together in -many ways to form a software release. -\fBcvs\fP -provides the functions necessary to manage these software releases and to -control the concurrent editing of source files among multiple software -developers. -.PP -The six major features of \fBcvs\fP are listed below, and will be -described in more detail in the following sections: -.RS -.IP 1. -Concurrent access and conflict-resolution algorithms to guarantee that -source changes are not \*Qlost.\*U -.IP 2. -Support for tracking third-party vendor source distributions while -maintaining the local modifications made to those sources. -.IP 3. -A flexible module database that provides a symbolic mapping of names to -components of a larger software distribution. -This symbolic mapping provides for location independence within the software -release and, for example, allows one to check out a copy of the \*Qdiff\*U -program without ever knowing that the sources to \*Qdiff\*U actually reside -in the \*Qbin/diff\*U directory. -.IP 4. -Configurable logging support allows all \*Qcommitted\*U source file changes -to be logged using an arbitrary program to save the log messages in a file, -notesfile, or news database. -.IP 5. -A software release can be symbolically tagged and checked out at any time -based on that tag. -An exact copy of a previous software release can be checked out at -any time, \fIregardless\fP of whether files or directories have been -added/removed from the \*Qcurrent\*U software release. -As well, -a \*Qdate\*U can be used to check out the \fIexact\fP version of the software -release as of the specified date. -.IP 6. -A \*Qpatch\*U format file [Wall] can be produced between two software -releases, even if the releases span multiple directories. -.RE -.PP -The sources maintained by \fBcvs\fP are kept within a single directory -hierarchy known as the \*Qsource repository.\*U -This \*Qsource repository\*U holds the actual -.SM -RCS -.LG -\*Q,v\*U files directly, as well as a special per-repository directory -(\c -.SM -CVSROOT.adm\c -.LG -) which contains a small number of administrative files that describe the -repository and how it can be accessed. -See Figure 1 for a picture of the \fBcvs\fP tree. -.KF -.hl -.DS B -.PS -line from 4.112,9.200 to 5.550,8.887 -line from 5.447,8.884 to 5.550,8.887 to 5.458,8.933 -line from 4.112,9.200 to 4.550,8.950 -line from 4.451,8.978 to 4.550,8.950 to 4.476,9.021 -line from 4.112,9.200 to 3.737,8.887 -line from 3.798,8.971 to 3.737,8.887 to 3.830,8.932 -line from 3.612,8.762 to 4.737,8.137 -line from 4.638,8.164 to 4.737,8.137 to 4.662,8.208 -line from 3.612,8.762 to 3.737,8.137 -line from 3.693,8.231 to 3.737,8.137 to 3.742,8.240 -line from 3.612,8.762 to 2.612,8.200 -line from 2.687,8.271 to 2.612,8.200 to 2.712,8.227 -line from 2.362,9.262 to 2.737,8.950 -line from 2.645,8.995 to 2.737,8.950 to 2.677,9.033 -line from 2.362,9.262 to 1.925,8.950 -line from 1.992,9.028 to 1.925,8.950 to 2.021,8.988 -line from 3.362,9.762 to 4.050,9.387 -line from 3.950,9.413 to 4.050,9.387 to 3.974,9.457 -line from 3.362,9.762 to 2.487,9.387 -line from 2.570,9.450 to 2.487,9.387 to 2.589,9.404 -.ps 11 -"newfs.c,v" at 4.487,8.043 ljust -.ps 11 -"mkfs.c,v" at 3.487,8.043 ljust -.ps 11 -"Makefile,v" at 2.237,8.043 ljust -.ps 11 -"newfs" at 3.487,8.793 ljust -.ps 11 -"halt.c,v" at 5.487,8.793 ljust -.ps 11 -"Makefile,v" at 4.237,8.793 ljust -.ps 11 -"modules,v" at 2.487,8.793 ljust -.ps 11 -"loginfo,v" at 1.488,8.793 ljust -.ps 11 -"etc" at 3.987,9.293 ljust -.ps 11 -"CVSROOT.adm" at 1.988,9.293 ljust -.ps 11 -"/src/master" at 2.987,9.793 ljust -.PE -.DE -.hl -.ce 100 -.LG -\fBFigure 1.\fP -.SM -\fBcvs\fP Source Repository -.ce 0 -.sp -.KE -.NH 2 -Software Conflict Resolution\** -.FS -The basic conflict-resolution algorithms -used in the \fBcvs\fP program find their roots -in the original work done by Dick Grune at Vrije Universiteit in Amsterdam -and posted to \fBcomp.sources.unix\fP in the volume 6 release sometime in 1986. -This original version of \fBcvs\fP was a collection of shell scripts that -combined to form a front end to the -.SM -RCS -.LG -programs. -.FE -.PP -\fBcvs\fP allows several software developers to edit personal copies of a -revision controlled file concurrently. -The revision number of each checked out file is maintained independently -for each user, and \fBcvs\fP forces the checked out file to be current with -the \*Qhead\*U revision before it can be \*Qcommitted\*U as a permanent change. -A checked out file is brought up-to-date with the \*Qhead\*U revision using -the \*Qupdate\*U command of \fBcvs\fP. -This command compares the \*Qhead\*U revision number with that of the user's -file and performs an -.SM -RCS -.LG -merge operation if they are not the same. -The result of the merge is a file that contains the user's modifications -and those modifications that were \*Qcommitted\*U after the user -checked out his version of the file (as well as a backup copy of the -user's original file). -\fBcvs\fP points out any conflicts during the merge. -It is the user's responsibility to resolve these conflicts -and to \*Qcommit\*U his/her changes when ready. -.PP -Although the \fBcvs\fP conflict-resolution algorithm was defined in 1986, -it is remarkably similar to the \*QCopy-Modify-Merge\*U scenario included -with NSE\** -.FS -NSE is the Network Software Environment, a product of Sun Microsystems, Inc. -.FE -and described in [Honda] and [Courington]. -The following explanation from [Honda] also applies to \fBcvs\fP: -.QP -Simply stated, a developer copies an object without locking it, modifies -the copy, and then merges the modified copy with the original. -This paradigm allows developers to work in isolation from one another since -changes are made to copies of objects. -Because locks are not used, development is not serialized and can proceed -in parallel. -Developers, however, must merge objects after the changes have been made. -In particular, a developer must resolve conflicts when the same object has -been modified by someone else. -.PP -In practice, Prisma has found that conflicts that occur when the same -object has been modified by someone else are quite rare. -When they do happen, the changes made by the other developer are usually -easily resolved. -This practical use has shown that the \*QCopy-Modify-Merge\*U paradigm is a -correct and useful one. -.NH 2 -Tracking Third-Party Source Distributions -.PP -Currently, a large amount of software is based on source -distributions from a third-party distributor. -It is often the case that local modifications are to be made to this -distribution, \fIand\fP that the vendor's future releases should be -tracked. -Rolling your local modifications forward into the new vendor release is a -time-consuming task, but \fBcvs\fP can ease this burden somewhat. -The \fBcheckin\fP program of \fBcvs\fP initially sets up a source -repository by integrating the source modules directly from the vendor's -release, preserving the directory hierarchy of the vendor's distribution. -The branch support of -.SM -RCS -.LG -is used to build this vendor release as a branch of the main -.SM -RCS -.LG -trunk. -Figure 2 shows how the \*Qhead\*U tracks a sample vendor -branch when no local modifications have been made to the file. -.KF -.hl -.DS B -.PS -ellipse at 3.237,6.763 wid 1.000 ht 0.500 -dashwid = 0.050i -line dashed from 3.237,7.513 to 3.737,7.513 to 3.737,9.762 to 4.237,9.762 -line from 4.138,9.737 to 4.237,9.762 to 4.138,9.787 -line dashed from 2.237,8.262 to 3.237,8.262 to 3.237,7.013 -line from 3.212,7.112 to 3.237,7.013 to 3.262,7.112 -line from 3.737,6.763 to 4.237,6.763 -line from 4.138,6.737 to 4.237,6.763 to 4.138,6.788 -line from 2.237,6.763 to 2.737,6.763 -line from 2.637,6.737 to 2.737,6.763 to 2.637,6.788 -line from 1.738,6.013 to 1.738,6.513 -line from 1.762,6.413 to 1.738,6.513 to 1.713,6.413 -line from 1.238,7.013 to 2.237,7.013 to 2.237,6.513 to 1.238,6.513 to 1.238,7.013 -line from 4.237,9.012 to 5.237,9.012 to 5.237,8.512 to 4.237,8.512 to 4.237,9.012 -line from 4.237,8.012 to 5.237,8.012 to 5.237,7.513 to 4.237,7.513 to 4.237,8.012 -line from 4.237,7.013 to 5.237,7.013 to 5.237,6.513 to 4.237,6.513 to 4.237,7.013 -line from 4.737,7.013 to 4.737,7.513 -line from 4.763,7.413 to 4.737,7.513 to 4.712,7.413 -line from 4.737,8.012 to 4.737,8.512 -line from 4.763,8.412 to 4.737,8.512 to 4.712,8.412 -line from 4.237,10.012 to 5.237,10.012 to 5.237,9.512 to 4.237,9.512 to 4.237,10.012 -line from 4.737,9.012 to 4.737,9.512 -line from 4.763,9.412 to 4.737,9.512 to 4.712,9.412 -line from 5.987,5.013 to 5.987,6.013 to 0.988,6.013 to 0.988,5.013 to 5.987,5.013 -.ps 11 -"\"HEAD\"" at 1.550,8.231 ljust -.ps 11 -"'SunOS'" at 2.987,6.293 ljust -.ps 11 -"1.1.1" at 3.050,6.793 ljust -.ps 11 -"1.1" at 1.613,6.793 ljust -.ps 11 -"1.1.1.1" at 4.487,6.793 ljust -.ps 11 -"1.1.1.2" at 4.487,7.793 ljust -.ps 11 -"1.1.1.3" at 4.487,8.793 ljust -.ps 11 -"1.1.1.4" at 4.487,9.793 ljust -.ps 11 -"'SunOS_4_0'" at 5.487,6.793 ljust -.ps 11 -"'SunOS_4_0_1'" at 5.487,7.793 ljust -.ps 11 -"'YAPT_5_5C'" at 5.487,8.793 ljust -.ps 11 -"'SunOS_4_0_3'" at 5.487,9.793 ljust -.ps 11 -"rcsfile.c,v" at 2.987,5.543 ljust -.PE -.DE -.hl -.ce 100 -.LG -\fBFigure 2.\fP -.SM -\fBcvs\fP Vendor Branch Example -.ce 0 -.sp .3 -.KE -Once this is done, developers can check out files and make local changes to -the vendor's source distribution. -These local changes form a new branch to the tree which is then used as the -source for future check outs. -Figure 3 shows how the \*Qhead\*U moves to the main -.SM -RCS -.LG -trunk when a local modification is made. -.KF -.hl -.DS B -.PS -ellipse at 3.237,6.763 wid 1.000 ht 0.500 -dashwid = 0.050i -line dashed from 2.800,9.075 to 1.738,9.075 to 1.738,8.012 -line from 1.713,8.112 to 1.738,8.012 to 1.762,8.112 -line from 1.738,7.013 to 1.738,7.513 -line from 1.762,7.413 to 1.738,7.513 to 1.713,7.413 -line from 1.238,8.012 to 2.237,8.012 to 2.237,7.513 to 1.238,7.513 to 1.238,8.012 -line from 3.737,6.763 to 4.237,6.763 -line from 4.138,6.737 to 4.237,6.763 to 4.138,6.788 -line from 2.237,6.763 to 2.737,6.763 -line from 2.637,6.737 to 2.737,6.763 to 2.637,6.788 -line from 1.738,6.013 to 1.738,6.513 -line from 1.762,6.413 to 1.738,6.513 to 1.713,6.413 -line from 1.238,7.013 to 2.237,7.013 to 2.237,6.513 to 1.238,6.513 to 1.238,7.013 -line from 4.237,9.012 to 5.237,9.012 to 5.237,8.512 to 4.237,8.512 to 4.237,9.012 -line from 4.237,8.012 to 5.237,8.012 to 5.237,7.513 to 4.237,7.513 to 4.237,8.012 -line from 4.237,7.013 to 5.237,7.013 to 5.237,6.513 to 4.237,6.513 to 4.237,7.013 -line from 4.737,7.013 to 4.737,7.513 -line from 4.763,7.413 to 4.737,7.513 to 4.712,7.413 -line from 4.737,8.012 to 4.737,8.512 -line from 4.763,8.412 to 4.737,8.512 to 4.712,8.412 -line from 4.237,10.012 to 5.237,10.012 to 5.237,9.512 to 4.237,9.512 to 4.237,10.012 -line from 4.737,9.012 to 4.737,9.512 -line from 4.763,9.412 to 4.737,9.512 to 4.712,9.412 -line from 5.987,5.013 to 5.987,6.013 to 0.988,6.013 to 0.988,5.013 to 5.987,5.013 -.ps 11 -"1.2" at 1.613,7.793 ljust -.ps 11 -"\"HEAD\"" at 2.862,9.043 ljust -.ps 11 -"'SunOS'" at 2.987,6.293 ljust -.ps 11 -"1.1.1" at 3.050,6.793 ljust -.ps 11 -"1.1" at 1.613,6.793 ljust -.ps 11 -"1.1.1.1" at 4.487,6.793 ljust -.ps 11 -"1.1.1.2" at 4.487,7.793 ljust -.ps 11 -"1.1.1.3" at 4.487,8.793 ljust -.ps 11 -"1.1.1.4" at 4.487,9.793 ljust -.ps 11 -"'SunOS_4_0'" at 5.487,6.793 ljust -.ps 11 -"'SunOS_4_0_1'" at 5.487,7.793 ljust -.ps 11 -"'YAPT_5_5C'" at 5.487,8.793 ljust -.ps 11 -"'SunOS_4_0_3'" at 5.487,9.793 ljust -.ps 11 -"rcsfile.c,v" at 2.987,5.543 ljust -.PE -.DE -.hl -.ce 100 -.LG -\fBFigure 3.\fP -.SM -\fBcvs\fP Local Modification to Vendor Branch -.ce 0 -.sp -.KE -.PP -When a new version of the vendor's source distribution arrives, the -\fBcheckin\fP program adds the new and changed vendor's files to the -already existing source repository. -For files that have not been changed locally, the new file from the -vendor becomes the current \*Qhead\*U revision. -For files that have been modified locally, \fBcheckin\fP warns that the -file must be merged with the new vendor release. -The \fBcvs\fP \*Qjoin\*U command is a useful tool that aids this process by -performing the necessary -.SM -RCS -.LG -merge, as is done above when performing an \*Qupdate.\*U -.PP -There is also limited support for \*Qdual\*U derivations for source files. -See Figure 4 for a sample dual-derived file. -.KF -.hl -.DS B -.PS -ellipse at 2.337,8.575 wid 0.700 ht 0.375 -ellipse at 2.312,9.137 wid 0.700 ht 0.375 -line from 1.225,9.012 to 1.225,9.363 -line from 1.250,9.263 to 1.225,9.363 to 1.200,9.263 -line from 0.875,9.725 to 1.600,9.725 to 1.600,9.363 to 0.875,9.363 to 0.875,9.725 -line from 0.875,9.012 to 1.600,9.012 to 1.600,8.650 to 0.875,8.650 to 0.875,9.012 -line from 4.050,10.200 to 4.775,10.200 to 4.775,9.850 to 4.050,9.850 to 4.050,10.200 -line from 4.050,9.475 to 4.775,9.475 to 4.775,9.113 to 4.050,9.113 to 4.050,9.475 -line from 4.050,8.762 to 4.775,8.762 to 4.775,8.400 to 4.050,8.400 to 4.050,8.762 -line from 4.425,8.762 to 4.425,9.113 -line from 4.450,9.013 to 4.425,9.113 to 4.400,9.013 -line from 4.425,9.475 to 4.425,9.850 -line from 4.450,9.750 to 4.425,9.850 to 4.400,9.750 -line from 3.050,10.000 to 3.775,10.000 to 3.775,9.637 to 3.050,9.637 to 3.050,10.000 -line from 3.050,9.312 to 3.775,9.312 to 3.775,8.950 to 3.050,8.950 to 3.050,9.312 -line from 0.713,7.325 to 0.713,8.075 to 4.925,8.075 to 4.925,7.325 to 0.713,7.325 -line from 1.238,8.075 to 1.238,8.637 -line from 1.262,8.537 to 1.238,8.637 to 1.213,8.537 -line from 1.613,8.825 to 1.975,8.575 -line from 1.878,8.611 to 1.975,8.575 to 1.907,8.652 -line from 2.675,8.575 to 4.050,8.575 -line from 3.950,8.550 to 4.050,8.575 to 3.950,8.600 -line from 2.675,9.137 to 3.050,9.137 -line from 2.950,9.112 to 3.050,9.137 to 2.950,9.162 -line from 3.425,9.325 to 3.425,9.637 -line from 3.450,9.537 to 3.425,9.637 to 3.400,9.537 -line from 1.613,8.825 to 1.925,9.137 -line from 1.872,9.049 to 1.925,9.137 to 1.837,9.084 -.ps 11 -"'BSD'" at 2.138,9.481 ljust -.ps 11 -"1.2" at 1.113,9.543 ljust -.ps 11 -"1.1" at 1.125,8.831 ljust -.ps 11 -"1.1.1.1" at 4.175,8.543 ljust -.ps 11 -"1.1.1.2" at 4.175,9.281 ljust -.ps 11 -"1.1.1.3" at 4.175,9.993 ljust -.ps 11 -"1.1.2.2" at 3.175,9.793 ljust -.ps 11 -"1.1.2.1" at 3.175,9.106 ljust -.ps 11 -"rcsfile.c,v" at 2.425,7.706 ljust -.ps 11 -"1.1.1" at 2.175,8.568 ljust -.ps 11 -"'SunOS'" at 2.125,8.243 ljust -.ps 11 -"1.1.2" at 2.163,9.131 ljust -.PE -.DE -.hl -.ce 100 -.LG -\fBFigure 4.\fP -.SM -\fBcvs\fP Support For \*QDual\*U Derivations -.ce 0 -.sp -.KE -This example tracks the SunOS distribution but includes major changes from -Berkeley. -These BSD files are saved directly in the -.SM -RCS -.LG -file off a new branch. -.NH 2 -Location Independent Module Database -.PP -\fBcvs\fP contains support for a simple, yet powerful, \*Qmodule\*U database. -For reasons of efficiency, this database is stored in \fBndbm\fP\|(3) format. -The module database is used to apply names to collections of directories -and files as a matter of convenience for checking out pieces of a large -software distribution. -The database records the physical location of the sources as a form of -information hiding, allowing one to check out whole directory hierarchies -or individual files without regard for their actual location within the -global source distribution. -.PP -Consider the following small sample of a module database, which must be -tailored manually to each specific source repository environment: -.DS -\f(CW #key [-option argument] directory [files...] - diff bin/diff - libc lib/libc - sys -o sys/tools/make_links sys - modules -i mkmodules CVSROOT.adm modules - kernel -a sys lang/adb - ps bin Makefile ps.c\fP -.DE -.PP -The \*Qdiff\*U and \*Qlibc\*U modules refer to whole directory hierarchies that -are extracted on check out. -The \*Qsys\*U module extracts the \*Qsys\*U hierarchy, and runs the -\*Qmake_links\*U program at the end of the check out process (the \fI-o\fP -option specifies a program to run on check\fIo\fPut). -The \*Qmodules\*U module allows one to edit the module database file and -runs the \*Qmkmodules\*U program on check\fIi\fPn to regenerate the -\fBndbm\fP database that \fBcvs\fP uses. -The \*Qkernel\*U module is an alias (as the \fI-a\fP option specifies) -which causes the remaining arguments after the \fI-a\fP to be interpreted -exactly as if they had been specified on the command line. -This is useful for objects that require shared pieces of code from far away -places to be compiled (as is the case with the kernel debugger, \fBkadb\fP, -which shares code with the standard \fBadb\fP debugger). -The \*Qps\*U module shows that the source for \*Qps\*U lives in the \*Qbin\*U -directory, but only \fIMakefile\fP and \fIps.c\fP are required to build the -object. -.PP -The module database at Prisma is now populated for the entire UNIX -distribution and thereby allows us to issue the -following convenient commands to check out components of the UNIX -distribution without regard for their actual location within the master source -repository: -.DS -\f(CW example% cvs checkout diff - example% cvs checkout libc ps - example% cd diff; make\fP -.DE -.PP -In building the module database file, it is quite possible to have name -conflicts within a global software distribution. -For example, SunOS provides two \fBcat\fP programs: -one for the standard environment, \fI/bin/cat\fP, and one for the System V -environment, \fI/usr/5bin/cat\fP. -We resolved this conflict by naming the standard \fBcat\fP module -\*Qcat\*U, and the System V \fBcat\fP module \*Q5cat\*U. -Similar name modifications must be applied to other conflicting names, as -might be found between a utility program and a library function, though -Prisma chose not to include individual library functions within the module -database at this time. -.NH 2 -Configurable Logging Support -.PP -The \fBcvs\fP \*Qcommit\*U command is used to make a permanent change to the -master source repository (where the -.SM -RCS -.LG -\*Q,v\*U files live). -Whenever a \*Qcommit\*U is done, the log message for the change is carefully -logged by an arbitrary program (in a file, notesfile, news database, or -mail). -For example, a collection of these updates can be used to produce release -notices. -\fBcvs\fP can be configured to send log updates through one or more filter -programs, based on a regular expression match on the directory that is -being changed. -This allows multiple related or unrelated projects to exist within a single -\fBcvs\fP source repository tree, with each different project sending its -\*Qcommit\*U reports to a unique log device. -.PP -A sample logging configuration file might look as follows: -.DS -\f(CW #regex filter-program - DEFAULT /usr/local/bin/nfpipe -t %s utils.updates - ^diag /usr/local/bin/nfpipe -t %s diag.updates - ^local /usr/local/bin/nfpipe -t %s local.updates - ^perf /usr/local/bin/nfpipe -t %s perf.updates - ^sys /usr/local/bin/nfpipe -t %s kernel.updates\fP -.DE -.PP -This sample allows the diagnostics and performance groups to -share the same source repository with the kernel and utilities groups. -Changes that they make are sent directly to their own notesfile [Essick] -through the \*Qnfpipe\*U program. -A sufficiently simple title is substituted for the \*Q%s\*U argument before -the filter program is executed. -This logging configuration file is tailored manually to each specific -source repository environment. -.NH 2 -Tagged Releases and Dates -.PP -Any release can be given a symbolic tag name that is stored directly in the -.SM -RCS -.LG -files. -This tag can be used at any time to get an exact copy of any previous -release. -With equal ease, one can also extract an exact copy of the source files as -of any arbitrary date in the past as well. -Thus, all that's required to tag the current kernel, and to tag the kernel -as of the Fourth of July is: -.DS -\f(CW example% cvs tag TEST_KERNEL kernel - example% cvs tag -D 'July 4' PATRIOTIC_KERNEL kernel\fP -.DE -The following command would retrieve an exact copy of the test kernel at -some later date: -.DS -\f(CW example% cvs checkout -fp -rTEST_KERNEL kernel\fP -.DE -The \fI-f\fP option causes only files that match the specified tag to be -extracted, while the \fI-p\fP option automatically prunes empty directories. -Consequently, directories added to the kernel after the test kernel was -tagged are not included in the newly extracted copy of the test kernel. -.PP -The \fBcvs\fP date support has exactly the same interface as that provided -with -.SM -RCS\c -.LG -, however \fBcvs\fP must process the \*Q,v\*U files directly due to the -special handling required by the vendor branch support. -The standard -.SM -RCS -.LG -date handling only processes one branch (or the main trunk) when checking -out based on a date specification. -\fBcvs\fP must instead process the current \*Qhead\*U branch and, if a -match is not found, proceed to look for a match on the vendor branch. -This, combined with reasons of performance, is why \fBcvs\fP processes -revision (symbolic and numeric) and date specifications directly from the -\*Q,v\*U files. -.NH 2 -Building \*Qpatch\*U Source Distributions -.PP -\fBcvs\fP can produce a \*Qpatch\*U format [Wall] output file which can be -used to bring a previously released software distribution current with the -newest release. -This patch file supports an entire directory hierarchy within a single -patch, as well as being able to add whole new files to the previous -release. -One can combine symbolic revisions and dates together to display changes in -a very generic way: -.DS -\f(CW example% cvs patch -D 'December 1, 1988' \e - -D 'January 1, 1989' sys\fP -.DE -This example displays the kernel changes made in the month of December, -1988. -To release a patch file, for example, to take the \fBcvs\fP distribution -from version 1.0 to version 1.4 might be done as follows: -.DS -\f(CW example% cvs patch -rCVS_1_0 -rCVS_1_4 cvs\fP -.DE -.NH -CVS Experience -.NH 2 -Statistics -.PP -A quick summary of the scale that \fBcvs\fP is addressing today -can be found in Table 1. -.KF -.TS -box center tab(:); -c s -c s -c | c -l | n . -\fB\s+2Revision Control Statistics at Prisma -as of 11/11/89\fP\s-2 -_ -How Many...:Total -= -Files:17243 -Directories:1005 -Lines of code:3927255 -Removed files:131 -Software developers:14 -Software groups:6 -Megabytes of source:128 -.TE -.ce 100 -.LG -\fBTable 1.\fP -.SM -\fBcvs\fP Statistics -.ce 0 -.sp .3 -.KE -Table 2 shows the history of files changed or added and the number -of source lines affected by the change at Prisma. -Only changes made to the kernel sources are included. -.KF -.TS -box center tab(:); -c s s s s -c s s s s -c || c | c || c | c -c || c | c || c | c -l || n | n || n | n. -\fB\s+2Prisma Kernel Source File Changes -By Month, 1988-1989\fP\s-2 -_ -Month:# Changed:# Lines:# Added:# Lines -\^:Files:Changed:Files:Added -= -Dec:87:3619:68:9266 -Jan:39:4324:0:0 -Feb:73:1578:5:3550 -Mar:99:5301:18:11461 -Apr:112:7333:11:5759 -May:138:5371:17:13986 -Jun:65:2261:27:12875 -Jul:34:2000:1:58 -Aug:65:6378:8:4724 -Sep:266:23410:113:39965 -Oct:22:621:1:155 -Total:1000:62196:269:101799 -.TE -.ce 100 -.LG -\fBTable 2.\fP -.SM -\fBcvs\fP Usage History for the Kernel -.ce 0 -.sp -.KE -The large number of source file changes made in September are the result of -merging the SunOS 4.0.3 sources into the kernel. -This merge process is described in section 3.3. -.NH 2 -Performance -.PP -The performance of \fBcvs\fP is currently quite reasonable. -Little effort has been expended on tuning \fBcvs\fP, although performance -related decisions were made during the \fBcvs\fP design. -For example, \fBcvs\fP parses the -.SM -RCS -.LG -\*Q,v\*U files directly instead of running an -.SM -RCS -.LG -process. -This includes following branches as well as integrating with the vendor -source branches and the main trunk when checking out files based on a date. -.PP -Checking out the entire kernel source tree (1223 files/59 directories) -currently takes 16 wall clock minutes on a Sun-4/280. -However, bringing the tree up-to-date with the current kernel sources, once -it has been checked out, takes only 1.5 wall clock minutes. -Updating the \fIcomplete\fP 128 MByte source tree under \fBcvs\fP control -(17243 files/1005 directories) takes roughly 28 wall clock minutes and -utilizes one-third of the machine. -For now this is entirely acceptable; improvements on these numbers will -possibly be made in the future. -.NH 2 -The SunOS 4.0.3 Merge -.PP -The true test of the \fBcvs\fP vendor branch support came with the arrival -of the SunOS 4.0.3 source upgrade tape. -As described above, the \fBcheckin\fP program was used to install the new -sources and the resulting output file listed the files that had been -locally modified, needing to be merged manually. -For the kernel, there were 94 files in conflict. -The \fBcvs\fP \*Qjoin\*U command was used on each of the 94 conflicting -files, and the remaining conflicts were resolved. -.PP -The \*Qjoin\*U command performs an \fBrcsmerge\fP operation. -This in turn uses \fI/usr/lib/diff3\fP to produce a three-way diff file. -As it happens, the \fBdiff3\fP program has a hard-coded limit of 200 -source-file changes maximum. -This proved to be too small for a few of the kernel files that needed -merging by hand, due to the large number of local changes that Prisma had -made. -The \fBdiff3\fP problem was solved by increasing the hard-coded limit by an -order of magnitude. -.PP -The SunOS 4.0.3 kernel source upgrade distribution contained -346 files, 233 of which were modifications to previously released files, -and 113 of which were newly added files. -\fBcheckin\fP added the 113 new files to the source repository -without intervention. -Of the 233 modified files, 139 dropped in cleanly by \fBcheckin\fP, since -Prisma had not made any local changes to them, and 94 required manual -merging due to local modifications. -The 233 modified files consisted of 20,766 lines of differences. -It took one developer two days to manually merge the 94 files using the -\*Qjoin\*U command and resolving conflicts manually. -An additional day was required for kernel debugging. -The entire process of merging over 20,000 lines of differences was -completed in less than a week. -This one time-savings alone was justification enough for the \fBcvs\fP -development effort; we expect to gain even more when tracking future SunOS -releases. -.NH -Future Enhancements and Current Bugs -.PP -Since \fBcvs\fP was designed to be incomplete, for reasons of design -simplicity, there are naturally a good -number of enhancements that can be made to make it more useful. -As well, some nuisances exist in the current implementation. -.RS -.IP \(bu 3 -\fBcvs\fP does not currently \*Qremember\*U who has a checked out a copy of a -module. -As a result, it is impossible to know who might be working on the same -module that you are. -A simple-minded database that is updated nightly would likely suffice. -.IP \(bu 3 -Signal processing, keyboard interrupt handling in particular, is currently -somewhat weak. -This is due to the heavy use of the \fBsystem\fP\|(3) library -function to execute -.SM -RCS -.LG -programs like \fBco\fP and \fBci\fP. -It sometimes takes multiple interrupts to make \fBcvs\fP quit. -This can be fixed by using a home-grown \fBsystem\fP\|() replacement. -.IP \(bu 3 -Security of the source repository is currently not dealt with directly. -The usual UNIX approach of user-group-other security permissions through -the file system is utilized, but nothing else. -\fBcvs\fP could likely be a set-group-id executable that checks a -protected database to verify user access permissions for particular objects -before allowing any operations to affect those objects. -.IP \(bu 3 -With every checked-out directory, \fBcvs\fP maintains some administrative -files that record the current revision numbers of the checked-out files as -well as the location of the respective source repository. -\fBcvs\fP does not recover nicely at all if these administrative files are -removed. -.IP \(bu 3 -The source code for \fBcvs\fP has been tested extensively on Sun-3 and -Sun-4 systems, all running SunOS 4.0 or later versions of the operating -system. -Since the code has not yet been compiled under other platforms, the overall -portability of the code is still questionable. -.IP \(bu 3 -As witnessed in the previous section, the \fBcvs\fP method for tracking -third party vendor source distributions can work quite nicely. -However, if the vendor changes the directory structure or the file names -within the source distribution, \fBcvs\fP has no way of matching the old -release with the new one. -It is currently unclear as to how to solve this, though it is certain to -happen in practice. -.RE -.NH -Availability -.PP -The \fBcvs\fP program sources can be found in a recent posting to the -\fBcomp.sources.unix\fP newsgroup. -It is also currently available via anonymous ftp from \*Qprisma.com\*U. -Copying rights for \fBcvs\fP will be covered by the GNU General Public -License. -.NH -Summary -.PP -Prisma has used \fBcvs\fP since December, 1988. -It has evolved to meet our specific needs of revision and release control. -We will make our code freely available so that others can -benefit from our work, and can enhance \fBcvs\fP to meet broader needs yet. -.PP -Many of the other software release and revision control systems, like the -one described in [Glew], appear to use a collection of tools that are -geared toward specific environments \(em one set of tools for the kernel, -one set for \*Qgeneric\*U software, one set for utilities, and one set for -kernel and utilities. -Each of these tool sets apparently handle some specific aspect of the -problem uniquely. -\fBcvs\fP took a somewhat different approach. -File sharing through symbolic or hard links is not addressed; instead, the -disk space is simply burned since it is \*Qcheap.\*U -Support for producing objects for multiple architectures is not addressed; -instead, a parallel checked-out source tree must be used for each -architecture, again wasting disk space to simplify complexity and ease of -use \(em punting on this issue allowed \fIMakefile\fPs to remain -unchanged, unlike the approach taken in [Mahler], thereby maintaining closer -compatibility with the third-party vendor sources. -\fBcvs\fP is essentially a source-file server, making no assumptions or -special handling of the sources that it controls. -To \fBcvs\fP: -.QP -A source is a source, of course, of course, unless of course the source is -Mr. Ed.\** -.FS -\fBcvs\fP, of course, does not really discriminate against Mr. Ed.\** -.FE -.FS -Yet. -.FE -.LP -Sources are maintained, saved, and retrievable at any time based on -symbolic or numeric revision or date in the past. -It is entirely up to \fBcvs\fP wrapper programs to provide for release -environments and such. -.PP -The major advantage of \fBcvs\fP over the -many other similar systems that have already been designed is the -simplicity of \fBcvs\fP. -\fBcvs\fP contains only three programs that do all the work of release -and revision control, and two manually-maintained administrative -files for each source repository. -Of course, the deciding factor of any tool is whether people use it, and if -they even \fIlike\fP to use it. -At Prisma, \fBcvs\fP prevented members of the kernel -group from killing each other. -.NH -Acknowledgements -.PP -Many thanks to Dick Grune at Vrije Universiteit in Amsterdam for his work -on the original version of \fBcvs\fP and for making it available to the -world. -Thanks to Jeff Polk of Prisma for helping with the design of the module -database, vendor branch support, and for writing the \fBcheckin\fP shell -script. -Thanks also to the entire software group at Prisma for taking the -time to review the paper and correct my grammar. -.NH -References -.IP [Bell] 12 -Bell Telephone Laboratories. -\*QSource Code Control System User's Guide.\*U -\fIUNIX System III Programmer's Manual\fP, October 1981. -.IP [Courington] 12 -Courington, W. -\fIThe Network Software Environment\fP, -Sun Technical Report FE197-0, Sun Microsystems Inc, February 1989. -.IP [Essick] 12 -Essick, Raymond B. and Robert Bruce Kolstad. -\fINotesfile Reference Manual\fP, -Department of Computer Science Technical Report #1081, -University of Illinois at Urbana-Champaign, Urbana, Illinois, -1982, p. 26. -.IP [Glew] 12 -Glew, Andy. -\*QBoxes, Links, and Parallel Trees: -Elements of a Configuration Management System.\*U -\fIWorkshop Proceedings of the Software Management Conference\fP, USENIX, -New Orleans, April 1989. -.IP [Grune] 12 -Grune, Dick. -Distributed the original shell script version of \fBcvs\fP in the -\fBcomp.sources.unix\fP volume 6 release in 1986. -.IP [Honda] 12 -Honda, Masahiro and Terrence Miller. -\*QSoftware Management Using a CASE Environment.\*U -\fIWorkshop Proceedings of the Software Management Conference\fP, USENIX, -New Orleans, April 1989. -.IP [Mahler] 12 -Mahler, Alex and Andreas Lampen. -\*QAn Integrated Toolset for Engineering Software Configurations.\*U -\fIProceedings of the ACM SIGSOFT/SIGPLAN Software Engineering Symposium on -Practical Software Development Environments\fP, ACM, Boston, November 1988. -Described is the \fBshape\fP toolkit posted to the -\fBcomp.sources.unix\fP newsgroup in the volume 19 release. -.IP [Tichy] 12 -Tichy, Walter F. -\*QDesign, Implementation, and Evaluation of a Revision Control System.\*U -\fIProceedings of the 6th International Conference on Software -Engineering\fP, IEEE, Tokyo, September 1982. -.IP [Wall] 12 -Wall, Larry. -The \fBpatch\fP program is an indispensable tool for applying a diff file -to an original. -Can be found on uunet.uu.net in ~ftp/pub/patch.tar. diff --git a/gnu/usr.bin/cvs/lib/Makefile.in b/gnu/usr.bin/cvs/lib/Makefile.in deleted file mode 100644 index a8309f2..0000000 --- a/gnu/usr.bin/cvs/lib/Makefile.in +++ /dev/null @@ -1,91 +0,0 @@ -# Makefile for library files used by GNU CVS. -# Do not use this makefile directly, but only from `../Makefile'. -# Copyright (C) 1986, 1988-1992 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -# @(#)Makefile.in 1.12 92/03/31 - -SHELL = /bin/sh - -srcdir = @srcdir@ -@VPATH@ - -SOURCES = argmatch.c \ -error.c getopt.c getopt1.c \ -sighandle.c \ -strippath.c stripslash.c yesno.c \ -getdate.y \ -hostname.c fnmatch.c ftruncate.c mkdir.c rename.c regex.c \ -strdup.c getwd.c alloca.c - -OBJECTS = argmatch.o \ -error.o getopt.o getopt1.o \ -sighandle.o \ -strippath.o stripslash.o yesno.o \ -getdate.o \ -@LIBOBJS@ - -DISTFILES = Makefile.in getopt.h \ -fnmatch.h regex.h system.h wait.h $(SOURCES) - -xxx: - @cd ..; $(MAKE) all SUBDIRS=lib - -all: libcvs.a -.PHONY: all - -install: all -.PHONY: install - -tags: $(DISTFILES) - ctags $(DISTFILES) - -TAGS: $(DISTFILES) - etags $(DISTFILES) - -ls: - @echo $(DISTFILES) -.PHONY: ls - -clean: - rm -f *.a *.o *.tab.c getdate.c -.PHONY: clean - -distclean: clean - rm -f tags TAGS Makefile -.PHONY: distclean - -realclean: distclean -.PHONY: realclean - -dist: - ln $(DISTFILES) ../`cat ../.fname`/lib -.PHONY: dist - -libcvs.a: $(OBJECTS) - $(AR) cr $@ $(OBJECTS) - -$(RANLIB) $@ - -getdate.c: getdate.y - @echo expect 8 shift/reduce conflicts - $(YACC) $(srcdir)/getdate.y - -if test -f y.tab.c ; then mv y.tab.c getdate.c ; fi - -if test -f getdate.tab.c ; then mv getdate.tab.c getdate.c ; fi - -fnmatch.o: fnmatch.h -getopt1.o: getopt.h -regex.o: regex.h -getwd.o: system.h diff --git a/gnu/usr.bin/cvs/lib/regex.c b/gnu/usr.bin/cvs/lib/regex.c deleted file mode 100644 index 8169880..0000000 --- a/gnu/usr.bin/cvs/lib/regex.c +++ /dev/null @@ -1,4948 +0,0 @@ -/* Extended regular expression matching and search library, - version 0.12. - (Implements POSIX draft P10003.2/D11.2, except for - internationalization features.) - - Copyright (C) 1993 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* AIX requires this to be the first thing in the file. */ -#if defined (_AIX) && !defined (REGEX_MALLOC) - #pragma alloca -#endif - -#define _GNU_SOURCE - -/* We need this for `regex.h', and perhaps for the Emacs include files. */ -#include <sys/types.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* The `emacs' switch turns on certain matching commands - that make sense only in Emacs. */ -#ifdef emacs - -#include "lisp.h" -#include "buffer.h" -#include "syntax.h" - -/* Emacs uses `NULL' as a predicate. */ -#undef NULL - -#else /* not emacs */ - -/* We used to test for `BSTRING' here, but only GCC and Emacs define - `BSTRING', as far as I know, and neither of them use this code. */ -#if HAVE_STRING_H || STDC_HEADERS -#include <string.h> -#ifndef bcmp -#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) -#endif -#ifndef bcopy -#define bcopy(s, d, n) memcpy ((d), (s), (n)) -#endif -#ifndef bzero -#define bzero(s, n) memset ((s), 0, (n)) -#endif -#else -#include <strings.h> -#endif - -#ifdef STDC_HEADERS -#include <stdlib.h> -#else -char *malloc (); -char *realloc (); -#endif - - -/* Define the syntax stuff for \<, \>, etc. */ - -/* This must be nonzero for the wordchar and notwordchar pattern - commands in re_match_2. */ -#ifndef Sword -#define Sword 1 -#endif - -#ifdef SYNTAX_TABLE - -extern char *re_syntax_table; - -#else /* not SYNTAX_TABLE */ - -/* How many characters in the character set. */ -#define CHAR_SET_SIZE 256 - -static char re_syntax_table[CHAR_SET_SIZE]; - -static void -init_syntax_once () -{ - register int c; - static int done = 0; - - if (done) - return; - - bzero (re_syntax_table, sizeof re_syntax_table); - - for (c = 'a'; c <= 'z'; c++) - re_syntax_table[c] = Sword; - - for (c = 'A'; c <= 'Z'; c++) - re_syntax_table[c] = Sword; - - for (c = '0'; c <= '9'; c++) - re_syntax_table[c] = Sword; - - re_syntax_table['_'] = Sword; - - done = 1; -} - -#endif /* not SYNTAX_TABLE */ - -#define SYNTAX(c) re_syntax_table[c] - -#endif /* not emacs */ - -/* Get the interface, including the syntax bits. */ -#include "regex.h" - -/* isalpha etc. are used for the character classes. */ -#include <ctype.h> - -#ifndef isascii -#define isascii(c) 1 -#endif - -#ifdef isblank -#define ISBLANK(c) (isascii (c) && isblank (c)) -#else -#define ISBLANK(c) ((c) == ' ' || (c) == '\t') -#endif -#ifdef isgraph -#define ISGRAPH(c) (isascii (c) && isgraph (c)) -#else -#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c)) -#endif - -#define ISPRINT(c) (isascii (c) && isprint (c)) -#define ISDIGIT(c) (isascii (c) && isdigit (c)) -#define ISALNUM(c) (isascii (c) && isalnum (c)) -#define ISALPHA(c) (isascii (c) && isalpha (c)) -#define ISCNTRL(c) (isascii (c) && iscntrl (c)) -#define ISLOWER(c) (isascii (c) && islower (c)) -#define ISPUNCT(c) (isascii (c) && ispunct (c)) -#define ISSPACE(c) (isascii (c) && isspace (c)) -#define ISUPPER(c) (isascii (c) && isupper (c)) -#define ISXDIGIT(c) (isascii (c) && isxdigit (c)) - -#ifndef NULL -#define NULL 0 -#endif - -/* We remove any previous definition of `SIGN_EXTEND_CHAR', - since ours (we hope) works properly with all combinations of - machines, compilers, `char' and `unsigned char' argument types. - (Per Bothner suggested the basic approach.) */ -#undef SIGN_EXTEND_CHAR -#if __STDC__ -#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) -#else /* not __STDC__ */ -/* As in Harbison and Steele. */ -#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) -#endif - -/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we - use `alloca' instead of `malloc'. This is because using malloc in - re_search* or re_match* could cause memory leaks when C-g is used in - Emacs; also, malloc is slower and causes storage fragmentation. On - the other hand, malloc is more portable, and easier to debug. - - Because we sometimes use alloca, some routines have to be macros, - not functions -- `alloca'-allocated space disappears at the end of the - function it is called in. */ - -#ifdef REGEX_MALLOC - -#define REGEX_ALLOCATE malloc -#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) - -#else /* not REGEX_MALLOC */ - -/* Emacs already defines alloca, sometimes. */ -#ifndef alloca - -/* Make alloca work the best possible way. */ -#ifdef __GNUC__ -#define alloca __builtin_alloca -#else /* not __GNUC__ */ -#if HAVE_ALLOCA_H -#include <alloca.h> -#else /* not __GNUC__ or HAVE_ALLOCA_H */ -#ifndef _AIX /* Already did AIX, up at the top. */ -char *alloca (); -#endif /* not _AIX */ -#endif /* not HAVE_ALLOCA_H */ -#endif /* not __GNUC__ */ - -#endif /* not alloca */ - -#define REGEX_ALLOCATE alloca - -/* Assumes a `char *destination' variable. */ -#define REGEX_REALLOCATE(source, osize, nsize) \ - (destination = (char *) alloca (nsize), \ - bcopy (source, destination, osize), \ - destination) - -#endif /* not REGEX_MALLOC */ - - -/* True if `size1' is non-NULL and PTR is pointing anywhere inside - `string1' or just past its end. This works if PTR is NULL, which is - a good thing. */ -#define FIRST_STRING_P(ptr) \ - (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) - -/* (Re)Allocate N items of type T using malloc, or fail. */ -#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) -#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) -#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) - -#define BYTEWIDTH 8 /* In bits. */ - -#define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) - -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -typedef char boolean; -#define false 0 -#define true 1 - -/* These are the command codes that appear in compiled regular - expressions. Some opcodes are followed by argument bytes. A - command code can specify any interpretation whatsoever for its - arguments. Zero bytes may appear in the compiled regular expression. - - The value of `exactn' is needed in search.c (search_buffer) in Emacs. - So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of - `exactn' we use here must also be 1. */ - -typedef enum -{ - no_op = 0, - - /* Followed by one byte giving n, then by n literal bytes. */ - exactn = 1, - - /* Matches any (more or less) character. */ - anychar, - - /* Matches any one char belonging to specified set. First - following byte is number of bitmap bytes. Then come bytes - for a bitmap saying which chars are in. Bits in each byte - are ordered low-bit-first. A character is in the set if its - bit is 1. A character too large to have a bit in the map is - automatically not in the set. */ - charset, - - /* Same parameters as charset, but match any character that is - not one of those specified. */ - charset_not, - - /* Start remembering the text that is matched, for storing in a - register. Followed by one byte with the register number, in - the range 0 to one less than the pattern buffer's re_nsub - field. Then followed by one byte with the number of groups - inner to this one. (This last has to be part of the - start_memory only because we need it in the on_failure_jump - of re_match_2.) */ - start_memory, - - /* Stop remembering the text that is matched and store it in a - memory register. Followed by one byte with the register - number, in the range 0 to one less than `re_nsub' in the - pattern buffer, and one byte with the number of inner groups, - just like `start_memory'. (We need the number of inner - groups here because we don't have any easy way of finding the - corresponding start_memory when we're at a stop_memory.) */ - stop_memory, - - /* Match a duplicate of something remembered. Followed by one - byte containing the register number. */ - duplicate, - - /* Fail unless at beginning of line. */ - begline, - - /* Fail unless at end of line. */ - endline, - - /* Succeeds if at beginning of buffer (if emacs) or at beginning - of string to be matched (if not). */ - begbuf, - - /* Analogously, for end of buffer/string. */ - endbuf, - - /* Followed by two byte relative address to which to jump. */ - jump, - - /* Same as jump, but marks the end of an alternative. */ - jump_past_alt, - - /* Followed by two-byte relative address of place to resume at - in case of failure. */ - on_failure_jump, - - /* Like on_failure_jump, but pushes a placeholder instead of the - current string position when executed. */ - on_failure_keep_string_jump, - - /* Throw away latest failure point and then jump to following - two-byte relative address. */ - pop_failure_jump, - - /* Change to pop_failure_jump if know won't have to backtrack to - match; otherwise change to jump. This is used to jump - back to the beginning of a repeat. If what follows this jump - clearly won't match what the repeat does, such that we can be - sure that there is no use backtracking out of repetitions - already matched, then we change it to a pop_failure_jump. - Followed by two-byte address. */ - maybe_pop_jump, - - /* Jump to following two-byte address, and push a dummy failure - point. This failure point will be thrown away if an attempt - is made to use it for a failure. A `+' construct makes this - before the first repeat. Also used as an intermediary kind - of jump when compiling an alternative. */ - dummy_failure_jump, - - /* Push a dummy failure point and continue. Used at the end of - alternatives. */ - push_dummy_failure, - - /* Followed by two-byte relative address and two-byte number n. - After matching N times, jump to the address upon failure. */ - succeed_n, - - /* Followed by two-byte relative address, and two-byte number n. - Jump to the address N times, then fail. */ - jump_n, - - /* Set the following two-byte relative address to the - subsequent two-byte number. The address *includes* the two - bytes of number. */ - set_number_at, - - wordchar, /* Matches any word-constituent character. */ - notwordchar, /* Matches any char that is not a word-constituent. */ - - wordbeg, /* Succeeds if at word beginning. */ - wordend, /* Succeeds if at word end. */ - - wordbound, /* Succeeds if at a word boundary. */ - notwordbound /* Succeeds if not at a word boundary. */ - -#ifdef emacs - ,before_dot, /* Succeeds if before point. */ - at_dot, /* Succeeds if at point. */ - after_dot, /* Succeeds if after point. */ - - /* Matches any character whose syntax is specified. Followed by - a byte which contains a syntax code, e.g., Sword. */ - syntaxspec, - - /* Matches any character whose syntax is not that specified. */ - notsyntaxspec -#endif /* emacs */ -} re_opcode_t; - -/* Common operations on the compiled pattern. */ - -/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ - -#define STORE_NUMBER(destination, number) \ - do { \ - (destination)[0] = (number) & 0377; \ - (destination)[1] = (number) >> 8; \ - } while (0) - -/* Same as STORE_NUMBER, except increment DESTINATION to - the byte after where the number is stored. Therefore, DESTINATION - must be an lvalue. */ - -#define STORE_NUMBER_AND_INCR(destination, number) \ - do { \ - STORE_NUMBER (destination, number); \ - (destination) += 2; \ - } while (0) - -/* Put into DESTINATION a number stored in two contiguous bytes starting - at SOURCE. */ - -#define EXTRACT_NUMBER(destination, source) \ - do { \ - (destination) = *(source) & 0377; \ - (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ - } while (0) - -#ifdef DEBUG -static void -extract_number (dest, source) - int *dest; - unsigned char *source; -{ - int temp = SIGN_EXTEND_CHAR (*(source + 1)); - *dest = *source & 0377; - *dest += temp << 8; -} - -#ifndef EXTRACT_MACROS /* To debug the macros. */ -#undef EXTRACT_NUMBER -#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) -#endif /* not EXTRACT_MACROS */ - -#endif /* DEBUG */ - -/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. - SOURCE must be an lvalue. */ - -#define EXTRACT_NUMBER_AND_INCR(destination, source) \ - do { \ - EXTRACT_NUMBER (destination, source); \ - (source) += 2; \ - } while (0) - -#ifdef DEBUG -static void -extract_number_and_incr (destination, source) - int *destination; - unsigned char **source; -{ - extract_number (destination, *source); - *source += 2; -} - -#ifndef EXTRACT_MACROS -#undef EXTRACT_NUMBER_AND_INCR -#define EXTRACT_NUMBER_AND_INCR(dest, src) \ - extract_number_and_incr (&dest, &src) -#endif /* not EXTRACT_MACROS */ - -#endif /* DEBUG */ - -/* If DEBUG is defined, Regex prints many voluminous messages about what - it is doing (if the variable `debug' is nonzero). If linked with the - main program in `iregex.c', you can enter patterns and strings - interactively. And if linked with the main program in `main.c' and - the other test files, you can run the already-written tests. */ - -#ifdef DEBUG - -/* We use standard I/O for debugging. */ -#include <stdio.h> - -/* It is useful to test things that ``must'' be true when debugging. */ -#include <assert.h> - -static int debug = 0; - -#define DEBUG_STATEMENT(e) e -#define DEBUG_PRINT1(x) if (debug) printf (x) -#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) -#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) -#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) -#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ - if (debug) print_partial_compiled_pattern (s, e) -#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ - if (debug) print_double_string (w, s1, sz1, s2, sz2) - - -extern void printchar (); - -/* Print the fastmap in human-readable form. */ - -void -print_fastmap (fastmap) - char *fastmap; -{ - unsigned was_a_range = 0; - unsigned i = 0; - - while (i < (1 << BYTEWIDTH)) - { - if (fastmap[i++]) - { - was_a_range = 0; - printchar (i - 1); - while (i < (1 << BYTEWIDTH) && fastmap[i]) - { - was_a_range = 1; - i++; - } - if (was_a_range) - { - printf ("-"); - printchar (i - 1); - } - } - } - putchar ('\n'); -} - - -/* Print a compiled pattern string in human-readable form, starting at - the START pointer into it and ending just before the pointer END. */ - -void -print_partial_compiled_pattern (start, end) - unsigned char *start; - unsigned char *end; -{ - int mcnt, mcnt2; - unsigned char *p = start; - unsigned char *pend = end; - - if (start == NULL) - { - printf ("(null)\n"); - return; - } - - /* Loop over pattern commands. */ - while (p < pend) - { - switch ((re_opcode_t) *p++) - { - case no_op: - printf ("/no_op"); - break; - - case exactn: - mcnt = *p++; - printf ("/exactn/%d", mcnt); - do - { - putchar ('/'); - printchar (*p++); - } - while (--mcnt); - break; - - case start_memory: - mcnt = *p++; - printf ("/start_memory/%d/%d", mcnt, *p++); - break; - - case stop_memory: - mcnt = *p++; - printf ("/stop_memory/%d/%d", mcnt, *p++); - break; - - case duplicate: - printf ("/duplicate/%d", *p++); - break; - - case anychar: - printf ("/anychar"); - break; - - case charset: - case charset_not: - { - register int c; - - printf ("/charset%s", - (re_opcode_t) *(p - 1) == charset_not ? "_not" : ""); - - assert (p + *p < pend); - - for (c = 0; c < *p; c++) - { - unsigned bit; - unsigned char map_byte = p[1 + c]; - - putchar ('/'); - - for (bit = 0; bit < BYTEWIDTH; bit++) - if (map_byte & (1 << bit)) - printchar (c * BYTEWIDTH + bit); - } - p += 1 + *p; - break; - } - - case begline: - printf ("/begline"); - break; - - case endline: - printf ("/endline"); - break; - - case on_failure_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/on_failure_jump/0/%d", mcnt); - break; - - case on_failure_keep_string_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/on_failure_keep_string_jump/0/%d", mcnt); - break; - - case dummy_failure_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/dummy_failure_jump/0/%d", mcnt); - break; - - case push_dummy_failure: - printf ("/push_dummy_failure"); - break; - - case maybe_pop_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/maybe_pop_jump/0/%d", mcnt); - break; - - case pop_failure_jump: - extract_number_and_incr (&mcnt, &p); - printf ("/pop_failure_jump/0/%d", mcnt); - break; - - case jump_past_alt: - extract_number_and_incr (&mcnt, &p); - printf ("/jump_past_alt/0/%d", mcnt); - break; - - case jump: - extract_number_and_incr (&mcnt, &p); - printf ("/jump/0/%d", mcnt); - break; - - case succeed_n: - extract_number_and_incr (&mcnt, &p); - extract_number_and_incr (&mcnt2, &p); - printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2); - break; - - case jump_n: - extract_number_and_incr (&mcnt, &p); - extract_number_and_incr (&mcnt2, &p); - printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2); - break; - - case set_number_at: - extract_number_and_incr (&mcnt, &p); - extract_number_and_incr (&mcnt2, &p); - printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2); - break; - - case wordbound: - printf ("/wordbound"); - break; - - case notwordbound: - printf ("/notwordbound"); - break; - - case wordbeg: - printf ("/wordbeg"); - break; - - case wordend: - printf ("/wordend"); - -#ifdef emacs - case before_dot: - printf ("/before_dot"); - break; - - case at_dot: - printf ("/at_dot"); - break; - - case after_dot: - printf ("/after_dot"); - break; - - case syntaxspec: - printf ("/syntaxspec"); - mcnt = *p++; - printf ("/%d", mcnt); - break; - - case notsyntaxspec: - printf ("/notsyntaxspec"); - mcnt = *p++; - printf ("/%d", mcnt); - break; -#endif /* emacs */ - - case wordchar: - printf ("/wordchar"); - break; - - case notwordchar: - printf ("/notwordchar"); - break; - - case begbuf: - printf ("/begbuf"); - break; - - case endbuf: - printf ("/endbuf"); - break; - - default: - printf ("?%d", *(p-1)); - } - } - printf ("/\n"); -} - - -void -print_compiled_pattern (bufp) - struct re_pattern_buffer *bufp; -{ - unsigned char *buffer = bufp->buffer; - - print_partial_compiled_pattern (buffer, buffer + bufp->used); - printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated); - - if (bufp->fastmap_accurate && bufp->fastmap) - { - printf ("fastmap: "); - print_fastmap (bufp->fastmap); - } - - printf ("re_nsub: %d\t", bufp->re_nsub); - printf ("regs_alloc: %d\t", bufp->regs_allocated); - printf ("can_be_null: %d\t", bufp->can_be_null); - printf ("newline_anchor: %d\n", bufp->newline_anchor); - printf ("no_sub: %d\t", bufp->no_sub); - printf ("not_bol: %d\t", bufp->not_bol); - printf ("not_eol: %d\t", bufp->not_eol); - printf ("syntax: %d\n", bufp->syntax); - /* Perhaps we should print the translate table? */ -} - - -void -print_double_string (where, string1, size1, string2, size2) - const char *where; - const char *string1; - const char *string2; - int size1; - int size2; -{ - unsigned this_char; - - if (where == NULL) - printf ("(null)"); - else - { - if (FIRST_STRING_P (where)) - { - for (this_char = where - string1; this_char < size1; this_char++) - printchar (string1[this_char]); - - where = string2; - } - - for (this_char = where - string2; this_char < size2; this_char++) - printchar (string2[this_char]); - } -} - -#else /* not DEBUG */ - -#undef assert -#define assert(e) - -#define DEBUG_STATEMENT(e) -#define DEBUG_PRINT1(x) -#define DEBUG_PRINT2(x1, x2) -#define DEBUG_PRINT3(x1, x2, x3) -#define DEBUG_PRINT4(x1, x2, x3, x4) -#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) -#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) - -#endif /* not DEBUG */ - -/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can - also be assigned to arbitrarily: each pattern buffer stores its own - syntax, so it can be changed between regex compilations. */ -reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; - - -/* Specify the precise syntax of regexps for compilation. This provides - for compatibility for various utilities which historically have - different, incompatible syntaxes. - - The argument SYNTAX is a bit mask comprised of the various bits - defined in regex.h. We return the old syntax. */ - -reg_syntax_t -re_set_syntax (syntax) - reg_syntax_t syntax; -{ - reg_syntax_t ret = re_syntax_options; - - re_syntax_options = syntax; - return ret; -} - -/* This table gives an error message for each of the error codes listed - in regex.h. Obviously the order here has to be same as there. */ - -static const char *re_error_msg[] = - { NULL, /* REG_NOERROR */ - "No match", /* REG_NOMATCH */ - "Invalid regular expression", /* REG_BADPAT */ - "Invalid collation character", /* REG_ECOLLATE */ - "Invalid character class name", /* REG_ECTYPE */ - "Trailing backslash", /* REG_EESCAPE */ - "Invalid back reference", /* REG_ESUBREG */ - "Unmatched [ or [^", /* REG_EBRACK */ - "Unmatched ( or \\(", /* REG_EPAREN */ - "Unmatched \\{", /* REG_EBRACE */ - "Invalid content of \\{\\}", /* REG_BADBR */ - "Invalid range end", /* REG_ERANGE */ - "Memory exhausted", /* REG_ESPACE */ - "Invalid preceding regular expression", /* REG_BADRPT */ - "Premature end of regular expression", /* REG_EEND */ - "Regular expression too big", /* REG_ESIZE */ - "Unmatched ) or \\)", /* REG_ERPAREN */ - }; - -/* Subroutine declarations and macros for regex_compile. */ - -static void store_op1 (), store_op2 (); -static void insert_op1 (), insert_op2 (); -static boolean at_begline_loc_p (), at_endline_loc_p (); -static boolean group_in_compile_stack (); -static reg_errcode_t compile_range (); - -/* Fetch the next character in the uncompiled pattern---translating it - if necessary. Also cast from a signed character in the constant - string passed to us by the user to an unsigned char that we can use - as an array index (in, e.g., `translate'). */ -#define PATFETCH(c) \ - do {if (p == pend) return REG_EEND; \ - c = (unsigned char) *p++; \ - if (translate) c = translate[c]; \ - } while (0) - -/* Fetch the next character in the uncompiled pattern, with no - translation. */ -#define PATFETCH_RAW(c) \ - do {if (p == pend) return REG_EEND; \ - c = (unsigned char) *p++; \ - } while (0) - -/* Go backwards one character in the pattern. */ -#define PATUNFETCH p-- - - -/* If `translate' is non-null, return translate[D], else just D. We - cast the subscript to translate because some data is declared as - `char *', to avoid warnings when a string constant is passed. But - when we use a character as a subscript we must make it unsigned. */ -#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) - - -/* Macros for outputting the compiled pattern into `buffer'. */ - -/* If the buffer isn't allocated when it comes in, use this. */ -#define INIT_BUF_SIZE 32 - -/* Make sure we have at least N more bytes of space in buffer. */ -#define GET_BUFFER_SPACE(n) \ - while (b - bufp->buffer + (n) > bufp->allocated) \ - EXTEND_BUFFER () - -/* Make sure we have one more byte of buffer space and then add C to it. */ -#define BUF_PUSH(c) \ - do { \ - GET_BUFFER_SPACE (1); \ - *b++ = (unsigned char) (c); \ - } while (0) - - -/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ -#define BUF_PUSH_2(c1, c2) \ - do { \ - GET_BUFFER_SPACE (2); \ - *b++ = (unsigned char) (c1); \ - *b++ = (unsigned char) (c2); \ - } while (0) - - -/* As with BUF_PUSH_2, except for three bytes. */ -#define BUF_PUSH_3(c1, c2, c3) \ - do { \ - GET_BUFFER_SPACE (3); \ - *b++ = (unsigned char) (c1); \ - *b++ = (unsigned char) (c2); \ - *b++ = (unsigned char) (c3); \ - } while (0) - - -/* Store a jump with opcode OP at LOC to location TO. We store a - relative address offset by the three bytes the jump itself occupies. */ -#define STORE_JUMP(op, loc, to) \ - store_op1 (op, loc, (to) - (loc) - 3) - -/* Likewise, for a two-argument jump. */ -#define STORE_JUMP2(op, loc, to, arg) \ - store_op2 (op, loc, (to) - (loc) - 3, arg) - -/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ -#define INSERT_JUMP(op, loc, to) \ - insert_op1 (op, loc, (to) - (loc) - 3, b) - -/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ -#define INSERT_JUMP2(op, loc, to, arg) \ - insert_op2 (op, loc, (to) - (loc) - 3, arg, b) - - -/* This is not an arbitrary limit: the arguments which represent offsets - into the pattern are two bytes long. So if 2^16 bytes turns out to - be too small, many things would have to change. */ -#define MAX_BUF_SIZE (1L << 16) - - -/* Extend the buffer by twice its current size via realloc and - reset the pointers that pointed into the old block to point to the - correct places in the new one. If extending the buffer results in it - being larger than MAX_BUF_SIZE, then flag memory exhausted. */ -#define EXTEND_BUFFER() \ - do { \ - unsigned char *old_buffer = bufp->buffer; \ - if (bufp->allocated == MAX_BUF_SIZE) \ - return REG_ESIZE; \ - bufp->allocated <<= 1; \ - if (bufp->allocated > MAX_BUF_SIZE) \ - bufp->allocated = MAX_BUF_SIZE; \ - bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ - if (bufp->buffer == NULL) \ - return REG_ESPACE; \ - /* If the buffer moved, move all the pointers into it. */ \ - if (old_buffer != bufp->buffer) \ - { \ - b = (b - old_buffer) + bufp->buffer; \ - begalt = (begalt - old_buffer) + bufp->buffer; \ - if (fixup_alt_jump) \ - fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ - if (laststart) \ - laststart = (laststart - old_buffer) + bufp->buffer; \ - if (pending_exact) \ - pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ - } \ - } while (0) - - -/* Since we have one byte reserved for the register number argument to - {start,stop}_memory, the maximum number of groups we can report - things about is what fits in that byte. */ -#define MAX_REGNUM 255 - -/* But patterns can have more than `MAX_REGNUM' registers. We just - ignore the excess. */ -typedef unsigned regnum_t; - - -/* Macros for the compile stack. */ - -/* Since offsets can go either forwards or backwards, this type needs to - be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ -typedef int pattern_offset_t; - -typedef struct -{ - pattern_offset_t begalt_offset; - pattern_offset_t fixup_alt_jump; - pattern_offset_t inner_group_offset; - pattern_offset_t laststart_offset; - regnum_t regnum; -} compile_stack_elt_t; - - -typedef struct -{ - compile_stack_elt_t *stack; - unsigned size; - unsigned avail; /* Offset of next open position. */ -} compile_stack_type; - - -#define INIT_COMPILE_STACK_SIZE 32 - -#define COMPILE_STACK_EMPTY (compile_stack.avail == 0) -#define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) - -/* The next available element. */ -#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) - - -/* Set the bit for character C in a list. */ -#define SET_LIST_BIT(c) \ - (b[((unsigned char) (c)) / BYTEWIDTH] \ - |= 1 << (((unsigned char) c) % BYTEWIDTH)) - - -/* Get the next unsigned number in the uncompiled pattern. */ -#define GET_UNSIGNED_NUMBER(num) \ - { if (p != pend) \ - { \ - PATFETCH (c); \ - while (ISDIGIT (c)) \ - { \ - if (num < 0) \ - num = 0; \ - num = num * 10 + c - '0'; \ - if (p == pend) \ - break; \ - PATFETCH (c); \ - } \ - } \ - } - -#define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ - -#define IS_CHAR_CLASS(string) \ - (STREQ (string, "alpha") || STREQ (string, "upper") \ - || STREQ (string, "lower") || STREQ (string, "digit") \ - || STREQ (string, "alnum") || STREQ (string, "xdigit") \ - || STREQ (string, "space") || STREQ (string, "print") \ - || STREQ (string, "punct") || STREQ (string, "graph") \ - || STREQ (string, "cntrl") || STREQ (string, "blank")) - -/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. - Returns one of error codes defined in `regex.h', or zero for success. - - Assumes the `allocated' (and perhaps `buffer') and `translate' - fields are set in BUFP on entry. - - If it succeeds, results are put in BUFP (if it returns an error, the - contents of BUFP are undefined): - `buffer' is the compiled pattern; - `syntax' is set to SYNTAX; - `used' is set to the length of the compiled pattern; - `fastmap_accurate' is zero; - `re_nsub' is the number of subexpressions in PATTERN; - `not_bol' and `not_eol' are zero; - - The `fastmap' and `newline_anchor' fields are neither - examined nor set. */ - -static reg_errcode_t -regex_compile (pattern, size, syntax, bufp) - const char *pattern; - int size; - reg_syntax_t syntax; - struct re_pattern_buffer *bufp; -{ - /* We fetch characters from PATTERN here. Even though PATTERN is - `char *' (i.e., signed), we declare these variables as unsigned, so - they can be reliably used as array indices. */ - register unsigned char c, c1; - - /* A random tempory spot in PATTERN. */ - const char *p1; - - /* Points to the end of the buffer, where we should append. */ - register unsigned char *b; - - /* Keeps track of unclosed groups. */ - compile_stack_type compile_stack; - - /* Points to the current (ending) position in the pattern. */ - const char *p = pattern; - const char *pend = pattern + size; - - /* How to translate the characters in the pattern. */ - char *translate = bufp->translate; - - /* Address of the count-byte of the most recently inserted `exactn' - command. This makes it possible to tell if a new exact-match - character can be added to that command or if the character requires - a new `exactn' command. */ - unsigned char *pending_exact = 0; - - /* Address of start of the most recently finished expression. - This tells, e.g., postfix * where to find the start of its - operand. Reset at the beginning of groups and alternatives. */ - unsigned char *laststart = 0; - - /* Address of beginning of regexp, or inside of last group. */ - unsigned char *begalt; - - /* Place in the uncompiled pattern (i.e., the {) to - which to go back if the interval is invalid. */ - const char *beg_interval; - - /* Address of the place where a forward jump should go to the end of - the containing expression. Each alternative of an `or' -- except the - last -- ends with a forward jump of this sort. */ - unsigned char *fixup_alt_jump = 0; - - /* Counts open-groups as they are encountered. Remembered for the - matching close-group on the compile stack, so the same register - number is put in the stop_memory as the start_memory. */ - regnum_t regnum = 0; - -#ifdef DEBUG - DEBUG_PRINT1 ("\nCompiling pattern: "); - if (debug) - { - unsigned debug_count; - - for (debug_count = 0; debug_count < size; debug_count++) - printchar (pattern[debug_count]); - putchar ('\n'); - } -#endif /* DEBUG */ - - /* Initialize the compile stack. */ - compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); - if (compile_stack.stack == NULL) - return REG_ESPACE; - - compile_stack.size = INIT_COMPILE_STACK_SIZE; - compile_stack.avail = 0; - - /* Initialize the pattern buffer. */ - bufp->syntax = syntax; - bufp->fastmap_accurate = 0; - bufp->not_bol = bufp->not_eol = 0; - - /* Set `used' to zero, so that if we return an error, the pattern - printer (for debugging) will think there's no pattern. We reset it - at the end. */ - bufp->used = 0; - - /* Always count groups, whether or not bufp->no_sub is set. */ - bufp->re_nsub = 0; - -#if !defined (emacs) && !defined (SYNTAX_TABLE) - /* Initialize the syntax table. */ - init_syntax_once (); -#endif - - if (bufp->allocated == 0) - { - if (bufp->buffer) - { /* If zero allocated, but buffer is non-null, try to realloc - enough space. This loses if buffer's address is bogus, but - that is the user's responsibility. */ - RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); - } - else - { /* Caller did not allocate a buffer. Do it for them. */ - bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); - } - if (!bufp->buffer) return REG_ESPACE; - - bufp->allocated = INIT_BUF_SIZE; - } - - begalt = b = bufp->buffer; - - /* Loop through the uncompiled pattern until we're at the end. */ - while (p != pend) - { - PATFETCH (c); - - switch (c) - { - case '^': - { - if ( /* If at start of pattern, it's an operator. */ - p == pattern + 1 - /* If context independent, it's an operator. */ - || syntax & RE_CONTEXT_INDEP_ANCHORS - /* Otherwise, depends on what's come before. */ - || at_begline_loc_p (pattern, p, syntax)) - BUF_PUSH (begline); - else - goto normal_char; - } - break; - - - case '$': - { - if ( /* If at end of pattern, it's an operator. */ - p == pend - /* If context independent, it's an operator. */ - || syntax & RE_CONTEXT_INDEP_ANCHORS - /* Otherwise, depends on what's next. */ - || at_endline_loc_p (p, pend, syntax)) - BUF_PUSH (endline); - else - goto normal_char; - } - break; - - - case '+': - case '?': - if ((syntax & RE_BK_PLUS_QM) - || (syntax & RE_LIMITED_OPS)) - goto normal_char; - handle_plus: - case '*': - /* If there is no previous pattern... */ - if (!laststart) - { - if (syntax & RE_CONTEXT_INVALID_OPS) - return REG_BADRPT; - else if (!(syntax & RE_CONTEXT_INDEP_OPS)) - goto normal_char; - } - - { - /* Are we optimizing this jump? */ - boolean keep_string_p = false; - - /* 1 means zero (many) matches is allowed. */ - char zero_times_ok = 0, many_times_ok = 0; - - /* If there is a sequence of repetition chars, collapse it - down to just one (the right one). We can't combine - interval operators with these because of, e.g., `a{2}*', - which should only match an even number of `a's. */ - - for (;;) - { - zero_times_ok |= c != '+'; - many_times_ok |= c != '?'; - - if (p == pend) - break; - - PATFETCH (c); - - if (c == '*' - || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) - ; - - else if (syntax & RE_BK_PLUS_QM && c == '\\') - { - if (p == pend) return REG_EESCAPE; - - PATFETCH (c1); - if (!(c1 == '+' || c1 == '?')) - { - PATUNFETCH; - PATUNFETCH; - break; - } - - c = c1; - } - else - { - PATUNFETCH; - break; - } - - /* If we get here, we found another repeat character. */ - } - - /* Star, etc. applied to an empty pattern is equivalent - to an empty pattern. */ - if (!laststart) - break; - - /* Now we know whether or not zero matches is allowed - and also whether or not two or more matches is allowed. */ - if (many_times_ok) - { /* More than one repetition is allowed, so put in at the - end a backward relative jump from `b' to before the next - jump we're going to put in below (which jumps from - laststart to after this jump). - - But if we are at the `*' in the exact sequence `.*\n', - insert an unconditional jump backwards to the ., - instead of the beginning of the loop. This way we only - push a failure point once, instead of every time - through the loop. */ - assert (p - 1 > pattern); - - /* Allocate the space for the jump. */ - GET_BUFFER_SPACE (3); - - /* We know we are not at the first character of the pattern, - because laststart was nonzero. And we've already - incremented `p', by the way, to be the character after - the `*'. Do we have to do something analogous here - for null bytes, because of RE_DOT_NOT_NULL? */ - if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') - && zero_times_ok - && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') - && !(syntax & RE_DOT_NEWLINE)) - { /* We have .*\n. */ - STORE_JUMP (jump, b, laststart); - keep_string_p = true; - } - else - /* Anything else. */ - STORE_JUMP (maybe_pop_jump, b, laststart - 3); - - /* We've added more stuff to the buffer. */ - b += 3; - } - - /* On failure, jump from laststart to b + 3, which will be the - end of the buffer after this jump is inserted. */ - GET_BUFFER_SPACE (3); - INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump - : on_failure_jump, - laststart, b + 3); - pending_exact = 0; - b += 3; - - if (!zero_times_ok) - { - /* At least one repetition is required, so insert a - `dummy_failure_jump' before the initial - `on_failure_jump' instruction of the loop. This - effects a skip over that instruction the first time - we hit that loop. */ - GET_BUFFER_SPACE (3); - INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); - b += 3; - } - } - break; - - - case '.': - laststart = b; - BUF_PUSH (anychar); - break; - - - case '[': - { - boolean had_char_class = false; - - if (p == pend) return REG_EBRACK; - - /* Ensure that we have enough space to push a charset: the - opcode, the length count, and the bitset; 34 bytes in all. */ - GET_BUFFER_SPACE (34); - - laststart = b; - - /* We test `*p == '^' twice, instead of using an if - statement, so we only need one BUF_PUSH. */ - BUF_PUSH (*p == '^' ? charset_not : charset); - if (*p == '^') - p++; - - /* Remember the first position in the bracket expression. */ - p1 = p; - - /* Push the number of bytes in the bitmap. */ - BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); - - /* Clear the whole map. */ - bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); - - /* charset_not matches newline according to a syntax bit. */ - if ((re_opcode_t) b[-2] == charset_not - && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) - SET_LIST_BIT ('\n'); - - /* Read in characters and ranges, setting map bits. */ - for (;;) - { - if (p == pend) return REG_EBRACK; - - PATFETCH (c); - - /* \ might escape characters inside [...] and [^...]. */ - if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') - { - if (p == pend) return REG_EESCAPE; - - PATFETCH (c1); - SET_LIST_BIT (c1); - continue; - } - - /* Could be the end of the bracket expression. If it's - not (i.e., when the bracket expression is `[]' so - far), the ']' character bit gets set way below. */ - if (c == ']' && p != p1 + 1) - break; - - /* Look ahead to see if it's a range when the last thing - was a character class. */ - if (had_char_class && c == '-' && *p != ']') - return REG_ERANGE; - - /* Look ahead to see if it's a range when the last thing - was a character: if this is a hyphen not at the - beginning or the end of a list, then it's the range - operator. */ - if (c == '-' - && !(p - 2 >= pattern && p[-2] == '[') - && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') - && *p != ']') - { - reg_errcode_t ret - = compile_range (&p, pend, translate, syntax, b); - if (ret != REG_NOERROR) return ret; - } - - else if (p[0] == '-' && p[1] != ']') - { /* This handles ranges made up of characters only. */ - reg_errcode_t ret; - - /* Move past the `-'. */ - PATFETCH (c1); - - ret = compile_range (&p, pend, translate, syntax, b); - if (ret != REG_NOERROR) return ret; - } - - /* See if we're at the beginning of a possible character - class. */ - - else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') - { /* Leave room for the null. */ - char str[CHAR_CLASS_MAX_LENGTH + 1]; - - PATFETCH (c); - c1 = 0; - - /* If pattern is `[[:'. */ - if (p == pend) return REG_EBRACK; - - for (;;) - { - PATFETCH (c); - if (c == ':' || c == ']' || p == pend - || c1 == CHAR_CLASS_MAX_LENGTH) - break; - str[c1++] = c; - } - str[c1] = '\0'; - - /* If isn't a word bracketed by `[:' and:`]': - undo the ending character, the letters, and leave - the leading `:' and `[' (but set bits for them). */ - if (c == ':' && *p == ']') - { - int ch; - boolean is_alnum = STREQ (str, "alnum"); - boolean is_alpha = STREQ (str, "alpha"); - boolean is_blank = STREQ (str, "blank"); - boolean is_cntrl = STREQ (str, "cntrl"); - boolean is_digit = STREQ (str, "digit"); - boolean is_graph = STREQ (str, "graph"); - boolean is_lower = STREQ (str, "lower"); - boolean is_print = STREQ (str, "print"); - boolean is_punct = STREQ (str, "punct"); - boolean is_space = STREQ (str, "space"); - boolean is_upper = STREQ (str, "upper"); - boolean is_xdigit = STREQ (str, "xdigit"); - - if (!IS_CHAR_CLASS (str)) return REG_ECTYPE; - - /* Throw away the ] at the end of the character - class. */ - PATFETCH (c); - - if (p == pend) return REG_EBRACK; - - for (ch = 0; ch < 1 << BYTEWIDTH; ch++) - { - if ( (is_alnum && ISALNUM (ch)) - || (is_alpha && ISALPHA (ch)) - || (is_blank && ISBLANK (ch)) - || (is_cntrl && ISCNTRL (ch)) - || (is_digit && ISDIGIT (ch)) - || (is_graph && ISGRAPH (ch)) - || (is_lower && ISLOWER (ch)) - || (is_print && ISPRINT (ch)) - || (is_punct && ISPUNCT (ch)) - || (is_space && ISSPACE (ch)) - || (is_upper && ISUPPER (ch)) - || (is_xdigit && ISXDIGIT (ch))) - SET_LIST_BIT (ch); - } - had_char_class = true; - } - else - { - c1++; - while (c1--) - PATUNFETCH; - SET_LIST_BIT ('['); - SET_LIST_BIT (':'); - had_char_class = false; - } - } - else - { - had_char_class = false; - SET_LIST_BIT (c); - } - } - - /* Discard any (non)matching list bytes that are all 0 at the - end of the map. Decrease the map-length byte too. */ - while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) - b[-1]--; - b += b[-1]; - } - break; - - - case '(': - if (syntax & RE_NO_BK_PARENS) - goto handle_open; - else - goto normal_char; - - - case ')': - if (syntax & RE_NO_BK_PARENS) - goto handle_close; - else - goto normal_char; - - - case '\n': - if (syntax & RE_NEWLINE_ALT) - goto handle_alt; - else - goto normal_char; - - - case '|': - if (syntax & RE_NO_BK_VBAR) - goto handle_alt; - else - goto normal_char; - - - case '{': - if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) - goto handle_interval; - else - goto normal_char; - - - case '\\': - if (p == pend) return REG_EESCAPE; - - /* Do not translate the character after the \, so that we can - distinguish, e.g., \B from \b, even if we normally would - translate, e.g., B to b. */ - PATFETCH_RAW (c); - - switch (c) - { - case '(': - if (syntax & RE_NO_BK_PARENS) - goto normal_backslash; - - handle_open: - bufp->re_nsub++; - regnum++; - - if (COMPILE_STACK_FULL) - { - RETALLOC (compile_stack.stack, compile_stack.size << 1, - compile_stack_elt_t); - if (compile_stack.stack == NULL) return REG_ESPACE; - - compile_stack.size <<= 1; - } - - /* These are the values to restore when we hit end of this - group. They are all relative offsets, so that if the - whole pattern moves because of realloc, they will still - be valid. */ - COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; - COMPILE_STACK_TOP.fixup_alt_jump - = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; - COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; - COMPILE_STACK_TOP.regnum = regnum; - - /* We will eventually replace the 0 with the number of - groups inner to this one. But do not push a - start_memory for groups beyond the last one we can - represent in the compiled pattern. */ - if (regnum <= MAX_REGNUM) - { - COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; - BUF_PUSH_3 (start_memory, regnum, 0); - } - - compile_stack.avail++; - - fixup_alt_jump = 0; - laststart = 0; - begalt = b; - /* If we've reached MAX_REGNUM groups, then this open - won't actually generate any code, so we'll have to - clear pending_exact explicitly. */ - pending_exact = 0; - break; - - - case ')': - if (syntax & RE_NO_BK_PARENS) goto normal_backslash; - - if (COMPILE_STACK_EMPTY) - if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) - goto normal_backslash; - else - return REG_ERPAREN; - - handle_close: - if (fixup_alt_jump) - { /* Push a dummy failure point at the end of the - alternative for a possible future - `pop_failure_jump' to pop. See comments at - `push_dummy_failure' in `re_match_2'. */ - BUF_PUSH (push_dummy_failure); - - /* We allocated space for this jump when we assigned - to `fixup_alt_jump', in the `handle_alt' case below. */ - STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); - } - - /* See similar code for backslashed left paren above. */ - if (COMPILE_STACK_EMPTY) - if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) - goto normal_char; - else - return REG_ERPAREN; - - /* Since we just checked for an empty stack above, this - ``can't happen''. */ - assert (compile_stack.avail != 0); - { - /* We don't just want to restore into `regnum', because - later groups should continue to be numbered higher, - as in `(ab)c(de)' -- the second group is #2. */ - regnum_t this_group_regnum; - - compile_stack.avail--; - begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; - fixup_alt_jump - = COMPILE_STACK_TOP.fixup_alt_jump - ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 - : 0; - laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; - this_group_regnum = COMPILE_STACK_TOP.regnum; - /* If we've reached MAX_REGNUM groups, then this open - won't actually generate any code, so we'll have to - clear pending_exact explicitly. */ - pending_exact = 0; - - /* We're at the end of the group, so now we know how many - groups were inside this one. */ - if (this_group_regnum <= MAX_REGNUM) - { - unsigned char *inner_group_loc - = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; - - *inner_group_loc = regnum - this_group_regnum; - BUF_PUSH_3 (stop_memory, this_group_regnum, - regnum - this_group_regnum); - } - } - break; - - - case '|': /* `\|'. */ - if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) - goto normal_backslash; - handle_alt: - if (syntax & RE_LIMITED_OPS) - goto normal_char; - - /* Insert before the previous alternative a jump which - jumps to this alternative if the former fails. */ - GET_BUFFER_SPACE (3); - INSERT_JUMP (on_failure_jump, begalt, b + 6); - pending_exact = 0; - b += 3; - - /* The alternative before this one has a jump after it - which gets executed if it gets matched. Adjust that - jump so it will jump to this alternative's analogous - jump (put in below, which in turn will jump to the next - (if any) alternative's such jump, etc.). The last such - jump jumps to the correct final destination. A picture: - _____ _____ - | | | | - | v | v - a | b | c - - If we are at `b', then fixup_alt_jump right now points to a - three-byte space after `a'. We'll put in the jump, set - fixup_alt_jump to right after `b', and leave behind three - bytes which we'll fill in when we get to after `c'. */ - - if (fixup_alt_jump) - STORE_JUMP (jump_past_alt, fixup_alt_jump, b); - - /* Mark and leave space for a jump after this alternative, - to be filled in later either by next alternative or - when know we're at the end of a series of alternatives. */ - fixup_alt_jump = b; - GET_BUFFER_SPACE (3); - b += 3; - - laststart = 0; - begalt = b; - break; - - - case '{': - /* If \{ is a literal. */ - if (!(syntax & RE_INTERVALS) - /* If we're at `\{' and it's not the open-interval - operator. */ - || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - || (p - 2 == pattern && p == pend)) - goto normal_backslash; - - handle_interval: - { - /* If got here, then the syntax allows intervals. */ - - /* At least (most) this many matches must be made. */ - int lower_bound = -1, upper_bound = -1; - - beg_interval = p - 1; - - if (p == pend) - { - if (syntax & RE_NO_BK_BRACES) - goto unfetch_interval; - else - return REG_EBRACE; - } - - GET_UNSIGNED_NUMBER (lower_bound); - - if (c == ',') - { - GET_UNSIGNED_NUMBER (upper_bound); - if (upper_bound < 0) upper_bound = RE_DUP_MAX; - } - else - /* Interval such as `{1}' => match exactly once. */ - upper_bound = lower_bound; - - if (lower_bound < 0 || upper_bound > RE_DUP_MAX - || lower_bound > upper_bound) - { - if (syntax & RE_NO_BK_BRACES) - goto unfetch_interval; - else - return REG_BADBR; - } - - if (!(syntax & RE_NO_BK_BRACES)) - { - if (c != '\\') return REG_EBRACE; - - PATFETCH (c); - } - - if (c != '}') - { - if (syntax & RE_NO_BK_BRACES) - goto unfetch_interval; - else - return REG_BADBR; - } - - /* We just parsed a valid interval. */ - - /* If it's invalid to have no preceding re. */ - if (!laststart) - { - if (syntax & RE_CONTEXT_INVALID_OPS) - return REG_BADRPT; - else if (syntax & RE_CONTEXT_INDEP_OPS) - laststart = b; - else - goto unfetch_interval; - } - - /* If the upper bound is zero, don't want to succeed at - all; jump from `laststart' to `b + 3', which will be - the end of the buffer after we insert the jump. */ - if (upper_bound == 0) - { - GET_BUFFER_SPACE (3); - INSERT_JUMP (jump, laststart, b + 3); - b += 3; - } - - /* Otherwise, we have a nontrivial interval. When - we're all done, the pattern will look like: - set_number_at <jump count> <upper bound> - set_number_at <succeed_n count> <lower bound> - succeed_n <after jump addr> <succed_n count> - <body of loop> - jump_n <succeed_n addr> <jump count> - (The upper bound and `jump_n' are omitted if - `upper_bound' is 1, though.) */ - else - { /* If the upper bound is > 1, we need to insert - more at the end of the loop. */ - unsigned nbytes = 10 + (upper_bound > 1) * 10; - - GET_BUFFER_SPACE (nbytes); - - /* Initialize lower bound of the `succeed_n', even - though it will be set during matching by its - attendant `set_number_at' (inserted next), - because `re_compile_fastmap' needs to know. - Jump to the `jump_n' we might insert below. */ - INSERT_JUMP2 (succeed_n, laststart, - b + 5 + (upper_bound > 1) * 5, - lower_bound); - b += 5; - - /* Code to initialize the lower bound. Insert - before the `succeed_n'. The `5' is the last two - bytes of this `set_number_at', plus 3 bytes of - the following `succeed_n'. */ - insert_op2 (set_number_at, laststart, 5, lower_bound, b); - b += 5; - - if (upper_bound > 1) - { /* More than one repetition is allowed, so - append a backward jump to the `succeed_n' - that starts this interval. - - When we've reached this during matching, - we'll have matched the interval once, so - jump back only `upper_bound - 1' times. */ - STORE_JUMP2 (jump_n, b, laststart + 5, - upper_bound - 1); - b += 5; - - /* The location we want to set is the second - parameter of the `jump_n'; that is `b-2' as - an absolute address. `laststart' will be - the `set_number_at' we're about to insert; - `laststart+3' the number to set, the source - for the relative address. But we are - inserting into the middle of the pattern -- - so everything is getting moved up by 5. - Conclusion: (b - 2) - (laststart + 3) + 5, - i.e., b - laststart. - - We insert this at the beginning of the loop - so that if we fail during matching, we'll - reinitialize the bounds. */ - insert_op2 (set_number_at, laststart, b - laststart, - upper_bound - 1, b); - b += 5; - } - } - pending_exact = 0; - beg_interval = NULL; - } - break; - - unfetch_interval: - /* If an invalid interval, match the characters as literals. */ - assert (beg_interval); - p = beg_interval; - beg_interval = NULL; - - /* normal_char and normal_backslash need `c'. */ - PATFETCH (c); - - if (!(syntax & RE_NO_BK_BRACES)) - { - if (p > pattern && p[-1] == '\\') - goto normal_backslash; - } - goto normal_char; - -#ifdef emacs - /* There is no way to specify the before_dot and after_dot - operators. rms says this is ok. --karl */ - case '=': - BUF_PUSH (at_dot); - break; - - case 's': - laststart = b; - PATFETCH (c); - BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); - break; - - case 'S': - laststart = b; - PATFETCH (c); - BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); - break; -#endif /* emacs */ - - - case 'w': - laststart = b; - BUF_PUSH (wordchar); - break; - - - case 'W': - laststart = b; - BUF_PUSH (notwordchar); - break; - - - case '<': - BUF_PUSH (wordbeg); - break; - - case '>': - BUF_PUSH (wordend); - break; - - case 'b': - BUF_PUSH (wordbound); - break; - - case 'B': - BUF_PUSH (notwordbound); - break; - - case '`': - BUF_PUSH (begbuf); - break; - - case '\'': - BUF_PUSH (endbuf); - break; - - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - if (syntax & RE_NO_BK_REFS) - goto normal_char; - - c1 = c - '0'; - - if (c1 > regnum) - return REG_ESUBREG; - - /* Can't back reference to a subexpression if inside of it. */ - if (group_in_compile_stack (compile_stack, c1)) - goto normal_char; - - laststart = b; - BUF_PUSH_2 (duplicate, c1); - break; - - - case '+': - case '?': - if (syntax & RE_BK_PLUS_QM) - goto handle_plus; - else - goto normal_backslash; - - default: - normal_backslash: - /* You might think it would be useful for \ to mean - not to translate; but if we don't translate it - it will never match anything. */ - c = TRANSLATE (c); - goto normal_char; - } - break; - - - default: - /* Expects the character in `c'. */ - normal_char: - /* If no exactn currently being built. */ - if (!pending_exact - - /* If last exactn not at current position. */ - || pending_exact + *pending_exact + 1 != b - - /* We have only one byte following the exactn for the count. */ - || *pending_exact == (1 << BYTEWIDTH) - 1 - - /* If followed by a repetition operator. */ - || *p == '*' || *p == '^' - || ((syntax & RE_BK_PLUS_QM) - ? *p == '\\' && (p[1] == '+' || p[1] == '?') - : (*p == '+' || *p == '?')) - || ((syntax & RE_INTERVALS) - && ((syntax & RE_NO_BK_BRACES) - ? *p == '{' - : (p[0] == '\\' && p[1] == '{')))) - { - /* Start building a new exactn. */ - - laststart = b; - - BUF_PUSH_2 (exactn, 0); - pending_exact = b - 1; - } - - BUF_PUSH (c); - (*pending_exact)++; - break; - } /* switch (c) */ - } /* while p != pend */ - - - /* Through the pattern now. */ - - if (fixup_alt_jump) - STORE_JUMP (jump_past_alt, fixup_alt_jump, b); - - if (!COMPILE_STACK_EMPTY) - return REG_EPAREN; - - free (compile_stack.stack); - - /* We have succeeded; set the length of the buffer. */ - bufp->used = b - bufp->buffer; - -#ifdef DEBUG - if (debug) - { - DEBUG_PRINT1 ("\nCompiled pattern: "); - print_compiled_pattern (bufp); - } -#endif /* DEBUG */ - - return REG_NOERROR; -} /* regex_compile */ - -/* Subroutines for `regex_compile'. */ - -/* Store OP at LOC followed by two-byte integer parameter ARG. */ - -static void -store_op1 (op, loc, arg) - re_opcode_t op; - unsigned char *loc; - int arg; -{ - *loc = (unsigned char) op; - STORE_NUMBER (loc + 1, arg); -} - - -/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ - -static void -store_op2 (op, loc, arg1, arg2) - re_opcode_t op; - unsigned char *loc; - int arg1, arg2; -{ - *loc = (unsigned char) op; - STORE_NUMBER (loc + 1, arg1); - STORE_NUMBER (loc + 3, arg2); -} - - -/* Copy the bytes from LOC to END to open up three bytes of space at LOC - for OP followed by two-byte integer parameter ARG. */ - -static void -insert_op1 (op, loc, arg, end) - re_opcode_t op; - unsigned char *loc; - int arg; - unsigned char *end; -{ - register unsigned char *pfrom = end; - register unsigned char *pto = end + 3; - - while (pfrom != loc) - *--pto = *--pfrom; - - store_op1 (op, loc, arg); -} - - -/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ - -static void -insert_op2 (op, loc, arg1, arg2, end) - re_opcode_t op; - unsigned char *loc; - int arg1, arg2; - unsigned char *end; -{ - register unsigned char *pfrom = end; - register unsigned char *pto = end + 5; - - while (pfrom != loc) - *--pto = *--pfrom; - - store_op2 (op, loc, arg1, arg2); -} - - -/* P points to just after a ^ in PATTERN. Return true if that ^ comes - after an alternative or a begin-subexpression. We assume there is at - least one character before the ^. */ - -static boolean -at_begline_loc_p (pattern, p, syntax) - const char *pattern, *p; - reg_syntax_t syntax; -{ - const char *prev = p - 2; - boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; - - return - /* After a subexpression? */ - (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) - /* After an alternative? */ - || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); -} - - -/* The dual of at_begline_loc_p. This one is for $. We assume there is - at least one character after the $, i.e., `P < PEND'. */ - -static boolean -at_endline_loc_p (p, pend, syntax) - const char *p, *pend; - int syntax; -{ - const char *next = p; - boolean next_backslash = *next == '\\'; - const char *next_next = p + 1 < pend ? p + 1 : NULL; - - return - /* Before a subexpression? */ - (syntax & RE_NO_BK_PARENS ? *next == ')' - : next_backslash && next_next && *next_next == ')') - /* Before an alternative? */ - || (syntax & RE_NO_BK_VBAR ? *next == '|' - : next_backslash && next_next && *next_next == '|'); -} - - -/* Returns true if REGNUM is in one of COMPILE_STACK's elements and - false if it's not. */ - -static boolean -group_in_compile_stack (compile_stack, regnum) - compile_stack_type compile_stack; - regnum_t regnum; -{ - int this_element; - - for (this_element = compile_stack.avail - 1; - this_element >= 0; - this_element--) - if (compile_stack.stack[this_element].regnum == regnum) - return true; - - return false; -} - - -/* Read the ending character of a range (in a bracket expression) from the - uncompiled pattern *P_PTR (which ends at PEND). We assume the - starting character is in `P[-2]'. (`P[-1]' is the character `-'.) - Then we set the translation of all bits between the starting and - ending characters (inclusive) in the compiled pattern B. - - Return an error code. - - We use these short variable names so we can use the same macros as - `regex_compile' itself. */ - -static reg_errcode_t -compile_range (p_ptr, pend, translate, syntax, b) - const char **p_ptr, *pend; - char *translate; - reg_syntax_t syntax; - unsigned char *b; -{ - unsigned this_char; - - const char *p = *p_ptr; - int range_start, range_end; - - if (p == pend) - return REG_ERANGE; - - /* Even though the pattern is a signed `char *', we need to fetch - with unsigned char *'s; if the high bit of the pattern character - is set, the range endpoints will be negative if we fetch using a - signed char *. - - We also want to fetch the endpoints without translating them; the - appropriate translation is done in the bit-setting loop below. */ - range_start = ((unsigned char *) p)[-2]; - range_end = ((unsigned char *) p)[0]; - - /* Have to increment the pointer into the pattern string, so the - caller isn't still at the ending character. */ - (*p_ptr)++; - - /* If the start is after the end, the range is empty. */ - if (range_start > range_end) - return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; - - /* Here we see why `this_char' has to be larger than an `unsigned - char' -- the range is inclusive, so if `range_end' == 0xff - (assuming 8-bit characters), we would otherwise go into an infinite - loop, since all characters <= 0xff. */ - for (this_char = range_start; this_char <= range_end; this_char++) - { - SET_LIST_BIT (TRANSLATE (this_char)); - } - - return REG_NOERROR; -} - -/* Failure stack declarations and macros; both re_compile_fastmap and - re_match_2 use a failure stack. These have to be macros because of - REGEX_ALLOCATE. */ - - -/* Number of failure points for which to initially allocate space - when matching. If this number is exceeded, we allocate more - space, so it is not a hard limit. */ -#ifndef INIT_FAILURE_ALLOC -#define INIT_FAILURE_ALLOC 5 -#endif - -/* Roughly the maximum number of failure points on the stack. Would be - exactly that if always used MAX_FAILURE_SPACE each time we failed. - This is a variable only so users of regex can assign to it; we never - change it ourselves. */ -int re_max_failures = 2000; - -typedef const unsigned char *fail_stack_elt_t; - -typedef struct -{ - fail_stack_elt_t *stack; - unsigned size; - unsigned avail; /* Offset of next open position. */ -} fail_stack_type; - -#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) -#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) -#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) -#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) - - -/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ - -#define INIT_FAIL_STACK() \ - do { \ - fail_stack.stack = (fail_stack_elt_t *) \ - REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ - \ - if (fail_stack.stack == NULL) \ - return -2; \ - \ - fail_stack.size = INIT_FAILURE_ALLOC; \ - fail_stack.avail = 0; \ - } while (0) - - -/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. - - Return 1 if succeeds, and 0 if either ran out of memory - allocating space for it or it was already too large. - - REGEX_REALLOCATE requires `destination' be declared. */ - -#define DOUBLE_FAIL_STACK(fail_stack) \ - ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ - ? 0 \ - : ((fail_stack).stack = (fail_stack_elt_t *) \ - REGEX_REALLOCATE ((fail_stack).stack, \ - (fail_stack).size * sizeof (fail_stack_elt_t), \ - ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ - \ - (fail_stack).stack == NULL \ - ? 0 \ - : ((fail_stack).size <<= 1, \ - 1))) - - -/* Push PATTERN_OP on FAIL_STACK. - - Return 1 if was able to do so and 0 if ran out of memory allocating - space to do so. */ -#define PUSH_PATTERN_OP(pattern_op, fail_stack) \ - ((FAIL_STACK_FULL () \ - && !DOUBLE_FAIL_STACK (fail_stack)) \ - ? 0 \ - : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ - 1)) - -/* This pushes an item onto the failure stack. Must be a four-byte - value. Assumes the variable `fail_stack'. Probably should only - be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_ITEM(item) \ - fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item - -/* The complement operation. Assumes `fail_stack' is nonempty. */ -#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] - -/* Used to omit pushing failure point id's when we're not debugging. */ -#ifdef DEBUG -#define DEBUG_PUSH PUSH_FAILURE_ITEM -#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () -#else -#define DEBUG_PUSH(item) -#define DEBUG_POP(item_addr) -#endif - - -/* Push the information about the state we will need - if we ever fail back to it. - - Requires variables fail_stack, regstart, regend, reg_info, and - num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be - declared. - - Does `return FAILURE_CODE' if runs out of memory. */ - -#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ - do { \ - char *destination; \ - /* Must be int, so when we don't save any registers, the arithmetic \ - of 0 + -1 isn't done as unsigned. */ \ - int this_reg; \ - \ - DEBUG_STATEMENT (failure_id++); \ - DEBUG_STATEMENT (nfailure_points_pushed++); \ - DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ - DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ - DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ - \ - DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ - DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ - \ - /* Ensure we have enough space allocated for what we will push. */ \ - while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ - { \ - if (!DOUBLE_FAIL_STACK (fail_stack)) \ - return failure_code; \ - \ - DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ - (fail_stack).size); \ - DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ - } \ - \ - /* Push the info, starting with the registers. */ \ - DEBUG_PRINT1 ("\n"); \ - \ - for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ - this_reg++) \ - { \ - DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ - DEBUG_STATEMENT (num_regs_pushed++); \ - \ - DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ - PUSH_FAILURE_ITEM (regstart[this_reg]); \ - \ - DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ - PUSH_FAILURE_ITEM (regend[this_reg]); \ - \ - DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ - DEBUG_PRINT2 (" match_null=%d", \ - REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ - DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ - DEBUG_PRINT2 (" matched_something=%d", \ - MATCHED_SOMETHING (reg_info[this_reg])); \ - DEBUG_PRINT2 (" ever_matched=%d", \ - EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ - DEBUG_PRINT1 ("\n"); \ - PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ - } \ - \ - DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ - PUSH_FAILURE_ITEM (lowest_active_reg); \ - \ - DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ - PUSH_FAILURE_ITEM (highest_active_reg); \ - \ - DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ - DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ - PUSH_FAILURE_ITEM (pattern_place); \ - \ - DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ - DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ - size2); \ - DEBUG_PRINT1 ("'\n"); \ - PUSH_FAILURE_ITEM (string_place); \ - \ - DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ - DEBUG_PUSH (failure_id); \ - } while (0) - -/* This is the number of items that are pushed and popped on the stack - for each register. */ -#define NUM_REG_ITEMS 3 - -/* Individual items aside from the registers. */ -#ifdef DEBUG -#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ -#else -#define NUM_NONREG_ITEMS 4 -#endif - -/* We push at most this many items on the stack. */ -#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) - -/* We actually push this many items. */ -#define NUM_FAILURE_ITEMS \ - ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ - + NUM_NONREG_ITEMS) - -/* How many items can still be added to the stack without overflowing it. */ -#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) - - -/* Pops what PUSH_FAIL_STACK pushes. - - We restore into the parameters, all of which should be lvalues: - STR -- the saved data position. - PAT -- the saved pattern position. - LOW_REG, HIGH_REG -- the highest and lowest active registers. - REGSTART, REGEND -- arrays of string positions. - REG_INFO -- array of information about each subexpression. - - Also assumes the variables `fail_stack' and (if debugging), `bufp', - `pend', `string1', `size1', `string2', and `size2'. */ - -#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ -{ \ - DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ - int this_reg; \ - const unsigned char *string_temp; \ - \ - assert (!FAIL_STACK_EMPTY ()); \ - \ - /* Remove failure points and point to how many regs pushed. */ \ - DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ - DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ - DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ - \ - assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ - \ - DEBUG_POP (&failure_id); \ - DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ - \ - /* If the saved string location is NULL, it came from an \ - on_failure_keep_string_jump opcode, and we want to throw away the \ - saved NULL, thus retaining our current position in the string. */ \ - string_temp = POP_FAILURE_ITEM (); \ - if (string_temp != NULL) \ - str = (const char *) string_temp; \ - \ - DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ - DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ - DEBUG_PRINT1 ("'\n"); \ - \ - pat = (unsigned char *) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ - DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ - \ - /* Restore register info. */ \ - high_reg = (unsigned) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ - \ - low_reg = (unsigned) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ - \ - for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ - { \ - DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ - \ - reg_info[this_reg].word = POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ - \ - regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ - \ - regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ - } \ - \ - DEBUG_STATEMENT (nfailure_points_popped++); \ -} /* POP_FAILURE_POINT */ - -/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in - BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible - characters can start a string that matches the pattern. This fastmap - is used by re_search to skip quickly over impossible starting points. - - The caller must supply the address of a (1 << BYTEWIDTH)-byte data - area as BUFP->fastmap. - - We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in - the pattern buffer. - - Returns 0 if we succeed, -2 if an internal error. */ - -int -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; -{ - int j, k; - fail_stack_type fail_stack; -#ifndef REGEX_MALLOC - char *destination; -#endif - /* We don't push any register information onto the failure stack. */ - unsigned num_regs = 0; - - register char *fastmap = bufp->fastmap; - unsigned char *pattern = bufp->buffer; - unsigned long size = bufp->used; - const unsigned char *p = pattern; - register unsigned char *pend = pattern + size; - - /* Assume that each path through the pattern can be null until - proven otherwise. We set this false at the bottom of switch - statement, to which we get only if a particular path doesn't - match the empty string. */ - boolean path_can_be_null = true; - - /* We aren't doing a `succeed_n' to begin with. */ - boolean succeed_n_p = false; - - assert (fastmap != NULL && p != NULL); - - INIT_FAIL_STACK (); - bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ - bufp->fastmap_accurate = 1; /* It will be when we're done. */ - bufp->can_be_null = 0; - - while (p != pend || !FAIL_STACK_EMPTY ()) - { - if (p == pend) - { - bufp->can_be_null |= path_can_be_null; - - /* Reset for next path. */ - path_can_be_null = true; - - p = fail_stack.stack[--fail_stack.avail]; - } - - /* We should never be about to go beyond the end of the pattern. */ - assert (p < pend); - -#ifdef SWITCH_ENUM_BUG - switch ((int) ((re_opcode_t) *p++)) -#else - switch ((re_opcode_t) *p++) -#endif - { - - /* I guess the idea here is to simply not bother with a fastmap - if a backreference is used, since it's too hard to figure out - the fastmap for the corresponding group. Setting - `can_be_null' stops `re_search_2' from using the fastmap, so - that is all we do. */ - case duplicate: - bufp->can_be_null = 1; - return 0; - - - /* Following are the cases which match a character. These end - with `break'. */ - - case exactn: - fastmap[p[1]] = 1; - break; - - - case charset: - for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) - if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) - fastmap[j] = 1; - break; - - - case charset_not: - /* Chars beyond end of map must be allowed. */ - for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) - fastmap[j] = 1; - - for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) - if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) - fastmap[j] = 1; - break; - - - case wordchar: - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) == Sword) - fastmap[j] = 1; - break; - - - case notwordchar: - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) != Sword) - fastmap[j] = 1; - break; - - - case anychar: - /* `.' matches anything ... */ - for (j = 0; j < (1 << BYTEWIDTH); j++) - fastmap[j] = 1; - - /* ... except perhaps newline. */ - if (!(bufp->syntax & RE_DOT_NEWLINE)) - fastmap['\n'] = 0; - - /* Return if we have already set `can_be_null'; if we have, - then the fastmap is irrelevant. Something's wrong here. */ - else if (bufp->can_be_null) - return 0; - - /* Otherwise, have to check alternative paths. */ - break; - - -#ifdef emacs - case syntaxspec: - k = *p++; - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) == (enum syntaxcode) k) - fastmap[j] = 1; - break; - - - case notsyntaxspec: - k = *p++; - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) != (enum syntaxcode) k) - fastmap[j] = 1; - break; - - - /* All cases after this match the empty string. These end with - `continue'. */ - - - case before_dot: - case at_dot: - case after_dot: - continue; -#endif /* not emacs */ - - - case no_op: - case begline: - case endline: - case begbuf: - case endbuf: - case wordbound: - case notwordbound: - case wordbeg: - case wordend: - case push_dummy_failure: - continue; - - - case jump_n: - case pop_failure_jump: - case maybe_pop_jump: - case jump: - case jump_past_alt: - case dummy_failure_jump: - EXTRACT_NUMBER_AND_INCR (j, p); - p += j; - if (j > 0) - continue; - - /* Jump backward implies we just went through the body of a - loop and matched nothing. Opcode jumped to should be - `on_failure_jump' or `succeed_n'. Just treat it like an - ordinary jump. For a * loop, it has pushed its failure - point already; if so, discard that as redundant. */ - if ((re_opcode_t) *p != on_failure_jump - && (re_opcode_t) *p != succeed_n) - continue; - - p++; - EXTRACT_NUMBER_AND_INCR (j, p); - p += j; - - /* If what's on the stack is where we are now, pop it. */ - if (!FAIL_STACK_EMPTY () - && fail_stack.stack[fail_stack.avail - 1] == p) - fail_stack.avail--; - - continue; - - - case on_failure_jump: - case on_failure_keep_string_jump: - handle_on_failure_jump: - EXTRACT_NUMBER_AND_INCR (j, p); - - /* For some patterns, e.g., `(a?)?', `p+j' here points to the - end of the pattern. We don't want to push such a point, - since when we restore it above, entering the switch will - increment `p' past the end of the pattern. We don't need - to push such a point since we obviously won't find any more - fastmap entries beyond `pend'. Such a pattern can match - the null string, though. */ - if (p + j < pend) - { - if (!PUSH_PATTERN_OP (p + j, fail_stack)) - return -2; - } - else - bufp->can_be_null = 1; - - if (succeed_n_p) - { - EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ - succeed_n_p = false; - } - - continue; - - - case succeed_n: - /* Get to the number of times to succeed. */ - p += 2; - - /* Increment p past the n for when k != 0. */ - EXTRACT_NUMBER_AND_INCR (k, p); - if (k == 0) - { - p -= 4; - succeed_n_p = true; /* Spaghetti code alert. */ - goto handle_on_failure_jump; - } - continue; - - - case set_number_at: - p += 4; - continue; - - - case start_memory: - case stop_memory: - p += 2; - continue; - - - default: - abort (); /* We have listed all the cases. */ - } /* switch *p++ */ - - /* Getting here means we have found the possible starting - characters for one path of the pattern -- and that the empty - string does not match. We need not follow this path further. - Instead, look at the next alternative (remembered on the - stack), or quit if no more. The test at the top of the loop - does these things. */ - path_can_be_null = false; - p = pend; - } /* while p */ - - /* Set `can_be_null' for the last path (also the first path, if the - pattern is empty). */ - bufp->can_be_null |= path_can_be_null; - return 0; -} /* re_compile_fastmap */ - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use - this memory for recording register information. STARTS and ENDS - must be allocated using the malloc library routine, and must each - be at least NUM_REGS * sizeof (regoff_t) bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ - -void -re_set_registers (bufp, regs, num_regs, starts, ends) - struct re_pattern_buffer *bufp; - struct re_registers *regs; - unsigned num_regs; - regoff_t *starts, *ends; -{ - if (num_regs) - { - bufp->regs_allocated = REGS_REALLOCATE; - regs->num_regs = num_regs; - regs->start = starts; - regs->end = ends; - } - else - { - bufp->regs_allocated = REGS_UNALLOCATED; - regs->num_regs = 0; - regs->start = regs->end = (regoff_t) 0; - } -} - -/* Searching routines. */ - -/* Like re_search_2, below, but only one string is specified, and - doesn't let you say where to stop matching. */ - -int -re_search (bufp, string, size, startpos, range, regs) - struct re_pattern_buffer *bufp; - const char *string; - int size, startpos, range; - struct re_registers *regs; -{ - return re_search_2 (bufp, NULL, 0, string, size, startpos, range, - regs, size); -} - - -/* Using the compiled pattern in BUFP->buffer, first tries to match the - virtual concatenation of STRING1 and STRING2, starting first at index - STARTPOS, then at STARTPOS + 1, and so on. - - STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. - - RANGE is how far to scan while trying to match. RANGE = 0 means try - only at STARTPOS; in general, the last start tried is STARTPOS + - RANGE. - - In REGS, return the indices of the virtual concatenation of STRING1 - and STRING2 that matched the entire BUFP->buffer and its contained - subexpressions. - - Do not consider matching one past the index STOP in the virtual - concatenation of STRING1 and STRING2. - - We return either the position in the strings at which the match was - found, -1 if no match, or -2 if error (such as failure - stack overflow). */ - -int -re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int startpos; - int range; - struct re_registers *regs; - int stop; -{ - int val; - register char *fastmap = bufp->fastmap; - register char *translate = bufp->translate; - int total_size = size1 + size2; - int endpos = startpos + range; - - /* Check for out-of-range STARTPOS. */ - if (startpos < 0 || startpos > total_size) - return -1; - - /* Fix up RANGE if it might eventually take us outside - the virtual concatenation of STRING1 and STRING2. */ - if (endpos < -1) - range = -1 - startpos; - else if (endpos > total_size) - range = total_size - startpos; - - /* If the search isn't to be a backwards one, don't waste time in a - search for a pattern that must be anchored. */ - if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) - { - if (startpos > 0) - return -1; - else - range = 1; - } - - /* Update the fastmap now if not correct already. */ - if (fastmap && !bufp->fastmap_accurate) - if (re_compile_fastmap (bufp) == -2) - return -2; - - /* Loop through the string, looking for a place to start matching. */ - for (;;) - { - /* If a fastmap is supplied, skip quickly over characters that - cannot be the start of a match. If the pattern can match the - null string, however, we don't need to skip characters; we want - the first null string. */ - if (fastmap && startpos < total_size && !bufp->can_be_null) - { - if (range > 0) /* Searching forwards. */ - { - register const char *d; - register int lim = 0; - int irange = range; - - if (startpos < size1 && startpos + range >= size1) - lim = range - (size1 - startpos); - - d = (startpos >= size1 ? string2 - size1 : string1) + startpos; - - /* Written out as an if-else to avoid testing `translate' - inside the loop. */ - if (translate) - while (range > lim - && !fastmap[(unsigned char) - translate[(unsigned char) *d++]]) - range--; - else - while (range > lim && !fastmap[(unsigned char) *d++]) - range--; - - startpos += irange - range; - } - else /* Searching backwards. */ - { - register char c = (size1 == 0 || startpos >= size1 - ? string2[startpos - size1] - : string1[startpos]); - - if (!fastmap[(unsigned char) TRANSLATE (c)]) - goto advance; - } - } - - /* If can't match the null string, and that's all we have left, fail. */ - if (range >= 0 && startpos == total_size && fastmap - && !bufp->can_be_null) - return -1; - - val = re_match_2 (bufp, string1, size1, string2, size2, - startpos, regs, stop); - if (val >= 0) - return startpos; - - if (val == -2) - return -2; - - advance: - if (!range) - break; - else if (range > 0) - { - range--; - startpos++; - } - else - { - range++; - startpos--; - } - } - return -1; -} /* re_search_2 */ - -/* Declarations and macros for re_match_2. */ - -static int bcmp_translate (); -static boolean alt_match_null_string_p (), - common_op_match_null_string_p (), - group_match_null_string_p (); - -/* Structure for per-register (a.k.a. per-group) information. - This must not be longer than one word, because we push this value - onto the failure stack. Other register information, such as the - starting and ending positions (which are addresses), and the list of - inner groups (which is a bits list) are maintained in separate - variables. - - We are making a (strictly speaking) nonportable assumption here: that - the compiler will pack our bit fields into something that fits into - the type of `word', i.e., is something that fits into one item on the - failure stack. */ -typedef union -{ - fail_stack_elt_t word; - struct - { - /* This field is one if this group can match the empty string, - zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ -#define MATCH_NULL_UNSET_VALUE 3 - unsigned match_null_string_p : 2; - unsigned is_active : 1; - unsigned matched_something : 1; - unsigned ever_matched_something : 1; - } bits; -} register_info_type; - -#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) -#define IS_ACTIVE(R) ((R).bits.is_active) -#define MATCHED_SOMETHING(R) ((R).bits.matched_something) -#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) - - -/* Call this when have matched a real character; it sets `matched' flags - for the subexpressions which we are currently inside. Also records - that those subexprs have matched. */ -#define SET_REGS_MATCHED() \ - do \ - { \ - unsigned r; \ - for (r = lowest_active_reg; r <= highest_active_reg; r++) \ - { \ - MATCHED_SOMETHING (reg_info[r]) \ - = EVER_MATCHED_SOMETHING (reg_info[r]) \ - = 1; \ - } \ - } \ - while (0) - - -/* This converts PTR, a pointer into one of the search strings `string1' - and `string2' into an offset from the beginning of that string. */ -#define POINTER_TO_OFFSET(ptr) \ - (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1) - -/* Registers are set to a sentinel when they haven't yet matched. */ -#define REG_UNSET_VALUE ((char *) -1) -#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) - - -/* Macros for dealing with the split strings in re_match_2. */ - -#define MATCHING_IN_FIRST_STRING (dend == end_match_1) - -/* Call before fetching a character with *d. This switches over to - string2 if necessary. */ -#define PREFETCH() \ - while (d == dend) \ - { \ - /* End of string2 => fail. */ \ - if (dend == end_match_2) \ - goto fail; \ - /* End of string1 => advance to string2. */ \ - d = string2; \ - dend = end_match_2; \ - } - - -/* Test if at very beginning or at very end of the virtual concatenation - of `string1' and `string2'. If only one string, it's `string2'. */ -#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) -#define AT_STRINGS_END(d) ((d) == end2) - - -/* Test if D points to a character which is word-constituent. We have - two special cases to check for: if past the end of string1, look at - the first character in string2; and if before the beginning of - string2, look at the last character in string1. */ -#define WORDCHAR_P(d) \ - (SYNTAX ((d) == end1 ? *string2 \ - : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ - == Sword) - -/* Test if the character before D and the one at D differ with respect - to being word-constituent. */ -#define AT_WORD_BOUNDARY(d) \ - (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ - || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) - - -/* Free everything we malloc. */ -#ifdef REGEX_MALLOC -#define FREE_VAR(var) if (var) free (var); var = NULL -#define FREE_VARIABLES() \ - do { \ - FREE_VAR (fail_stack.stack); \ - FREE_VAR (regstart); \ - FREE_VAR (regend); \ - FREE_VAR (old_regstart); \ - FREE_VAR (old_regend); \ - FREE_VAR (best_regstart); \ - FREE_VAR (best_regend); \ - FREE_VAR (reg_info); \ - FREE_VAR (reg_dummy); \ - FREE_VAR (reg_info_dummy); \ - } while (0) -#else /* not REGEX_MALLOC */ -/* Some MIPS systems (at least) want this to free alloca'd storage. */ -#define FREE_VARIABLES() alloca (0) -#endif /* not REGEX_MALLOC */ - - -/* These values must meet several constraints. They must not be valid - register values; since we have a limit of 255 registers (because - we use only one byte in the pattern for the register number), we can - use numbers larger than 255. They must differ by 1, because of - NUM_FAILURE_ITEMS above. And the value for the lowest register must - be larger than the value for the highest register, so we do not try - to actually save any registers when none are active. */ -#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) -#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) - -/* Matching routines. */ - -#ifndef emacs /* Emacs never uses this. */ -/* re_match is like re_match_2 except it takes only a single string. */ - -int -re_match (bufp, string, size, pos, regs) - struct re_pattern_buffer *bufp; - const char *string; - int size, pos; - struct re_registers *regs; - { - return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size); -} -#endif /* not emacs */ - - -/* re_match_2 matches the compiled pattern in BUFP against the - the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 - and SIZE2, respectively). We start matching at POS, and stop - matching at STOP. - - If REGS is non-null and the `no_sub' field of BUFP is nonzero, we - store offsets for the substring each group matched in REGS. See the - documentation for exactly how many groups we fill. - - We return -1 if no match, -2 if an internal error (such as the - failure stack overflowing). Otherwise, we return the length of the - matched substring. */ - -int -re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int pos; - struct re_registers *regs; - int stop; -{ - /* General temporaries. */ - int mcnt; - unsigned char *p1; - - /* Just past the end of the corresponding string. */ - const char *end1, *end2; - - /* Pointers into string1 and string2, just past the last characters in - each to consider matching. */ - const char *end_match_1, *end_match_2; - - /* Where we are in the data, and the end of the current string. */ - const char *d, *dend; - - /* Where we are in the pattern, and the end of the pattern. */ - unsigned char *p = bufp->buffer; - register unsigned char *pend = p + bufp->used; - - /* We use this to map every character in the string. */ - char *translate = bufp->translate; - - /* Failure point stack. Each place that can handle a failure further - down the line pushes a failure point on this stack. It consists of - restart, regend, and reg_info for all registers corresponding to - the subexpressions we're currently inside, plus the number of such - registers, and, finally, two char *'s. The first char * is where - to resume scanning the pattern; the second one is where to resume - scanning the strings. If the latter is zero, the failure point is - a ``dummy''; if a failure happens and the failure point is a dummy, - it gets discarded and the next next one is tried. */ - fail_stack_type fail_stack; -#ifdef DEBUG - static unsigned failure_id = 0; - unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; -#endif - - /* We fill all the registers internally, independent of what we - return, for use in backreferences. The number here includes - an element for register zero. */ - unsigned num_regs = bufp->re_nsub + 1; - - /* The currently active registers. */ - unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG; - unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG; - - /* Information on the contents of registers. These are pointers into - the input strings; they record just what was matched (on this - attempt) by a subexpression part of the pattern, that is, the - regnum-th regstart pointer points to where in the pattern we began - matching and the regnum-th regend points to right after where we - stopped matching the regnum-th subexpression. (The zeroth register - keeps track of what the whole pattern matches.) */ - const char **regstart, **regend; - - /* If a group that's operated upon by a repetition operator fails to - match anything, then the register for its start will need to be - restored because it will have been set to wherever in the string we - are when we last see its open-group operator. Similarly for a - register's end. */ - const char **old_regstart, **old_regend; - - /* The is_active field of reg_info helps us keep track of which (possibly - nested) subexpressions we are currently in. The matched_something - field of reg_info[reg_num] helps us tell whether or not we have - matched any of the pattern so far this time through the reg_num-th - subexpression. These two fields get reset each time through any - loop their register is in. */ - register_info_type *reg_info; - - /* The following record the register info as found in the above - variables when we find a match better than any we've seen before. - This happens as we backtrack through the failure points, which in - turn happens only if we have not yet matched the entire string. */ - unsigned best_regs_set = false; - const char **best_regstart, **best_regend; - - /* Logically, this is `best_regend[0]'. But we don't want to have to - allocate space for that if we're not allocating space for anything - else (see below). Also, we never need info about register 0 for - any of the other register vectors, and it seems rather a kludge to - treat `best_regend' differently than the rest. So we keep track of - the end of the best match so far in a separate variable. We - initialize this to NULL so that when we backtrack the first time - and need to test it, it's not garbage. */ - const char *match_end = NULL; - - /* Used when we pop values we don't care about. */ - const char **reg_dummy; - register_info_type *reg_info_dummy; - -#ifdef DEBUG - /* Counts the total number of registers pushed. */ - unsigned num_regs_pushed = 0; -#endif - - DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); - - INIT_FAIL_STACK (); - - /* Do not bother to initialize all the register variables if there are - no groups in the pattern, as it takes a fair amount of time. If - there are groups, we include space for register 0 (the whole - pattern), even though we never use it, since it simplifies the - array indexing. We should fix this. */ - if (bufp->re_nsub) - { - regstart = REGEX_TALLOC (num_regs, const char *); - regend = REGEX_TALLOC (num_regs, const char *); - old_regstart = REGEX_TALLOC (num_regs, const char *); - old_regend = REGEX_TALLOC (num_regs, const char *); - best_regstart = REGEX_TALLOC (num_regs, const char *); - best_regend = REGEX_TALLOC (num_regs, const char *); - reg_info = REGEX_TALLOC (num_regs, register_info_type); - reg_dummy = REGEX_TALLOC (num_regs, const char *); - reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); - - if (!(regstart && regend && old_regstart && old_regend && reg_info - && best_regstart && best_regend && reg_dummy && reg_info_dummy)) - { - FREE_VARIABLES (); - return -2; - } - } -#ifdef REGEX_MALLOC - else - { - /* We must initialize all our variables to NULL, so that - `FREE_VARIABLES' doesn't try to free them. */ - regstart = regend = old_regstart = old_regend = best_regstart - = best_regend = reg_dummy = NULL; - reg_info = reg_info_dummy = (register_info_type *) NULL; - } -#endif /* REGEX_MALLOC */ - - /* The starting position is bogus. */ - if (pos < 0 || pos > size1 + size2) - { - FREE_VARIABLES (); - return -1; - } - - /* Initialize subexpression text positions to -1 to mark ones that no - start_memory/stop_memory has been seen for. Also initialize the - register information struct. */ - for (mcnt = 1; mcnt < num_regs; mcnt++) - { - regstart[mcnt] = regend[mcnt] - = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; - - REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; - IS_ACTIVE (reg_info[mcnt]) = 0; - MATCHED_SOMETHING (reg_info[mcnt]) = 0; - EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; - } - - /* We move `string1' into `string2' if the latter's empty -- but not if - `string1' is null. */ - if (size2 == 0 && string1 != NULL) - { - string2 = string1; - size2 = size1; - string1 = 0; - size1 = 0; - } - end1 = string1 + size1; - end2 = string2 + size2; - - /* Compute where to stop matching, within the two strings. */ - if (stop <= size1) - { - end_match_1 = string1 + stop; - end_match_2 = string2; - } - else - { - end_match_1 = end1; - end_match_2 = string2 + stop - size1; - } - - /* `p' scans through the pattern as `d' scans through the data. - `dend' is the end of the input string that `d' points within. `d' - is advanced into the following input string whenever necessary, but - this happens before fetching; therefore, at the beginning of the - loop, `d' can be pointing at the end of a string, but it cannot - equal `string2'. */ - if (size1 > 0 && pos <= size1) - { - d = string1 + pos; - dend = end_match_1; - } - else - { - d = string2 + pos - size1; - dend = end_match_2; - } - - DEBUG_PRINT1 ("The compiled pattern is: "); - DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); - DEBUG_PRINT1 ("The string to match is: `"); - DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); - DEBUG_PRINT1 ("'\n"); - - /* This loops over pattern commands. It exits by returning from the - function if the match is complete, or it drops through if the match - fails at this starting point in the input data. */ - for (;;) - { - DEBUG_PRINT2 ("\n0x%x: ", p); - - if (p == pend) - { /* End of pattern means we might have succeeded. */ - DEBUG_PRINT1 ("end of pattern ... "); - - /* If we haven't matched the entire string, and we want the - longest match, try backtracking. */ - if (d != end_match_2) - { - DEBUG_PRINT1 ("backtracking.\n"); - - if (!FAIL_STACK_EMPTY ()) - { /* More failure points to try. */ - boolean same_str_p = (FIRST_STRING_P (match_end) - == MATCHING_IN_FIRST_STRING); - - /* If exceeds best match so far, save it. */ - if (!best_regs_set - || (same_str_p && d > match_end) - || (!same_str_p && !MATCHING_IN_FIRST_STRING)) - { - best_regs_set = true; - match_end = d; - - DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); - - for (mcnt = 1; mcnt < num_regs; mcnt++) - { - best_regstart[mcnt] = regstart[mcnt]; - best_regend[mcnt] = regend[mcnt]; - } - } - goto fail; - } - - /* If no failure points, don't restore garbage. */ - else if (best_regs_set) - { - restore_best_regs: - /* Restore best match. It may happen that `dend == - end_match_1' while the restored d is in string2. - For example, the pattern `x.*y.*z' against the - strings `x-' and `y-z-', if the two strings are - not consecutive in memory. */ - DEBUG_PRINT1 ("Restoring best registers.\n"); - - d = match_end; - dend = ((d >= string1 && d <= end1) - ? end_match_1 : end_match_2); - - for (mcnt = 1; mcnt < num_regs; mcnt++) - { - regstart[mcnt] = best_regstart[mcnt]; - regend[mcnt] = best_regend[mcnt]; - } - } - } /* d != end_match_2 */ - - DEBUG_PRINT1 ("Accepting match.\n"); - - /* If caller wants register contents data back, do it. */ - if (regs && !bufp->no_sub) - { - /* Have the register data arrays been allocated? */ - if (bufp->regs_allocated == REGS_UNALLOCATED) - { /* No. So allocate them with malloc. We need one - extra element beyond `num_regs' for the `-1' marker - GNU code uses. */ - regs->num_regs = MAX (RE_NREGS, num_regs + 1); - regs->start = TALLOC (regs->num_regs, regoff_t); - regs->end = TALLOC (regs->num_regs, regoff_t); - if (regs->start == NULL || regs->end == NULL) - return -2; - bufp->regs_allocated = REGS_REALLOCATE; - } - else if (bufp->regs_allocated == REGS_REALLOCATE) - { /* Yes. If we need more elements than were already - allocated, reallocate them. If we need fewer, just - leave it alone. */ - if (regs->num_regs < num_regs + 1) - { - regs->num_regs = num_regs + 1; - RETALLOC (regs->start, regs->num_regs, regoff_t); - RETALLOC (regs->end, regs->num_regs, regoff_t); - if (regs->start == NULL || regs->end == NULL) - return -2; - } - } - else - assert (bufp->regs_allocated == REGS_FIXED); - - /* Convert the pointer data in `regstart' and `regend' to - indices. Register zero has to be set differently, - since we haven't kept track of any info for it. */ - if (regs->num_regs > 0) - { - regs->start[0] = pos; - regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1 - : d - string2 + size1); - } - - /* Go through the first `min (num_regs, regs->num_regs)' - registers, since that is all we initialized. */ - for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++) - { - if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) - regs->start[mcnt] = regs->end[mcnt] = -1; - else - { - regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]); - regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]); - } - } - - /* If the regs structure we return has more elements than - were in the pattern, set the extra elements to -1. If - we (re)allocated the registers, this is the case, - because we always allocate enough to have at least one - -1 at the end. */ - for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++) - regs->start[mcnt] = regs->end[mcnt] = -1; - } /* regs && !bufp->no_sub */ - - FREE_VARIABLES (); - DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", - nfailure_points_pushed, nfailure_points_popped, - nfailure_points_pushed - nfailure_points_popped); - DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); - - mcnt = d - pos - (MATCHING_IN_FIRST_STRING - ? string1 - : string2 - size1); - - DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); - - return mcnt; - } - - /* Otherwise match next pattern command. */ -#ifdef SWITCH_ENUM_BUG - switch ((int) ((re_opcode_t) *p++)) -#else - switch ((re_opcode_t) *p++) -#endif - { - /* Ignore these. Used to ignore the n of succeed_n's which - currently have n == 0. */ - case no_op: - DEBUG_PRINT1 ("EXECUTING no_op.\n"); - break; - - - /* Match the next n pattern characters exactly. The following - byte in the pattern defines n, and the n bytes after that - are the characters to match. */ - case exactn: - mcnt = *p++; - DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); - - /* This is written out as an if-else so we don't waste time - testing `translate' inside the loop. */ - if (translate) - { - do - { - PREFETCH (); - if (translate[(unsigned char) *d++] != (char) *p++) - goto fail; - } - while (--mcnt); - } - else - { - do - { - PREFETCH (); - if (*d++ != (char) *p++) goto fail; - } - while (--mcnt); - } - SET_REGS_MATCHED (); - break; - - - /* Match any character except possibly a newline or a null. */ - case anychar: - DEBUG_PRINT1 ("EXECUTING anychar.\n"); - - PREFETCH (); - - if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') - || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) - goto fail; - - SET_REGS_MATCHED (); - DEBUG_PRINT2 (" Matched `%d'.\n", *d); - d++; - break; - - - case charset: - case charset_not: - { - register unsigned char c; - boolean not = (re_opcode_t) *(p - 1) == charset_not; - - DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); - - PREFETCH (); - c = TRANSLATE (*d); /* The character to match. */ - - /* Cast to `unsigned' instead of `unsigned char' in case the - bit list is a full 32 bytes long. */ - if (c < (unsigned) (*p * BYTEWIDTH) - && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; - - p += 1 + *p; - - if (!not) goto fail; - - SET_REGS_MATCHED (); - d++; - break; - } - - - /* The beginning of a group is represented by start_memory. - The arguments are the register number in the next byte, and the - number of groups inner to this one in the next. The text - matched within the group is recorded (in the internal - registers data structure) under the register number. */ - case start_memory: - DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); - - /* Find out if this group can match the empty string. */ - p1 = p; /* To send to group_match_null_string_p. */ - - if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) - REG_MATCH_NULL_STRING_P (reg_info[*p]) - = group_match_null_string_p (&p1, pend, reg_info); - - /* Save the position in the string where we were the last time - we were at this open-group operator in case the group is - operated upon by a repetition operator, e.g., with `(a*)*b' - against `ab'; then we want to ignore where we are now in - the string in case this attempt to match fails. */ - old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) - ? REG_UNSET (regstart[*p]) ? d : regstart[*p] - : regstart[*p]; - DEBUG_PRINT2 (" old_regstart: %d\n", - POINTER_TO_OFFSET (old_regstart[*p])); - - regstart[*p] = d; - DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); - - IS_ACTIVE (reg_info[*p]) = 1; - MATCHED_SOMETHING (reg_info[*p]) = 0; - - /* This is the new highest active register. */ - highest_active_reg = *p; - - /* If nothing was active before, this is the new lowest active - register. */ - if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) - lowest_active_reg = *p; - - /* Move past the register number and inner group count. */ - p += 2; - break; - - - /* The stop_memory opcode represents the end of a group. Its - arguments are the same as start_memory's: the register - number, and the number of inner groups. */ - case stop_memory: - DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); - - /* We need to save the string position the last time we were at - this close-group operator in case the group is operated - upon by a repetition operator, e.g., with `((a*)*(b*)*)*' - against `aba'; then we want to ignore where we are now in - the string in case this attempt to match fails. */ - old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) - ? REG_UNSET (regend[*p]) ? d : regend[*p] - : regend[*p]; - DEBUG_PRINT2 (" old_regend: %d\n", - POINTER_TO_OFFSET (old_regend[*p])); - - regend[*p] = d; - DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); - - /* This register isn't active anymore. */ - IS_ACTIVE (reg_info[*p]) = 0; - - /* If this was the only register active, nothing is active - anymore. */ - if (lowest_active_reg == highest_active_reg) - { - lowest_active_reg = NO_LOWEST_ACTIVE_REG; - highest_active_reg = NO_HIGHEST_ACTIVE_REG; - } - else - { /* We must scan for the new highest active register, since - it isn't necessarily one less than now: consider - (a(b)c(d(e)f)g). When group 3 ends, after the f), the - new highest active register is 1. */ - unsigned char r = *p - 1; - while (r > 0 && !IS_ACTIVE (reg_info[r])) - r--; - - /* If we end up at register zero, that means that we saved - the registers as the result of an `on_failure_jump', not - a `start_memory', and we jumped to past the innermost - `stop_memory'. For example, in ((.)*) we save - registers 1 and 2 as a result of the *, but when we pop - back to the second ), we are at the stop_memory 1. - Thus, nothing is active. */ - if (r == 0) - { - lowest_active_reg = NO_LOWEST_ACTIVE_REG; - highest_active_reg = NO_HIGHEST_ACTIVE_REG; - } - else - highest_active_reg = r; - } - - /* If just failed to match something this time around with a - group that's operated on by a repetition operator, try to - force exit from the ``loop'', and restore the register - information for this group that we had before trying this - last match. */ - if ((!MATCHED_SOMETHING (reg_info[*p]) - || (re_opcode_t) p[-3] == start_memory) - && (p + 2) < pend) - { - boolean is_a_jump_n = false; - - p1 = p + 2; - mcnt = 0; - switch ((re_opcode_t) *p1++) - { - case jump_n: - is_a_jump_n = true; - case pop_failure_jump: - case maybe_pop_jump: - case jump: - case dummy_failure_jump: - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - if (is_a_jump_n) - p1 += 2; - break; - - default: - /* do nothing */ ; - } - p1 += mcnt; - - /* If the next operation is a jump backwards in the pattern - to an on_failure_jump right before the start_memory - corresponding to this stop_memory, exit from the loop - by forcing a failure after pushing on the stack the - on_failure_jump's jump in the pattern, and d. */ - if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump - && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) - { - /* If this group ever matched anything, then restore - what its registers were before trying this last - failed match, e.g., with `(a*)*b' against `ab' for - regstart[1], and, e.g., with `((a*)*(b*)*)*' - against `aba' for regend[3]. - - Also restore the registers for inner groups for, - e.g., `((a*)(b*))*' against `aba' (register 3 would - otherwise get trashed). */ - - if (EVER_MATCHED_SOMETHING (reg_info[*p])) - { - unsigned r; - - EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; - - /* Restore this and inner groups' (if any) registers. */ - for (r = *p; r < *p + *(p + 1); r++) - { - regstart[r] = old_regstart[r]; - - /* xx why this test? */ - if ((int) old_regend[r] >= (int) regstart[r]) - regend[r] = old_regend[r]; - } - } - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - PUSH_FAILURE_POINT (p1 + mcnt, d, -2); - - goto fail; - } - } - - /* Move past the register number and the inner group count. */ - p += 2; - break; - - - /* \<digit> has been turned into a `duplicate' command which is - followed by the numeric value of <digit> as the register number. */ - case duplicate: - { - register const char *d2, *dend2; - int regno = *p++; /* Get which register to match against. */ - DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); - - /* Can't back reference a group which we've never matched. */ - if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) - goto fail; - - /* Where in input to try to start matching. */ - d2 = regstart[regno]; - - /* Where to stop matching; if both the place to start and - the place to stop matching are in the same string, then - set to the place to stop, otherwise, for now have to use - the end of the first string. */ - - dend2 = ((FIRST_STRING_P (regstart[regno]) - == FIRST_STRING_P (regend[regno])) - ? regend[regno] : end_match_1); - for (;;) - { - /* If necessary, advance to next segment in register - contents. */ - while (d2 == dend2) - { - if (dend2 == end_match_2) break; - if (dend2 == regend[regno]) break; - - /* End of string1 => advance to string2. */ - d2 = string2; - dend2 = regend[regno]; - } - /* At end of register contents => success */ - if (d2 == dend2) break; - - /* If necessary, advance to next segment in data. */ - PREFETCH (); - - /* How many characters left in this segment to match. */ - mcnt = dend - d; - - /* Want how many consecutive characters we can match in - one shot, so, if necessary, adjust the count. */ - if (mcnt > dend2 - d2) - mcnt = dend2 - d2; - - /* Compare that many; failure if mismatch, else move - past them. */ - if (translate - ? bcmp_translate (d, d2, mcnt, translate) - : bcmp (d, d2, mcnt)) - goto fail; - d += mcnt, d2 += mcnt; - } - } - break; - - - /* begline matches the empty string at the beginning of the string - (unless `not_bol' is set in `bufp'), and, if - `newline_anchor' is set, after newlines. */ - case begline: - DEBUG_PRINT1 ("EXECUTING begline.\n"); - - if (AT_STRINGS_BEG (d)) - { - if (!bufp->not_bol) break; - } - else if (d[-1] == '\n' && bufp->newline_anchor) - { - break; - } - /* In all other cases, we fail. */ - goto fail; - - - /* endline is the dual of begline. */ - case endline: - DEBUG_PRINT1 ("EXECUTING endline.\n"); - - if (AT_STRINGS_END (d)) - { - if (!bufp->not_eol) break; - } - - /* We have to ``prefetch'' the next character. */ - else if ((d == end1 ? *string2 : *d) == '\n' - && bufp->newline_anchor) - { - break; - } - goto fail; - - - /* Match at the very beginning of the data. */ - case begbuf: - DEBUG_PRINT1 ("EXECUTING begbuf.\n"); - if (AT_STRINGS_BEG (d)) - break; - goto fail; - - - /* Match at the very end of the data. */ - case endbuf: - DEBUG_PRINT1 ("EXECUTING endbuf.\n"); - if (AT_STRINGS_END (d)) - break; - goto fail; - - - /* on_failure_keep_string_jump is used to optimize `.*\n'. It - pushes NULL as the value for the string on the stack. Then - `pop_failure_point' will keep the current value for the - string, instead of restoring it. To see why, consider - matching `foo\nbar' against `.*\n'. The .* matches the foo; - then the . fails against the \n. But the next thing we want - to do is match the \n against the \n; if we restored the - string value, we would be back at the foo. - - Because this is used only in specific cases, we don't need to - check all the things that `on_failure_jump' does, to make - sure the right things get saved on the stack. Hence we don't - share its code. The only reason to push anything on the - stack at all is that otherwise we would have to change - `anychar's code to do something besides goto fail in this - case; that seems worse than this. */ - case on_failure_keep_string_jump: - DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); - - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); - - PUSH_FAILURE_POINT (p + mcnt, NULL, -2); - break; - - - /* Uses of on_failure_jump: - - Each alternative starts with an on_failure_jump that points - to the beginning of the next alternative. Each alternative - except the last ends with a jump that in effect jumps past - the rest of the alternatives. (They really jump to the - ending jump of the following alternative, because tensioning - these jumps is a hassle.) - - Repeats start with an on_failure_jump that points past both - the repetition text and either the following jump or - pop_failure_jump back to this on_failure_jump. */ - case on_failure_jump: - on_failure: - DEBUG_PRINT1 ("EXECUTING on_failure_jump"); - - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); - - /* If this on_failure_jump comes right before a group (i.e., - the original * applied to a group), save the information - for that group and all inner ones, so that if we fail back - to this point, the group's information will be correct. - For example, in \(a*\)*\1, we need the preceding group, - and in \(\(a*\)b*\)\2, we need the inner group. */ - - /* We can't use `p' to check ahead because we push - a failure point to `p + mcnt' after we do this. */ - p1 = p; - - /* We need to skip no_op's before we look for the - start_memory in case this on_failure_jump is happening as - the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 - against aba. */ - while (p1 < pend && (re_opcode_t) *p1 == no_op) - p1++; - - if (p1 < pend && (re_opcode_t) *p1 == start_memory) - { - /* We have a new highest active register now. This will - get reset at the start_memory we are about to get to, - but we will have saved all the registers relevant to - this repetition op, as described above. */ - highest_active_reg = *(p1 + 1) + *(p1 + 2); - if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) - lowest_active_reg = *(p1 + 1); - } - - DEBUG_PRINT1 (":\n"); - PUSH_FAILURE_POINT (p + mcnt, d, -2); - break; - - - /* A smart repeat ends with `maybe_pop_jump'. - We change it to either `pop_failure_jump' or `jump'. */ - case maybe_pop_jump: - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); - { - register unsigned char *p2 = p; - - /* Compare the beginning of the repeat with what in the - pattern follows its end. If we can establish that there - is nothing that they would both match, i.e., that we - would have to backtrack because of (as in, e.g., `a*a') - then we can change to pop_failure_jump, because we'll - never have to backtrack. - - This is not true in the case of alternatives: in - `(a|ab)*' we do need to backtrack to the `ab' alternative - (e.g., if the string was `ab'). But instead of trying to - detect that here, the alternative has put on a dummy - failure point which is what we will end up popping. */ - - /* Skip over open/close-group commands. */ - while (p2 + 2 < pend - && ((re_opcode_t) *p2 == stop_memory - || (re_opcode_t) *p2 == start_memory)) - p2 += 3; /* Skip over args, too. */ - - /* If we're at the end of the pattern, we can change. */ - if (p2 == pend) - { - /* Consider what happens when matching ":\(.*\)" - against ":/". I don't really understand this code - yet. */ - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT1 - (" End of pattern: change to `pop_failure_jump'.\n"); - } - - else if ((re_opcode_t) *p2 == exactn - || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) - { - register unsigned char c - = *p2 == (unsigned char) endline ? '\n' : p2[2]; - p1 = p + mcnt; - - /* p1[0] ... p1[2] are the `on_failure_jump' corresponding - to the `maybe_finalize_jump' of this case. Examine what - follows. */ - if ((re_opcode_t) p1[3] == exactn && p1[5] != c) - { - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", - c, p1[5]); - } - - else if ((re_opcode_t) p1[3] == charset - || (re_opcode_t) p1[3] == charset_not) - { - int not = (re_opcode_t) p1[3] == charset_not; - - if (c < (unsigned char) (p1[4] * BYTEWIDTH) - && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; - - /* `not' is equal to 1 if c would match, which means - that we can't change to pop_failure_jump. */ - if (!not) - { - p[-3] = (unsigned char) pop_failure_jump; - DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); - } - } - } - } - p -= 2; /* Point at relative address again. */ - if ((re_opcode_t) p[-1] != pop_failure_jump) - { - p[-1] = (unsigned char) jump; - DEBUG_PRINT1 (" Match => jump.\n"); - goto unconditional_jump; - } - /* Note fall through. */ - - - /* The end of a simple repeat has a pop_failure_jump back to - its matching on_failure_jump, where the latter will push a - failure point. The pop_failure_jump takes off failure - points put on by this pop_failure_jump's matching - on_failure_jump; we got through the pattern to here from the - matching on_failure_jump, so didn't fail. */ - case pop_failure_jump: - { - /* We need to pass separate storage for the lowest and - highest registers, even though we don't care about the - actual values. Otherwise, we will restore only one - register from the stack, since lowest will == highest in - `pop_failure_point'. */ - unsigned dummy_low_reg, dummy_high_reg; - unsigned char *pdummy; - const char *sdummy; - - DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); - POP_FAILURE_POINT (sdummy, pdummy, - dummy_low_reg, dummy_high_reg, - reg_dummy, reg_dummy, reg_info_dummy); - } - /* Note fall through. */ - - - /* Unconditionally jump (without popping any failure points). */ - case jump: - unconditional_jump: - EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ - DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); - p += mcnt; /* Do the jump. */ - DEBUG_PRINT2 ("(to 0x%x).\n", p); - break; - - - /* We need this opcode so we can detect where alternatives end - in `group_match_null_string_p' et al. */ - case jump_past_alt: - DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); - goto unconditional_jump; - - - /* Normally, the on_failure_jump pushes a failure point, which - then gets popped at pop_failure_jump. We will end up at - pop_failure_jump, also, and with a pattern of, say, `a+', we - are skipping over the on_failure_jump, so we have to push - something meaningless for pop_failure_jump to pop. */ - case dummy_failure_jump: - DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); - /* It doesn't matter what we push for the string here. What - the code at `fail' tests is the value for the pattern. */ - PUSH_FAILURE_POINT (0, 0, -2); - goto unconditional_jump; - - - /* At the end of an alternative, we need to push a dummy failure - point in case we are followed by a `pop_failure_jump', because - we don't want the failure point for the alternative to be - popped. For example, matching `(a|ab)*' against `aab' - requires that we match the `ab' alternative. */ - case push_dummy_failure: - DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); - /* See comments just above at `dummy_failure_jump' about the - two zeroes. */ - PUSH_FAILURE_POINT (0, 0, -2); - break; - - /* Have to succeed matching what follows at least n times. - After that, handle like `on_failure_jump'. */ - case succeed_n: - EXTRACT_NUMBER (mcnt, p + 2); - DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); - - assert (mcnt >= 0); - /* Originally, this is how many times we HAVE to succeed. */ - if (mcnt > 0) - { - mcnt--; - p += 2; - STORE_NUMBER_AND_INCR (p, mcnt); - DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt); - } - else if (mcnt == 0) - { - DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); - p[2] = (unsigned char) no_op; - p[3] = (unsigned char) no_op; - goto on_failure; - } - break; - - case jump_n: - EXTRACT_NUMBER (mcnt, p + 2); - DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); - - /* Originally, this is how many times we CAN jump. */ - if (mcnt) - { - mcnt--; - STORE_NUMBER (p + 2, mcnt); - goto unconditional_jump; - } - /* If don't have to jump any more, skip over the rest of command. */ - else - p += 4; - break; - - case set_number_at: - { - DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); - - EXTRACT_NUMBER_AND_INCR (mcnt, p); - p1 = p + mcnt; - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); - STORE_NUMBER (p1, mcnt); - break; - } - - case wordbound: - DEBUG_PRINT1 ("EXECUTING wordbound.\n"); - if (AT_WORD_BOUNDARY (d)) - break; - goto fail; - - case notwordbound: - DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); - if (AT_WORD_BOUNDARY (d)) - goto fail; - break; - - case wordbeg: - DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); - if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) - break; - goto fail; - - case wordend: - DEBUG_PRINT1 ("EXECUTING wordend.\n"); - if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) - && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) - break; - goto fail; - -#ifdef emacs -#ifdef emacs19 - case before_dot: - DEBUG_PRINT1 ("EXECUTING before_dot.\n"); - if (PTR_CHAR_POS ((unsigned char *) d) >= point) - goto fail; - break; - - case at_dot: - DEBUG_PRINT1 ("EXECUTING at_dot.\n"); - if (PTR_CHAR_POS ((unsigned char *) d) != point) - goto fail; - break; - - case after_dot: - DEBUG_PRINT1 ("EXECUTING after_dot.\n"); - if (PTR_CHAR_POS ((unsigned char *) d) <= point) - goto fail; - break; -#else /* not emacs19 */ - case at_dot: - DEBUG_PRINT1 ("EXECUTING at_dot.\n"); - if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point) - goto fail; - break; -#endif /* not emacs19 */ - - case syntaxspec: - DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); - mcnt = *p++; - goto matchsyntax; - - case wordchar: - DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); - mcnt = (int) Sword; - matchsyntax: - PREFETCH (); - if (SYNTAX (*d++) != (enum syntaxcode) mcnt) - goto fail; - SET_REGS_MATCHED (); - break; - - case notsyntaxspec: - DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); - mcnt = *p++; - goto matchnotsyntax; - - case notwordchar: - DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); - mcnt = (int) Sword; - matchnotsyntax: - PREFETCH (); - if (SYNTAX (*d++) == (enum syntaxcode) mcnt) - goto fail; - SET_REGS_MATCHED (); - break; - -#else /* not emacs */ - case wordchar: - DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); - PREFETCH (); - if (!WORDCHAR_P (d)) - goto fail; - SET_REGS_MATCHED (); - d++; - break; - - case notwordchar: - DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); - PREFETCH (); - if (WORDCHAR_P (d)) - goto fail; - SET_REGS_MATCHED (); - d++; - break; -#endif /* not emacs */ - - default: - abort (); - } - continue; /* Successfully executed one pattern command; keep going. */ - - - /* We goto here if a matching operation fails. */ - fail: - if (!FAIL_STACK_EMPTY ()) - { /* A restart point is known. Restore to that state. */ - DEBUG_PRINT1 ("\nFAIL:\n"); - POP_FAILURE_POINT (d, p, - lowest_active_reg, highest_active_reg, - regstart, regend, reg_info); - - /* If this failure point is a dummy, try the next one. */ - if (!p) - goto fail; - - /* If we failed to the end of the pattern, don't examine *p. */ - assert (p <= pend); - if (p < pend) - { - boolean is_a_jump_n = false; - - /* If failed to a backwards jump that's part of a repetition - loop, need to pop this failure point and use the next one. */ - switch ((re_opcode_t) *p) - { - case jump_n: - is_a_jump_n = true; - case maybe_pop_jump: - case pop_failure_jump: - case jump: - p1 = p + 1; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - p1 += mcnt; - - if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) - || (!is_a_jump_n - && (re_opcode_t) *p1 == on_failure_jump)) - goto fail; - break; - default: - /* do nothing */ ; - } - } - - if (d >= string1 && d <= end1) - dend = end_match_1; - } - else - break; /* Matching at this starting point really fails. */ - } /* for (;;) */ - - if (best_regs_set) - goto restore_best_regs; - - FREE_VARIABLES (); - - return -1; /* Failure to match. */ -} /* re_match_2 */ - -/* Subroutine definitions for re_match_2. */ - - -/* We are passed P pointing to a register number after a start_memory. - - Return true if the pattern up to the corresponding stop_memory can - match the empty string, and false otherwise. - - If we find the matching stop_memory, sets P to point to one past its number. - Otherwise, sets P to an undefined byte less than or equal to END. - - We don't handle duplicates properly (yet). */ - -static boolean -group_match_null_string_p (p, end, reg_info) - unsigned char **p, *end; - register_info_type *reg_info; -{ - int mcnt; - /* Point to after the args to the start_memory. */ - unsigned char *p1 = *p + 2; - - while (p1 < end) - { - /* Skip over opcodes that can match nothing, and return true or - false, as appropriate, when we get to one that can't, or to the - matching stop_memory. */ - - switch ((re_opcode_t) *p1) - { - /* Could be either a loop or a series of alternatives. */ - case on_failure_jump: - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - - /* If the next operation is not a jump backwards in the - pattern. */ - - if (mcnt >= 0) - { - /* Go through the on_failure_jumps of the alternatives, - seeing if any of the alternatives cannot match nothing. - The last alternative starts with only a jump, - whereas the rest start with on_failure_jump and end - with a jump, e.g., here is the pattern for `a|b|c': - - /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 - /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 - /exactn/1/c - - So, we have to first go through the first (n-1) - alternatives and then deal with the last one separately. */ - - - /* Deal with the first (n-1) alternatives, which start - with an on_failure_jump (see above) that jumps to right - past a jump_past_alt. */ - - while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) - { - /* `mcnt' holds how many bytes long the alternative - is, including the ending `jump_past_alt' and - its number. */ - - if (!alt_match_null_string_p (p1, p1 + mcnt - 3, - reg_info)) - return false; - - /* Move to right after this alternative, including the - jump_past_alt. */ - p1 += mcnt; - - /* Break if it's the beginning of an n-th alternative - that doesn't begin with an on_failure_jump. */ - if ((re_opcode_t) *p1 != on_failure_jump) - break; - - /* Still have to check that it's not an n-th - alternative that starts with an on_failure_jump. */ - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) - { - /* Get to the beginning of the n-th alternative. */ - p1 -= 3; - break; - } - } - - /* Deal with the last alternative: go back and get number - of the `jump_past_alt' just before it. `mcnt' contains - the length of the alternative. */ - EXTRACT_NUMBER (mcnt, p1 - 2); - - if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) - return false; - - p1 += mcnt; /* Get past the n-th alternative. */ - } /* if mcnt > 0 */ - break; - - - case stop_memory: - assert (p1[1] == **p); - *p = p1 + 2; - return true; - - - default: - if (!common_op_match_null_string_p (&p1, end, reg_info)) - return false; - } - } /* while p1 < end */ - - return false; -} /* group_match_null_string_p */ - - -/* Similar to group_match_null_string_p, but doesn't deal with alternatives: - It expects P to be the first byte of a single alternative and END one - byte past the last. The alternative can contain groups. */ - -static boolean -alt_match_null_string_p (p, end, reg_info) - unsigned char *p, *end; - register_info_type *reg_info; -{ - int mcnt; - unsigned char *p1 = p; - - while (p1 < end) - { - /* Skip over opcodes that can match nothing, and break when we get - to one that can't. */ - - switch ((re_opcode_t) *p1) - { - /* It's a loop. */ - case on_failure_jump: - p1++; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - p1 += mcnt; - break; - - default: - if (!common_op_match_null_string_p (&p1, end, reg_info)) - return false; - } - } /* while p1 < end */ - - return true; -} /* alt_match_null_string_p */ - - -/* Deals with the ops common to group_match_null_string_p and - alt_match_null_string_p. - - Sets P to one after the op and its arguments, if any. */ - -static boolean -common_op_match_null_string_p (p, end, reg_info) - unsigned char **p, *end; - register_info_type *reg_info; -{ - int mcnt; - boolean ret; - int reg_no; - unsigned char *p1 = *p; - - switch ((re_opcode_t) *p1++) - { - case no_op: - case begline: - case endline: - case begbuf: - case endbuf: - case wordbeg: - case wordend: - case wordbound: - case notwordbound: -#ifdef emacs - case before_dot: - case at_dot: - case after_dot: -#endif - break; - - case start_memory: - reg_no = *p1; - assert (reg_no > 0 && reg_no <= MAX_REGNUM); - ret = group_match_null_string_p (&p1, end, reg_info); - - /* Have to set this here in case we're checking a group which - contains a group and a back reference to it. */ - - if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) - REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; - - if (!ret) - return false; - break; - - /* If this is an optimized succeed_n for zero times, make the jump. */ - case jump: - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - if (mcnt >= 0) - p1 += mcnt; - else - return false; - break; - - case succeed_n: - /* Get to the number of times to succeed. */ - p1 += 2; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - - if (mcnt == 0) - { - p1 -= 4; - EXTRACT_NUMBER_AND_INCR (mcnt, p1); - p1 += mcnt; - } - else - return false; - break; - - case duplicate: - if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) - return false; - break; - - case set_number_at: - p1 += 4; - - default: - /* All other opcodes mean we cannot match the empty string. */ - return false; - } - - *p = p1; - return true; -} /* common_op_match_null_string_p */ - - -/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN - bytes; nonzero otherwise. */ - -static int -bcmp_translate (s1, s2, len, translate) - unsigned char *s1, *s2; - register int len; - char *translate; -{ - register unsigned char *p1 = s1, *p2 = s2; - while (len) - { - if (translate[*p1++] != translate[*p2++]) return 1; - len--; - } - return 0; -} - -/* Entry points for GNU code. */ - -/* re_compile_pattern is the GNU regular expression compiler: it - compiles PATTERN (of length SIZE) and puts the result in BUFP. - Returns 0 if the pattern was valid, otherwise an error string. - - Assumes the `allocated' (and perhaps `buffer') and `translate' fields - are set in BUFP on entry. - - We call regex_compile to do the actual compilation. */ - -const char * -re_compile_pattern (pattern, length, bufp) - const char *pattern; - int length; - struct re_pattern_buffer *bufp; -{ - reg_errcode_t ret; - - /* GNU code is written to assume at least RE_NREGS registers will be set - (and at least one extra will be -1). */ - bufp->regs_allocated = REGS_UNALLOCATED; - - /* And GNU code determines whether or not to get register information - by passing null for the REGS argument to re_match, etc., not by - setting no_sub. */ - bufp->no_sub = 0; - - /* Match anchors at newline. */ - bufp->newline_anchor = 1; - - ret = regex_compile (pattern, length, re_syntax_options, bufp); - - return re_error_msg[(int) ret]; -} - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them if this is an Emacs or POSIX compilation. */ - -#if !defined (emacs) && !defined (_POSIX_SOURCE) - -/* BSD has one and only one pattern buffer. */ -static struct re_pattern_buffer re_comp_buf; - -char * -re_comp (s) - const char *s; -{ - reg_errcode_t ret; - - if (!s) - { - if (!re_comp_buf.buffer) - return "No previous regular expression"; - return 0; - } - - if (!re_comp_buf.buffer) - { - re_comp_buf.buffer = (unsigned char *) malloc (200); - if (re_comp_buf.buffer == NULL) - return "Memory exhausted"; - re_comp_buf.allocated = 200; - - re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); - if (re_comp_buf.fastmap == NULL) - return "Memory exhausted"; - } - - /* Since `re_exec' always passes NULL for the `regs' argument, we - don't need to initialize the pattern buffer fields which affect it. */ - - /* Match anchors at newlines. */ - re_comp_buf.newline_anchor = 1; - - ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); - - /* Yes, we're discarding `const' here. */ - return (char *) re_error_msg[(int) ret]; -} - - -int -re_exec (s) - const char *s; -{ - const int len = strlen (s); - return - 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); -} -#endif /* not emacs and not _POSIX_SOURCE */ - -/* POSIX.2 functions. Don't define these for Emacs. */ - -#ifndef emacs - -/* regcomp takes a regular expression as a string and compiles it. - - PREG is a regex_t *. We do not expect any fields to be initialized, - since POSIX says we shouldn't. Thus, we set - - `buffer' to the compiled pattern; - `used' to the length of the compiled pattern; - `syntax' to RE_SYNTAX_POSIX_EXTENDED if the - REG_EXTENDED bit in CFLAGS is set; otherwise, to - RE_SYNTAX_POSIX_BASIC; - `newline_anchor' to REG_NEWLINE being set in CFLAGS; - `fastmap' and `fastmap_accurate' to zero; - `re_nsub' to the number of subexpressions in PATTERN. - - PATTERN is the address of the pattern string. - - CFLAGS is a series of bits which affect compilation. - - If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we - use POSIX basic syntax. - - If REG_NEWLINE is set, then . and [^...] don't match newline. - Also, regexec will try a match beginning after every newline. - - If REG_ICASE is set, then we considers upper- and lowercase - versions of letters to be equivalent when matching. - - If REG_NOSUB is set, then when PREG is passed to regexec, that - routine will report only success or failure, and nothing about the - registers. - - It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for - the return codes and their meanings.) */ - -int -regcomp (preg, pattern, cflags) - regex_t *preg; - const char *pattern; - int cflags; -{ - reg_errcode_t ret; - unsigned syntax - = (cflags & REG_EXTENDED) ? - RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; - - /* regex_compile will allocate the space for the compiled pattern. */ - preg->buffer = 0; - preg->allocated = 0; - - /* Don't bother to use a fastmap when searching. This simplifies the - REG_NEWLINE case: if we used a fastmap, we'd have to put all the - characters after newlines into the fastmap. This way, we just try - every character. */ - preg->fastmap = 0; - - if (cflags & REG_ICASE) - { - unsigned i; - - preg->translate = (char *) malloc (CHAR_SET_SIZE); - if (preg->translate == NULL) - return (int) REG_ESPACE; - - /* Map uppercase characters to corresponding lowercase ones. */ - for (i = 0; i < CHAR_SET_SIZE; i++) - preg->translate[i] = ISUPPER (i) ? tolower (i) : i; - } - else - preg->translate = NULL; - - /* If REG_NEWLINE is set, newlines are treated differently. */ - if (cflags & REG_NEWLINE) - { /* REG_NEWLINE implies neither . nor [^...] match newline. */ - syntax &= ~RE_DOT_NEWLINE; - syntax |= RE_HAT_LISTS_NOT_NEWLINE; - /* It also changes the matching behavior. */ - preg->newline_anchor = 1; - } - else - preg->newline_anchor = 0; - - preg->no_sub = !!(cflags & REG_NOSUB); - - /* POSIX says a null character in the pattern terminates it, so we - can use strlen here in compiling the pattern. */ - ret = regex_compile (pattern, strlen (pattern), syntax, preg); - - /* POSIX doesn't distinguish between an unmatched open-group and an - unmatched close-group: both are REG_EPAREN. */ - if (ret == REG_ERPAREN) ret = REG_EPAREN; - - return (int) ret; -} - - -/* regexec searches for a given pattern, specified by PREG, in the - string STRING. - - If NMATCH is zero or REG_NOSUB was set in the cflags argument to - `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at - least NMATCH elements, and we set them to the offsets of the - corresponding matched substrings. - - EFLAGS specifies `execution flags' which affect matching: if - REG_NOTBOL is set, then ^ does not match at the beginning of the - string; if REG_NOTEOL is set, then $ does not match at the end. - - We return 0 if we find a match and REG_NOMATCH if not. */ - -int -regexec (preg, string, nmatch, pmatch, eflags) - const regex_t *preg; - const char *string; - size_t nmatch; - regmatch_t pmatch[]; - int eflags; -{ - int ret; - struct re_registers regs; - regex_t private_preg; - int len = strlen (string); - boolean want_reg_info = !preg->no_sub && nmatch > 0; - - private_preg = *preg; - - private_preg.not_bol = !!(eflags & REG_NOTBOL); - private_preg.not_eol = !!(eflags & REG_NOTEOL); - - /* The user has told us exactly how many registers to return - information about, via `nmatch'. We have to pass that on to the - matching routines. */ - private_preg.regs_allocated = REGS_FIXED; - - if (want_reg_info) - { - regs.num_regs = nmatch; - regs.start = TALLOC (nmatch, regoff_t); - regs.end = TALLOC (nmatch, regoff_t); - if (regs.start == NULL || regs.end == NULL) - return (int) REG_NOMATCH; - } - - /* Perform the searching operation. */ - ret = re_search (&private_preg, string, len, - /* start: */ 0, /* range: */ len, - want_reg_info ? ®s : (struct re_registers *) 0); - - /* Copy the register information to the POSIX structure. */ - if (want_reg_info) - { - if (ret >= 0) - { - unsigned r; - - for (r = 0; r < nmatch; r++) - { - pmatch[r].rm_so = regs.start[r]; - pmatch[r].rm_eo = regs.end[r]; - } - } - - /* If we needed the temporary register info, free the space now. */ - free (regs.start); - free (regs.end); - } - - /* We want zero return to mean success, unlike `re_search'. */ - return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; -} - - -/* Returns a message corresponding to an error code, ERRCODE, returned - from either regcomp or regexec. We don't use PREG here. */ - -size_t -regerror (errcode, preg, errbuf, errbuf_size) - int errcode; - const regex_t *preg; - char *errbuf; - size_t errbuf_size; -{ - const char *msg; - size_t msg_size; - - if (errcode < 0 - || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0]))) - /* Only error codes returned by the rest of the code should be passed - to this routine. If we are given anything else, or if other regex - code generates an invalid error code, then the program has a bug. - Dump core so we can fix it. */ - abort (); - - msg = re_error_msg[errcode]; - - /* POSIX doesn't require that we do anything in this case, but why - not be nice. */ - if (! msg) - msg = "Success"; - - msg_size = strlen (msg) + 1; /* Includes the null. */ - - if (errbuf_size != 0) - { - if (msg_size > errbuf_size) - { - strncpy (errbuf, msg, errbuf_size - 1); - errbuf[errbuf_size - 1] = 0; - } - else - strcpy (errbuf, msg); - } - - return msg_size; -} - - -/* Free dynamically allocated space used by PREG. */ - -void -regfree (preg) - regex_t *preg; -{ - if (preg->buffer != NULL) - free (preg->buffer); - preg->buffer = NULL; - - preg->allocated = 0; - preg->used = 0; - - if (preg->fastmap != NULL) - free (preg->fastmap); - preg->fastmap = NULL; - preg->fastmap_accurate = 0; - - if (preg->translate != NULL) - free (preg->translate); - preg->translate = NULL; -} - -#endif /* not emacs */ - -/* -Local variables: -make-backup-files: t -version-control: t -trim-versions-without-asking: nil -End: -*/ diff --git a/gnu/usr.bin/cvs/lib/y.tab.h b/gnu/usr.bin/cvs/lib/y.tab.h deleted file mode 100644 index 4a541d2..0000000 --- a/gnu/usr.bin/cvs/lib/y.tab.h +++ /dev/null @@ -1,18 +0,0 @@ -#define tAGO 257 -#define tDAY 258 -#define tDAYZONE 259 -#define tID 260 -#define tMERIDIAN 261 -#define tMINUTE_UNIT 262 -#define tMONTH 263 -#define tMONTH_UNIT 264 -#define tSEC_UNIT 265 -#define tSNUMBER 266 -#define tUNUMBER 267 -#define tZONE 268 -#define tDST 269 -typedef union { - time_t Number; - enum _MERIDIAN Meridian; -} YYSTYPE; -extern YYSTYPE yylval; diff --git a/gnu/usr.bin/cvs/mkmodules/xxx b/gnu/usr.bin/cvs/mkmodules/xxx deleted file mode 100644 index f0dd87d..0000000 --- a/gnu/usr.bin/cvs/mkmodules/xxx +++ /dev/null @@ -1,5320 +0,0 @@ -# 1 "/usr/src/gnu/cvs/mkmodules/mkmodules.c" - - - - - - - - - - - - - -# 1 "/usr/include/sys/syslimits.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 14 "/usr/src/gnu/cvs/mkmodules/mkmodules.c" 2 - -# 1 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 1 - - -# 1 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 1 - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/types.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -typedef unsigned char u_char; -typedef unsigned short u_short; -typedef unsigned int u_int; -typedef unsigned long u_long; -typedef unsigned short ushort; - -typedef char * caddr_t; -typedef long daddr_t; -typedef short dev_t; -typedef u_long ino_t; -typedef long off_t; -typedef u_short nlink_t; -typedef long swblk_t; -typedef long segsz_t; -typedef u_short uid_t; -typedef u_short gid_t; -typedef short pid_t; -typedef u_short mode_t; -typedef u_long fixpt_t; - - -typedef struct _uquad { u_long val[2]; } u_quad; -typedef struct _quad { long val[2]; } quad; -typedef long * qaddr_t; - - - - - - -# 1 "/usr/include/machine/ansi.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 69 "/usr/include/sys/types.h" 2 - - -# 1 "/usr/include/machine/types.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -typedef struct _physadr { - int r[1]; -} *physadr; - -typedef struct label_t { - int val[6]; -} label_t; - -typedef u_long vm_offset_t; -typedef u_long vm_size_t; - - -# 71 "/usr/include/sys/types.h" 2 - - - - -typedef unsigned long clock_t; - - - - -typedef unsigned int size_t; - - - - -typedef long time_t; - - - - - - - - - - - - - - - - -typedef long fd_mask; - - - - - - -typedef struct fd_set { - fd_mask fds_bits[(((256 )+(( (sizeof(fd_mask) * 8 ) )-1))/( (sizeof(fd_mask) * 8 ) )) ]; -} fd_set; - - - - - - -# 132 "/usr/include/sys/types.h" - - - - -# 20 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - -# 1 "/usr/include/sys/stat.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -struct stat -{ - dev_t st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - dev_t st_rdev; - off_t st_size; - time_t st_atime; - long st_spare1; - time_t st_mtime; - long st_spare2; - time_t st_ctime; - long st_spare3; - long st_blksize; - long st_blocks; - u_long st_flags; - u_long st_gen; -}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 76 "/usr/include/sys/cdefs.h" - - - -# 114 "/usr/include/sys/stat.h" 2 - - - -mode_t umask (mode_t) ; -int chmod (const char *, mode_t) ; -int fstat (int, struct stat *) ; -int mkdir (const char *, mode_t) ; -int mkfifo (const char *, mode_t) ; -int stat (const char *, struct stat *) ; - -int fchmod (int, mode_t) ; -int lstat (const char *, struct stat *) ; - - - -# 21 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -off_t lseek (); - - - - - -# 1 "/usr/include/time.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/machine/ansi.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 57 "/usr/include/machine/ansi.h" - -# 39 "/usr/include/time.h" 2 - - - - - - - - - - - - - - - - - - - - - -struct tm { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; - long tm_gmtoff; - char *tm_zone; -}; - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 78 "/usr/include/sys/cdefs.h" - -# 74 "/usr/include/time.h" 2 - - - -char *asctime (const struct tm *) ; -clock_t clock (void) ; -char *ctime (const time_t *) ; -double difftime (time_t, time_t) ; -struct tm *gmtime (const time_t *) ; -struct tm *localtime (const time_t *) ; -time_t mktime (struct tm *) ; -size_t strftime (char *, size_t, const char *, const struct tm *) ; -time_t time (time_t *) ; - - -void tzset (void) ; - - - -char *timezone (int, int) ; -void tzsetwall (void) ; - - - - -# 72 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - - - -# 86 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" - -# 1 "/usr/include/sys/timeb.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -struct timeb { - time_t time; - unsigned short millitm; - short timezone; - short dstflag; -}; -# 87 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - - - - - - - - - - -# 1 "/usr/include/sys/param.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/types.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 135 "/usr/include/sys/types.h" - -# 46 "/usr/include/sys/param.h" 2 - - - - - - - - - - -# 1 "/usr/include/sys/syslimits.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 56 "/usr/include/sys/param.h" 2 - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/signal.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/machine/trap.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 42 "/usr/include/sys/signal.h" 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 78 "/usr/include/sys/cdefs.h" - -# 90 "/usr/include/sys/signal.h" 2 - - - -typedef void (*sig_t) (int) ; - - -typedef void (*__sighandler_t) (int) ; -typedef unsigned int sigset_t; - - -int sigaddset (sigset_t *, int) ; -int sigdelset (sigset_t *, int) ; -int sigemptyset (sigset_t *) ; -int sigfillset (sigset_t *) ; -int sigismember (const sigset_t *, int) ; - - - - - - - - - - - -struct sigaction { - __sighandler_t sa_handler; - sigset_t sa_mask; - int sa_flags; -}; - - - - - - - - - - - - - - - - - - -struct sigvec { - void (*sv_handler)(); - int sv_mask; - int sv_flags; -}; - - - - - - - -struct sigaltstack { - char *ss_base; - int ss_len; - int ss_onstack; -}; - - - - -struct sigstack { - char *ss_sp; - int ss_onstack; -}; - - - - - - - - -struct sigcontext { - int sc_onstack; - int sc_mask; - int sc_sp; - int sc_fp; - int sc_ap; - int sc_pc; - int sc_ps; -}; - - - - - - - - - - - - - - -# 1 "/usr/include/sys/types.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 135 "/usr/include/sys/types.h" - -# 195 "/usr/include/sys/signal.h" 2 - - - - -__sighandler_t signal (int, __sighandler_t) ; -int raise (int) ; - -int kill (pid_t, int) ; -int sigaction (int, const struct sigaction *, struct sigaction *) ; -int sigpending (sigset_t *) ; -int sigprocmask (int, const sigset_t *, sigset_t *) ; -int sigsuspend (const sigset_t *) ; - - -int killpg (pid_t, int) ; -void psignal (unsigned, const char *) ; -int sigblock (int) ; -int siginterrupt (int, int) ; -int sigpause (int) ; -int sigreturn (struct sigcontext *) ; -int sigsetmask (int) ; -int sigstack (const struct sigstack *, struct sigstack *) ; -int sigvec (int, struct sigvec *, struct sigvec *) ; - - - - - -# 79 "/usr/include/sys/param.h" 2 - - - -# 1 "/usr/include/machine/param.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 82 "/usr/include/sys/param.h" 2 - -# 1 "/usr/include/machine/endian.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 78 "/usr/include/sys/cdefs.h" - -# 55 "/usr/include/machine/endian.h" 2 - - - - - - - - - -# 77 "/usr/include/machine/endian.h" - - - - - - - - - - - - - - - - - - -# 106 "/usr/include/machine/endian.h" - - - - - - - - - - - - -# 83 "/usr/include/sys/param.h" 2 - -# 1 "/usr/include/machine/limits.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 84 "/usr/include/sys/param.h" 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 97 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - - - - - - - - - - - - - - - - - - - -struct utimbuf -{ - long actime; - long modtime; -}; - -int utime (); - - -# 145 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" - -# 1 "/usr/include/strings.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/string.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/machine/ansi.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 57 "/usr/include/machine/ansi.h" - -# 38 "/usr/include/string.h" 2 - - - - - - - - - - - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 78 "/usr/include/sys/cdefs.h" - -# 49 "/usr/include/string.h" 2 - - - -void *memchr (const void *, int, size_t) ; -int memcmp (const void *, const void *, size_t) ; -void *memcpy (void *, const void *, size_t) ; -void *memmove (void *, const void *, size_t) ; -void *memset (void *, int, size_t) ; -char *strcat (char *, const char *) ; -char *strchr (const char *, int) ; -int strcmp (const char *, const char *) ; -int strcoll (const char *, const char *) ; -char *strcpy (char *, const char *) ; -size_t strcspn (const char *, const char *) ; -char *strerror (int) ; -size_t strlen (const char *) ; -char *strncat (char *, const char *, size_t) ; -int strncmp (const char *, const char *, size_t) ; -char *strncpy (char *, const char *, size_t) ; -char *strpbrk (const char *, const char *) ; -char *strrchr (const char *, int) ; -size_t strspn (const char *, const char *) ; -char *strstr (const char *, const char *) ; -char *strtok (char *, const char *) ; -size_t strxfrm (char *, const char *, size_t) ; - - - -int bcmp (const void *, const void *, size_t) ; -void bcopy (const void *, void *, size_t) ; -void bzero (void *, size_t) ; -int ffs (int) ; -char *index (const char *, int) ; -void *memccpy (void *, const void *, int, size_t) ; -char *rindex (const char *, int) ; -int strcasecmp (const char *, const char *) ; -char *strdup (const char *) ; -void strmode (int, char *) ; -int strncasecmp (const char *, const char *, size_t) ; -char *strsep (char **, const char *) ; -void swab (const void *, void *, size_t) ; - - - - -# 36 "/usr/include/strings.h" 2 - -# 146 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - - - -# 1 "/usr/include/errno.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -extern int errno; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 149 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - - - - -char *getenv (); -char *malloc (); -char *realloc (); -char *calloc (); -extern int errno; - - - - - - -# 173 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" - - - - - - -# 1 "/usr/include/sys/file.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/fcntl.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/types.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 135 "/usr/include/sys/types.h" - -# 46 "/usr/include/sys/fcntl.h" 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 99 "/usr/include/sys/fcntl.h" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -struct flock { - short l_type; - short l_whence; - off_t l_start; - off_t l_len; - pid_t l_pid; -}; - - - - - - - - - - - - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 78 "/usr/include/sys/cdefs.h" - -# 169 "/usr/include/sys/fcntl.h" 2 - - - -int open (const char *, int, ...) ; -int creat (const char *, mode_t) ; -int fcntl (int, int, ...) ; - -int flock (int, int) ; - - - - - -# 36 "/usr/include/sys/file.h" 2 - -# 1 "/usr/include/sys/unistd.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 37 "/usr/include/sys/file.h" 2 - - -# 73 "/usr/include/sys/file.h" - -# 179 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - -char *getwd (); - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/dir.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/dirent.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -struct dirent { - u_long d_fileno; - u_short d_reclen; - u_short d_namlen; - - - - - char d_name[255 + 1]; - -}; - - - - - - - - - - - -typedef struct _dirdesc { - int dd_fd; - long dd_loc; - long dd_size; - char *dd_buf; - int dd_len; - long dd_seek; -} DIR; - - - - - - - - - - - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 78 "/usr/include/sys/cdefs.h" - -# 88 "/usr/include/dirent.h" 2 - - - -DIR *opendir (const char *) ; -struct dirent *readdir (DIR *) ; -void rewinddir (DIR *) ; -int closedir (DIR *) ; - -long telldir (const DIR *) ; -void seekdir (DIR *, long) ; -int scandir (const char *, struct dirent ***, - int (*)(struct dirent *), int (*)(const void *, const void *)) ; -int alphasort (const void *, const void *) ; -int getdirentries (int, char *, int, long *) ; - - - - - - -# 44 "/usr/include/sys/dir.h" 2 - - - - - - - - - - - - - - - - - - -# 208 "/usr/src/gnu/cvs/mkmodules/../lib/system.h" 2 - - - - - - - - - - - - - - - - -# 3 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/include/stdio.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 78 "/usr/include/sys/cdefs.h" - -# 42 "/usr/include/stdio.h" 2 - - -# 1 "/usr/include/machine/ansi.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 57 "/usr/include/machine/ansi.h" - -# 44 "/usr/include/stdio.h" 2 - - - - - - - - - - -typedef long fpos_t; - - - - - - - - - - -struct __sbuf { - unsigned char *_base; - int _size; -}; - - - - - - - - - - - - - - - - - - - - - - - - - -typedef struct __sFILE { - unsigned char *_p; - int _r; - int _w; - short _flags; - short _file; - struct __sbuf _bf; - int _lbfsize; - - - void *_cookie; - int (*_close) (void *) ; - int (*_read) (void *, char *, int) ; - fpos_t (*_seek) (void *, fpos_t, int) ; - int (*_write) (void *, const char *, int) ; - - - struct __sbuf _ub; - unsigned char *_up; - int _ur; - - - unsigned char _ubuf[3]; - unsigned char _nbuf[1]; - - - struct __sbuf _lb; - - - int _blksize; - int _offset; -} FILE; - - -extern FILE __sF[]; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void clearerr (FILE *) ; -int fclose (FILE *) ; -int feof (FILE *) ; -int ferror (FILE *) ; -int fflush (FILE *) ; -int fgetc (FILE *) ; -int fgetpos (FILE *, fpos_t *) ; -char *fgets (char *, size_t, FILE *) ; -FILE *fopen (const char *, const char *) ; -int fprintf (FILE *, const char *, ...) ; -int fputc (int, FILE *) ; -int fputs (const char *, FILE *) ; -int fread (void *, size_t, size_t, FILE *) ; -FILE *freopen (const char *, const char *, FILE *) ; -int fscanf (FILE *, const char *, ...) ; -int fseek (FILE *, long, int) ; -int fsetpos (FILE *, const fpos_t *) ; -long ftell (const FILE *) ; -int fwrite (const void *, size_t, size_t, FILE *) ; -int getc (FILE *) ; -int getchar (void) ; -char *gets (char *) ; - -extern int sys_nerr; -extern char *sys_errlist[]; - -void perror (const char *) ; -int printf (const char *, ...) ; -int putc (int, FILE *) ; -int putchar (int) ; -int puts (const char *) ; -int remove (const char *) ; -int rename (const char *, const char *) ; -void rewind (FILE *) ; -int scanf (const char *, ...) ; -void setbuf (FILE *, char *) ; -int setvbuf (FILE *, char *, int, size_t) ; -int sprintf (char *, const char *, ...) ; -int sscanf (char *, const char *, ...) ; -FILE *tmpfile (void) ; -char *tmpnam (char *) ; -int ungetc (int, FILE *) ; -int vfprintf (FILE *, const char *, char * ) ; -int vprintf (const char *, char * ) ; -int vsprintf (char *, const char *, char * ) ; - - - - - - - - - - -char *ctermid (char *) ; -FILE *fdopen (int, const char *) ; -int fileno (FILE *) ; - - - - - - - - -char *fgetline (FILE *, size_t *) ; -int fpurge (FILE *) ; -int getw (FILE *) ; -int pclose (FILE *) ; -FILE *popen (const char *, const char *) ; -int putw (int, FILE *) ; -void setbuffer (FILE *, char *, int) ; -int setlinebuf (FILE *) ; -char *tempnam (const char *, const char *) ; -int snprintf (char *, size_t, const char *, ...) ; -int vsnprintf (char *, size_t, const char *, char * ) ; -int vscanf (const char *, char * ) ; -int vsscanf (const char *, const char *, char * ) ; - - - - - - - - - - - - - -FILE *funopen (const void *, - int (*)(void *, char *, int), - int (*)(void *, const char *, int), - fpos_t (*)(void *, fpos_t, int), - int (*)(void *)) ; - - - - - - - - - -int __srget (FILE *) ; -int __svfscanf (FILE *, const char *, char * ) ; -int __swbuf (int, FILE *) ; - - - - - - - - -static inline int __sputc(int _c, FILE *_p) { - if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) - return (*_p->_p++ = _c); - else - return (__swbuf(_c, _p)); -} -# 331 "/usr/include/stdio.h" - - - - - - - - - - - - - - - - - - - - - - - -# 4 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/include/ctype.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -extern char _ctype_[]; - - - - - - - - - - - - - - - - - - -# 5 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/include/pwd.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 1 "/usr/include/sys/types.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 135 "/usr/include/sys/types.h" - -# 39 "/usr/include/pwd.h" 2 - - - - - - - - - - - - - - - - - - - - -struct passwd { - char *pw_name; - char *pw_passwd; - int pw_uid; - int pw_gid; - time_t pw_change; - char *pw_class; - char *pw_gecos; - char *pw_dir; - char *pw_shell; - time_t pw_expire; -}; - -# 1 "/usr/include/sys/cdefs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 78 "/usr/include/sys/cdefs.h" - -# 72 "/usr/include/pwd.h" 2 - - - -struct passwd *getpwuid (uid_t) ; -struct passwd *getpwnam (const char *) ; - -struct passwd *getpwent (void) ; -int setpassent (int) ; -int setpwent (void) ; -void endpwent (void) ; - - - - -# 6 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/include/signal.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 222 "/usr/include/signal.h" - -# 7 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/src/gnu/cvs/mkmodules/../cvs/hash.h" 1 - - - - - - - - - - - - - - - - - - -enum ntype -{ - UNKNOWN, HEADER, ENTRIES, FILES, LIST, RCSNODE, - RCSVERS, DIRS, UPDATE, LOCK, NDBMNODE -}; -typedef enum ntype Ntype; - -struct node -{ - Ntype type; - struct node *next; - struct node *prev; - struct node *hashnext; - struct node *hashprev; - char *key; - char *data; - void (*delproc) (); -}; -typedef struct node Node; - -struct list -{ - Node *list; - Node *hasharray[151 ]; - struct list *next; -}; -typedef struct list List; - -struct entnode -{ - char *version; - char *timestamp; - char *options; - char *tag; - char *date; -}; -typedef struct entnode Entnode; - - -List *getlist (void); -Node *findnode (List * list, char *key); -Node *getnode (void); -int addnode (List * list, Node * p); -int walklist (List * list, int (*proc) ()); -void dellist (List ** listp); -void delnode (Node * p); -void freenode (Node * p); -void sortlist (List * list, int (*comp) ()); -# 77 "/usr/src/gnu/cvs/mkmodules/../cvs/hash.h" - -# 8 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/src/gnu/cvs/mkmodules/../cvs/rcs.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -struct rcsnode -{ - int refcount; - int flags; - char *path; - char *head; - char *branch; - List *symbols; - List *versions; - List *dates; -}; -typedef struct rcsnode RCSNode; - -struct rcsversnode -{ - char *version; - char *date; - char *next; - List *branches; -}; -typedef struct rcsversnode RCSVers; - - - - - - - - - - - - - - -List *RCS_parsefiles (List * files, char *xrepos); -RCSNode *RCS_parse (char *file, char *repos); -RCSNode *RCS_parsercsfile (char *rcsfile); -char *RCS_check_kflag (char *arg); -char *RCS_getdate (RCSNode * rcs, char *date, int force_tag_match); -char *RCS_gettag (RCSNode * rcs, char *tag, int force_tag_match); -char *RCS_getversion (RCSNode * rcs, char *tag, char *date, - int force_tag_match); -char *RCS_magicrev (RCSNode *rcs, char *rev); -int RCS_isbranch (char *file, char *rev, List *srcfiles); -char *RCS_whatbranch (char *file, char *tag, List *srcfiles); -char *RCS_head (RCSNode * rcs); -int RCS_datecmp (char *date1, char *date2); -time_t RCS_getrevtime (RCSNode * rcs, char *rev, char *date, int fudge); -void RCS_check_tag (char *tag); -void freercsnode (RCSNode ** rnodep); -# 102 "/usr/src/gnu/cvs/mkmodules/../cvs/rcs.h" - -# 9 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/src/gnu/cvs/mkmodules/../lib/regex.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -typedef unsigned reg_syntax_t; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -extern reg_syntax_t obscure_syntax; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -typedef enum -{ - REG_NOERROR = 0, - REG_NOMATCH, - - - - REG_BADPAT, - REG_ECOLLATE, - REG_ECTYPE, - REG_EESCAPE, - REG_ESUBREG, - REG_EBRACK, - REG_EPAREN, - REG_EBRACE, - REG_BADBR, - REG_ERANGE, - REG_ESPACE, - REG_BADRPT, - - - REG_EEND, - REG_ESIZE, - REG_ERPAREN -} reg_errcode_t; - - - - - - - - - - -struct re_pattern_buffer -{ - - - - - unsigned char *buffer; - - - unsigned long allocated; - - - unsigned long used; - - - reg_syntax_t syntax; - - - - - char *fastmap; - - - - - - char *translate; - - - size_t re_nsub; - - - - - - - unsigned can_be_null : 2; - - - - unsigned fastmap_accurate : 1; - - - - unsigned no_sub : 1; - - - - unsigned not_bol : 1; - - - unsigned not_eol : 1; - - - unsigned newline_anchor : 1; - - - - - unsigned caller_allocated_regs : 1; - -}; - -typedef struct re_pattern_buffer regex_t; - - - - - - - - - - - -typedef int regoff_t; - - - - -struct re_registers -{ - unsigned num_regs; - regoff_t *start; - regoff_t *end; -}; - - - - - - - - - - - - -typedef struct -{ - regoff_t rm_so; - regoff_t rm_eo; -} regmatch_t; - - - - - - - - - - -extern reg_syntax_t re_set_syntax (reg_syntax_t syntax); - - - - -extern const char *re_compile_pattern (const char *pattern, int length, - struct re_pattern_buffer *buffer); - - - - - -extern int re_compile_fastmap (struct re_pattern_buffer *buffer); - - - - - - - -extern int re_search (struct re_pattern_buffer *buffer, - const char *string, int length, - int start, int range, - struct re_registers *regs); - - - - -extern int re_search_2 (struct re_pattern_buffer *buffer, - const char *string1, int length1, - const char *string2, int length2, - int start, int range, - struct re_registers *regs, - int stop); - - - - -extern int re_match (const struct re_pattern_buffer *buffer, - const char *string, int length, - int start, struct re_registers *regs); - - - -extern int re_match_2 (const struct re_pattern_buffer *buffer, - const char *string1, int length1, - const char *string2, int length2, - int start, - struct re_registers *regs, - int stop); - - - - - - - - - - - -extern int regcomp (regex_t *preg, const char *pattern, int cflags); -extern int regexec (const regex_t *preg, const char *string, size_t nmatch, - regmatch_t pmatch[], int eflags); -extern size_t regerror (int errcode, const regex_t *preg, char *errbuf, - size_t errbuf_size); -extern void regfree (regex_t *preg); - -# 468 "/usr/src/gnu/cvs/mkmodules/../lib/regex.h" - - - - - - - - - - - - -# 10 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/src/gnu/cvs/mkmodules/../lib/fnmatch.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -extern int fnmatch (const char *pattern, const char *string, int flags); - - - - - -# 11 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/src/gnu/cvs/mkmodules/../lib/getopt.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - -extern char *optarg; - - - - - - - - - - - - - -extern int optind; - - - - -extern int opterr; - - - - - - - - - - - - - - - - - - - - - -struct option -{ - char *name; - int has_arg; - int *flag; - int val; -}; - - -extern const struct option *_getopt_long_options; - - - - - - - -extern int _getopt_long_only; - - - - - -extern int option_index; - - -int gnu_getopt (int argc, char **argv, const char *shortopts); -int gnu_getopt_long (int argc, char **argv, const char *shortopts, - const struct option *longopts, int *longind); -int gnu_getopt_long_only (int argc, char **argv, const char *shortopts, - const struct option *longopts, int *longind); - - - - - -# 12 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/src/gnu/cvs/mkmodules/../lib/wait.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# 13 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - -# 1 "/usr/src/gnu/cvs/mkmodules/../cvs/config.h" 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -extern void exit (); - - - -extern char *getwd (); - - - - - - - - - - - - - - - -# 14 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - - -# 1 "/usr/src/gnu/cvs/mkmodules/../cvs/myndbm.h" 1 - - - - - - -typedef struct -{ - List *dbm_list; - Node *dbm_next; -} DBM; - -typedef struct -{ - char *dptr; - int dsize; -} datum; - - - - - - - - - - - - - -DBM *mydbm_open (char *file, int flags, int mode); -void mydbm_close (DBM * db); -datum mydbm_fetch (DBM * db, datum key); -datum mydbm_firstkey (DBM * db); -datum mydbm_nextkey (DBM * db); - - - - - - - - - -# 16 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -enum mtype -{ - CHECKOUT, TAG, PATCH -}; - - - - - - -enum classify_type -{ - T_UNKNOWN = 1, - T_CONFLICT, - T_NEEDS_MERGE, - T_MODIFIED, - T_CHECKOUT, - T_ADDED, - T_REMOVED, - T_REMOVE_ENTRY, - T_UPTODATE, - T_TITLE -}; -typedef enum classify_type Ctype; - - - - - - - - -struct vers_ts -{ - char *vn_user; - - - - - - char *vn_rcs; - - char *ts_user; - char *ts_rcs; - char *options; - - char *tag; - char *date; - Entnode *entdata; - RCSNode *srcfile; -}; -typedef struct vers_ts Vers_TS; - - - - - -struct stickydirtag -{ - int aflag; - char *tag; - char *date; - char *options; -}; - - - - - - - - - - - - - - - - -enum direnter_type -{ - R_PROCESS = 1, - R_SKIP_FILES, - R_SKIP_DIRS, - R_SKIP_ALL -}; -typedef enum direnter_type Dtype; - -extern char *program_name, *command_name; -extern char *Rcsbin, *Editor, *CVSroot; -extern char *CurDir; -extern int really_quiet, quiet; -extern int use_editor; -extern int cvswrite; - -extern int trace; -extern int noexec; -extern int logoff; - - - -int Reader_Lock (char *xrepository); -DBM *open_module (void); -FILE *Fopen (char *name, char *mode); -FILE *open_file (char *name, char *mode); -List *Find_Dirs (char *repository, int which); -List *ParseEntries (int aflag); -char *Make_Date (char *rawdate); -char *Name_Repository (char *dir, char *update_dir); -char *Short_Repository (char *repository); -char *getcaller (void); -char *time_stamp (char *file); -char *xmalloc (int bytes); -char *xrealloc (char *ptr, int bytes); -char *xstrdup (char *str); -int No_Difference (char *file, Vers_TS * vers, List * entries); -int Parse_Info (char *infofile, char *repository, int (*callproc) (), int all); -int Reader_Lock (char *xrepository); -int SIG_register (int sig, void (*fn) ()); -int Writer_Lock (List * list); -int gethostname (char *name, int namelen); -int ign_name (char *name); -int isdir (char *file); -int isfile (char *file); -int islink (char *file); -int isreadable (char *file); -int iswritable (char *file); -int link_file (char *from, char *to); -int numdots (char *s); -int run_exec (char *stin, char *stout, char *sterr, int flags); -int unlink_file (char *f); -int update (int argc, char *argv[]); -int xcmp (char *file1, char *file2); -int yesno (void); -time_t get_date (char *date, struct timeb *now); -void Create_Admin (char *dir, char *repository, char *tag, char *date); -void Lock_Cleanup (void); -void ParseTag (char **tagp, char **datep); -void Scratch_Entry (List * list, char *fname); -void WriteTag (char *dir, char *tag, char *date); -void cat_module (int status); -void check_entries (char *dir); -void close_module (DBM * db); -void copy_file (char *from, char *to); -void error (int status, int errnum, char *message,...); -void fperror (FILE * fp, int status, int errnum, char *message,...); -void free_names (int *pargc, char *argv[]); -void freevers_ts (Vers_TS ** versp); -void ign_add (char *ign, int hold); -void ign_add_file (char *file, int hold); -void ign_setup (void); -void line2argv (int *pargc, char *argv[], char *line); -void make_directories (char *name); -void make_directory (char *name); -void rename_file (char *from, char *to); -void run_arg (char *s); -void run_args (char *fmt,...); -void run_print (FILE * fp); -void run_setup (char *fmt,...); -void strip_path (char *path); -void update_delproc (Node * p); -void usage (char **cpp); -void xchmod (char *fname, int writable); -int Checkin (int type, char *file, char *repository, char *rcs, char *rev, - char *tag, char *message, List * entries); -Ctype Classify_File (char *file, char *tag, char *date, char *options, - int force_tag_match, int aflag, char *repository, - List *entries, List *srcfiles, Vers_TS **versp); -List *Find_Names (char *repository, int which, int aflag, - List ** optentries); -void Register (List * list, char *fname, char *vn, char *ts, - char *options, char *tag, char *date); -void Update_Logfile (char *repository, char *xmessage, char *xrevision, - FILE * xlogfp, List * xchanges); -Vers_TS *Version_TS (char *repository, char *options, char *tag, - char *date, char *user, int force_tag_match, - int set_time, List * entries, List * xfiles); -void do_editor (char *dir, char *message, char *repository, - List * changes); -int do_module (DBM * db, char *mname, enum mtype m_type, char *msg, - int (*callback_proc) (), char *where, int shorten, - int local_specified, int run_module_prog, char *extra_arg); -int do_recursion (int (*xfileproc) (), int (*xfilesdoneproc) (), - Dtype (*xdirentproc) (), int (*xdirleaveproc) (), - Dtype xflags, int xwhich, int xaflag, int xreadlock, - int xdosrcs); -int do_update (int argc, char *argv[], char *xoptions, char *xtag, - char *xdate, int xforce, int local, int xbuild, - int xaflag, int xprune, int xpipeout, int which, - char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir); -void history_write (int type, char *update_dir, char *revs, char *name, - char *repository); -int start_recursion (int (*fileproc) (), int (*filesdoneproc) (), - Dtype (*direntproc) (), int (*dirleaveproc) (), - int argc, char *argv[], int local, int which, - int aflag, int readlock, char *update_preload, - int dosrcs); -void SIG_beginCrSect (); -void SIG_endCrSect (); -# 438 "/usr/src/gnu/cvs/mkmodules/../cvs/cvs.h" - -# 15 "/usr/src/gnu/cvs/mkmodules/mkmodules.c" 2 - - - - - - -PATH_MAX +2 - - -static char rcsid[] = "@(#)mkmodules.c 1.39 92/03/31"; - - - - - - -char *program_name, *command_name; - -char *Rcsbin = "" ; -int noexec = 0; -int trace = 0; - - -static int checkout_file (char *file, char *temp); -static void make_tempfile (char *temp); -static void mkmodules_usage (void); -static void rename_rcsfile (char *temp, char *real); - - - - - - -# 60 "/usr/src/gnu/cvs/mkmodules/mkmodules.c" - - -int -main (argc, argv) - int argc; - char *argv[]; -{ - extern char *getenv (); - char temp[PATH_MAX +2 ]; - char *cp; - - DBM *db; - - - - - - if ((program_name = rindex (argv[0], '/')) == 0 ) - program_name = argv[0]; - else - program_name++; - - if (argc != 2) - mkmodules_usage (); - - if ((cp = getenv ("RCSBIN" )) != 0 ) - Rcsbin = cp; - - - - - - if (Rcsbin[0] != '\0') - { - int len = strlen (Rcsbin); - char *rcsbin; - - if (Rcsbin[len - 1] != '/') - { - rcsbin = Rcsbin; - Rcsbin = xmalloc (len + 2); - (void) strcpy (Rcsbin, rcsbin); - (void) strcat (Rcsbin, "/"); - } - } - - if (chdir (argv[1]) < 0) - error (1, errno, "cannot chdir to %s", argv[1]); - - - - - make_tempfile (temp); - switch (checkout_file ("modules" , temp)) - { - - case 0: - - - if ((db = mydbm_open (temp, 0x0000 , 0666)) != 0 ) - mydbm_close (db); - - - - - rename_rcsfile (temp, "modules" ); - break; - - case -1: - (void) unlink_file (temp); - exit (1); - - - default: - error (0, 0, - "'cvs checkout' is less functional without a %s file", - "modules" ); - break; - } - - (void) unlink_file (temp); - - - - - - make_tempfile (temp); - if (checkout_file ("loginfo" , temp) == 0) - rename_rcsfile (temp, "loginfo" ); - else - error (0, 0, - "no logging of 'cvs commit' messages is done without a %s file", - "loginfo" ); - (void) unlink_file (temp); - - - - - - make_tempfile (temp); - if (checkout_file ("rcsinfo" , temp) == 0) - rename_rcsfile (temp, "rcsinfo" ); - else - error (0, 0, - "a %s file can be used to configure 'cvs commit' templates", - "rcsinfo" ); - (void) unlink_file (temp); - - - - - - make_tempfile (temp); - if (checkout_file ("editinfo" , temp) == 0) - rename_rcsfile (temp, "editinfo" ); - else - error (0, 0, - "a %s file can be used to validate log messages", - "editinfo" ); - (void) unlink_file (temp); - - - - - - make_tempfile (temp); - if (checkout_file ("commitinfo" , temp) == 0) - rename_rcsfile (temp, "commitinfo" ); - else - error (0, 0, - "a %s file can be used to configure 'cvs commit' checking", - "commitinfo" ); - (void) unlink_file (temp); - return (0); -} - - - - -static void -make_tempfile (temp) - char *temp; -{ - static int seed = 0; - int fd; - - if (seed == 0) - seed = getpid (); - while (1) - { - (void) sprintf (temp, "%s%d", ".#" , seed++); - if ((fd = open (temp, 0x0200 | 0x0800 | 0x0002 , 0666)) != -1) - break; - if (errno != 17 ) - error (1, errno, "cannot create temporary file %s", temp); - } - if (close(fd) < 0) - error(1, errno, "cannot close temporary file %s", temp); -} - -static int -checkout_file (file, temp) - char *file; - char *temp; -{ - char rcs[PATH_MAX +2 ]; - int retcode = 0; - - (void) sprintf (rcs, "%s%s", file, ",v" ); - if (!isfile (rcs)) - return (1); - run_setup ("%s%s -q -p", Rcsbin, "co" ); - run_arg (rcs); - if ((retcode = run_exec ( (char *)0 , temp, (char *)0 , 0x0000 )) != 0) - { - error (0, retcode == -1 ? errno : 0, "failed to check out %s file", file); - } - return (retcode); -} - -# 369 "/usr/src/gnu/cvs/mkmodules/mkmodules.c" - - -static void -rename_rcsfile (temp, real) - char *temp; - char *real; -{ - char bak[50]; - - if (chmod (temp, 0444) < 0) - error (0, errno, "warning: cannot chmod %s", temp); - (void) sprintf (bak, "%s%s", ".#" , real); - (void) unlink_file (bak); - (void) rename (real, bak); - (void) rename (temp, real); -} - - - - -void -Lock_Cleanup () -{ -} - -static void -mkmodules_usage () -{ - (void) fprintf ((&__sF[2]) , "Usage: %s modules-directory\n", program_name); - exit (1); -} |