Mercurial > emacs
changeset 53289:ef22c9575b53
Merged in changes from CVS HEAD
Patches applied:
* miles@gnu.org--gnu-2003/emacs--cvs-trunk--0--patch-138
Update from CVS
* miles@gnu.org--gnu-2003/emacs--cvs-trunk--0--patch-139
Update from CVS
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-15
author | Karoly Lorentey <lorentey@elte.hu> |
---|---|
date | Sun, 28 Dec 2003 16:03:57 +0000 |
parents | 7a619020ecd2 (diff) 4cb33bfb540c (current diff) |
children | 49084d566b9f |
files | ChangeLog lisp/ChangeLog lisp/vc.el src/regex.c src/regex.h src/xfaces.c |
diffstat | 122 files changed, 2852 insertions(+), 8799 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.multi-tty Sun Dec 28 16:03:57 2003 +0000 @@ -0,0 +1,254 @@ + -*- coding: utf-8; -*- +GOAL +---- + +The ultimate goal of this branch is to implement support for opening +multiple, different tty devices and simultaneous X and tty frames from +a single Emacs session. + +WHO IS DOING IT +--------------- + +I'm Károly Lőrentey. My address: lorentey@elte.hu. + +Patches or suggestions are welcome! + +Retrieving the latest version of the branch: + + tla register-archive lorentey@elte.hu--2004 http://lorentey.web.elte.hu/arch/2004/ + tla get lorentey@elte.hu--2004/emacs--multi-tty--0 <directory> + +(I use tla 1.1.) + + +STATUS +------ + +Basic multi-tty support is there; there are some rough edges, but it +already seems to be usable. Emacsclient has been extended to support +opening a new terminal frame. + +To try it out, compile Emacs with the following commands + + mkdir +build + cd +build + ../configure --with-x-toolkit=no --without-x + make bootstrap + +then start up the emacs server (src/emacs, M-x server-start), and then +(from a shell prompt on another terminal) start emacsclient with + + lib-src/emacsclient -h + +You'll hopefully have two fully working frames on separate terminals. +If you exit emacs, both terminals should be restored to their previous +states. You can close the newly opened frame and return to the shell +without exiting Emacs by pressing C-x 5 0, i.e., delete-frame. + +X, Mac, Windows and DOS support is broken, probably doesn't even +compile -- this will be solved later. + +Tested under GNU/Linux only. + +NEWS +---- + +For the NEWS file: + +** Support for multiple terminal devices has been added. You can + specify a terminal device (`tty' parameter) and a terminal type + (`tty-type' parameter) to `make-terminal-frame'. `tty' must be a + terminal device created by the updated emacsclient, or there will + be problems with terminal input and window resizes. (The kernel + notifies processes about pending input or terminal resizes only on + the controlling terminal, so we need emacsclient to sit on the real + terminal device, create SIGIO signals upon terminal input, and + forward SIGWINCH signals to us.) + + You can test for the presence of multiple terminal support by + testing for the `multi-tty' feature. + +** A make-frame-on-tty function has been added to make it easier to + create frames on new terminals. + +** Emacsclient has been extended to support opening a new terminal + frame. + +CHANGELOG +--------- + +See arch logs. + + +DIARY OF CHANGES +---------------- + +(ex-TODO items with explanations.) + +-- Introduce a new abstraction for terminal devices. + + (Done, see struct tty_output. The abstraction is not yet + complete.) + +-- Change the bootstrap procedure to initialize tty_list. + + (Done, but needs review.) + +-- Change make-terminal-frame to support specifying another tty. + + (Done, new frame parameters: `tty' and `tty-type'.) + +-- Implement support for reading from multiple terminals. + + (Done, read_avail_input tries to read from each terminal, until one + succeeds. MULTIKBOARD is not used. Secondary terminals don't send + SIGIO!) + +-- other-frame should cycle through the frames on the `current' + terminal only. + + (Done, by trivially modifiying next_frame and prev_frame.) + +-- Support different terminal sizes. + + (Done, no problem.) + +-- Make sure terminal resizes are handled gracefully. (Could be + problematic.) + + (Done. We don't get automatic SIGWINCH for additional ttys, + though.) + +-- Extend emacsclient to automatically open a new tty when it connects + to Emacs. + + (Done. It's an ugly hack, needs more work.) + +-- Redisplay must refresh the topmost frame on *all* terminals, not + just the initial terminal. + + (Done, but introduced an ugly redisplay problems. Ugh.) + +-- Fix redisplay problems. + + (Done; it turned out that the entire Wcm structure must be moved + inside tty_output. Why didn't I catch this earlier?) + +-- Provide a way for emacsclient to tell Emacs that the tty has been + resized. + + (Done, simply forward the SIGWINCH signal.) + +-- Each keypress should automatically select the frame corresponding + to the terminal that it was coming from. This means that Emacs + must know from which terminal the last keyboard event came from. + + (Done, it was quite simple, the input event system already + supported multiple frames.) + +-- Fix SIGIO issue with secondary terminals. + + (Done, emacsclient signals Emacs after writing to the proxy pseudo + terminal. Note that this means that multi-tty does not work with + raw ttys!) + +-- Make make-terminal-frame look up the `tty' and `tty-type' frame + parameters from the currently selected terminal before the global + default. + + (Done.) + +-- Put all cached terminal escape sequences into struct tty_output. + Currently, they are still stored in global variables, so we don't + really support multiple terminal types. + + (Done. It was not fun.) + +-- Implement sane error handling after initialization. (Currently + emacs exits if you specify a bad terminal type.) The helpful error + messages must still be provided when Emacs starts. + + (Done.) + +-- Implement terminal deletion, i.e., deleting local frames, closing + the tty device and restoring its previous state without exiting + Emacs. + + (Done, but at the moment only called when an error happens during + initialization. There is a memory corruption error around this + somewhere.) + +-- Implement automatic deletion of terminals when the last frame on + that terminal is closed. + + (Done.) + + +THINGS TO DO +------------ + +** Fix mysterious memory corruption error with tty deletion. To + trigger it, try the following shell command: + + while true; do TERM=no-such-terminal-definition emacsclient -h; done + + Emacs usually dumps core after a few dozen iterations. (The bug + seems to be related to the xfree()ing or bzero()ing of + tty_output.Wcm or some other tty_output part. Maybe there are + outside references to struct Wcm? Why were these vars collected + into a struct before multi-tty support?) + + The bug does not seem to happen if the error occurs before terminal + initialization or if I comment out all xfree()s in delete_frame. + Update: yes it does, although it is much rarer. Or maybe it's + another bug. + +** Change emacsclient/server.el to support the -h argument better, + i.e. automatically close the socket when the frame is closed. + +** Export delete_tty to the Lisp environment, for emacsclient. + +** Restore tty screen after closing the terminal. + +** 'TERM=dumb src/emacs' does not restore the terminal state. + +** C-g should work on secondary terminals. + +** Make parts of struct tty_output accessible from Lisp. The device + name and the type is sufficient. + +** Find out why does Emacs abort when it wants to close its + controlling tty. + +** Implement support for starting an interactive Emacs session without + an initial frame. (The user would connect to it and open frames + later, with emacsclient.) Not necessarily a good idea. + +** Support raw secondary terminals. (This one is tricky, SIGIO works + only on the controlling terminal. The emacsclient solution works + nicely, so this is not that important anyway.) + +** What does interrupt_input do? I tried to disable it for raw + secondary tty support, but it does not seem to do anything useful. + +** Move optimalization parameters (costs) from union output_data to + a backend-neutral per-device structure. + +** Find out the best way to support suspending Emacs with multiple + ttys. + +** Do tty output through term_hooks, like all other display backends. + +** Fix X support. + +** Allow simultaneous X and tty frames. + +** Fix Mac support (I can't do this myself). + +** Fix W32 support (I can't do this myself). + +** Fix DOS support (I can't do this myself). + + + +;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
--- a/etc/ONEWS Wed Dec 24 23:32:12 2003 +0000 +++ b/etc/ONEWS Sun Dec 28 16:03:57 2003 +0000 @@ -1029,7 +1029,7 @@ *** RCS customization. There is a new variable vc-consult-headers. If it is t (the default), -VC searches for RCS headers in working files (like `$Id: ONEWS,v 1.8 2003/02/04 14:30:40 lektu Exp $') and +VC searches for RCS headers in working files (like `$Id: ONEWS,v 1.9 2003/09/01 15:44:58 miles Exp $') and determines the state of the file from them, not from the master file. This is fast and more reliable when you use branches. (The variable was already present in Emacs 19.29, but didn't get mentioned in the
--- a/etc/TODO Wed Dec 24 23:32:12 2003 +0000 +++ b/etc/TODO Sun Dec 28 16:03:57 2003 +0000 @@ -137,7 +137,10 @@ * Highlight rectangles (`mouse-track-rectangle-p' in XEmacs). Already in CUA, but it's a valuable feature worth making more general. -* Support simultaneous tty and X frames. +* Support simultaneous tty and X frames. [For a partial + implementation, see tla branch + lorentey@elte.hu--2004/emacs--multi-tty--0 at + http://lorentey.web.elte.hu/arch/2004] * Provide MIME support for Rmail using the Gnus MIME library. [Maybe not now feasible, given Gnus maintenance decisions. fx looked at
--- a/etc/cs-survival.tex Wed Dec 24 23:32:12 2003 +0000 +++ b/etc/cs-survival.tex Sun Dec 28 16:03:57 2003 +0000 @@ -2,8 +2,8 @@ % Title: GNU Emacs Survival Card % Author: Wlodek Bzyl <matwb@univ.gda.pl> % -% $Revision: 1.2 $ -% $Date: 2003/02/04 14:30:41 $ +% $Revision: 1.3 $ +% $Date: 2003/09/01 15:44:59 $ % %**start of header
--- a/etc/fr-survival.tex Wed Dec 24 23:32:12 2003 +0000 +++ b/etc/fr-survival.tex Sun Dec 28 16:03:57 2003 +0000 @@ -3,8 +3,8 @@ % Title: GNU Emacs Survival Card % Author: Wlodek Bzyl <matwb@univ.gda.pl> % -% $Revision: 1.2 $ -% $Date: 2003/02/04 14:30:41 $ +% $Revision: 1.3 $ +% $Date: 2003/09/01 15:44:59 $ % %**start of header
--- a/etc/pl-refcard.tex Wed Dec 24 23:32:12 2003 +0000 +++ b/etc/pl-refcard.tex Sun Dec 28 16:03:57 2003 +0000 @@ -1,7 +1,7 @@ %&mex %===================================================================== -% $Revision: 1.3 $ -% $Date: 2003/02/04 14:30:42 $ +% $Revision: 1.4 $ +% $Date: 2003/09/01 15:44:59 $ %===================================================================== % Reference Card for GNU Emacs version 20 on Unix systems was % translated into Polish language by W{\l}odek Bzyl (matwb@univ.gda.pl)
--- a/etc/sk-survival.tex Wed Dec 24 23:32:12 2003 +0000 +++ b/etc/sk-survival.tex Sun Dec 28 16:03:57 2003 +0000 @@ -2,8 +2,8 @@ % Title: GNU Emacs Survival Card % Author: Wlodek Bzyl <matwb@univ.gda.pl> % -% $Revision: 1.2 $ -% $Date: 2003/02/04 14:30:42 $ +% $Revision: 1.3 $ +% $Date: 2003/09/01 15:44:59 $ % %**start of header
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/etc/survival.log Sun Dec 28 16:03:57 2003 +0000 @@ -0,0 +1,10 @@ +This is TeX, Version 3.14159 (Web2C 7.3.1) (format=tex 2000.12.11) 12 DEC 2000 10:16 +**survival +(survival.tex +\intercolumnskip=\dimen16 +\leftcolumn=\box16 +\defwidth=\dimen17 +\raggedstretch=\dimen18 +\raggedparfill=\skip18 + [1] [2] ) +Output written on survival.dvi (2 pages, 11216 bytes).
--- a/etc/termcap.src Wed Dec 24 23:32:12 2003 +0000 +++ b/etc/termcap.src Sun Dec 28 16:03:57 2003 +0000 @@ -10,7 +10,7 @@ # #------------------------------------------------------------------------------ # Version 10.2.1 -# $Date: 2002/04/20 07:38:53 $ +# $Date: 2003/02/04 14:30:42 $ # terminfo syntax # # Eric S. Raymond (current maintainer)
--- a/info/.cvsignore Wed Dec 24 23:32:12 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -emacs -emacs-[1-9]* -emacs-mime -ccmode -ccmode-[1-9]* -cl -cl-[1-9]* -dired-x -ediff -ediff-[1-9]* -eshell -forms -gnus -gnus-[1-9]* -info -message -mh-e -mh-e-[1-9]* -reftex -reftex-[1-9]* -sc -sc-[1-9]* -vip -vip-[1-9]* -viper -viper-[1-9]* -widget -ada-mode -eudc -autotype -efaq -efaq-[1-9]* -idlwave -idlwave-[1-9]* -ebrowse -pcl-cvs -woman -woman-[1-9]* -speedbar -elisp -elisp-[1-9]* -calc -calc-[1-9]* -eintr -eintr-[1-9]* -tramp -tramp-[1-9]* -ses -smtpmail
--- a/info/COPYING Wed Dec 24 23:32:12 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <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.
--- a/info/dir Wed Dec 24 23:32:12 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ --*- Text -*- -This is the file .../info/dir, which contains the topmost node of the -Info hierarchy. The first time you invoke Info you start off -looking at that node, which is (dir)Top. - -File: dir Node: Top This is the top of the INFO tree - -The Info Directory -****************** - - The Info Directory is the top-level menu of major Info topics. - Type "d" in Info to return to the Info Directory. Type "q" to exit Info. - Type "?" for a list of Info commands, or "h" to visit an Info tutorial. - Type "m" to choose a menu item--for instance, - "mEmacs<Return>" visits the Emacs manual. - In Emacs Info, you can click mouse button 2 on a menu item - or cross reference to follow it to its target. - -* Menu: Each line that starts with a * is a topic you can select with "m". - Every third topic has a red *. - -* Info: (info). How to use the documentation browsing system. - -Emacs -* Emacs: (emacs). The extensible self-documenting text editor. -* Emacs FAQ: (efaq). Frequently Asked Questions about Emacs. -* Emacs Lisp Introduction: (eintr). - A simple introduction to Emacs Lisp programming. -* Elisp: (elisp). The Emacs Lisp Reference Manual. - -* CL: (cl). Partial Common Lisp support for Emacs Lisp. -* Dired-X: (dired-x). Dired Extra Features. -* Ediff: (ediff). A visual interface for comparing and merging programs. -* PCL-CVS: (pcl-cvs). Emacs front-end to CVS. -* Speedbar: (speedbar). File/Tag summarizing utility. - -* Ada mode: (ada-mode). Emacs mode for editing Ada code. -* CC mode: (ccmode). Emacs mode for editing C, C++, Objective-C, - Java, Pike, and IDL code. -* Ebrowse: (ebrowse). A C++ class browser for Emacs. -* IDLWAVE: (idlwave). Major mode and shell for IDL and WAVE/CL files. - -* Gnus: (gnus). The news reader Gnus. -* Message: (message). Mail and news composition mode that goes with Gnus. -* MH-E: (mh-e). Emacs interface to the MH mail system. -* MIME: (emacs-mime). Emacs MIME de/composition library. -* SC: (sc). Supercite lets you cite parts of messages you're - replying to, in flexible ways. - -* Autotype: (autotype). Convenient features for text that you enter frequently - in Emacs. -* Calc: (calc). Advanced desk calculator and mathematical tool. -* Eshell: (eshell). A command shell implemented in Emacs Lisp. -* EUDC: (eudc). An Emacs client for directory servers (LDAP, PH). -* Forms: (forms). Emacs package for editing data bases - by filling in forms. -* RefTeX: (reftex). Emacs support for LaTeX cross-references and citations. -* Tramp: (tramp). Transparent Remote (file) Access, Multiple Protocol. - Edit remote files via a remote shell (rsh, - ssh, telnet). -* Widget: (widget). The "widget" package used by the Emacs Customization - facility. -* WoMan: (woman). Browse UN*X Manual Pages "Wo (without) Man". - -* VIPER: (viper). The newest Emacs VI-emulation mode. - (also, A VI Plan for Emacs Rescue - or the VI PERil.) -* VIP: (vip). An older VI-emulation for Emacs.
--- a/leim/CXTERM-DIC/4Corner.tit Wed Dec 24 23:32:12 2003 +0000 +++ b/leim/CXTERM-DIC/4Corner.tit Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -# $Id: 4Corner.tit,v 1.2 2001/03/06 13:29:34 handa Exp $ +# $Id: 4Corner.tit,v 1.3 2003/09/01 15:44:59 miles Exp $ # HANZI input table for cxterm # To be used by cxterm, convert me to .cit format first # .cit version 2
--- a/leim/CXTERM-DIC/CCDOSPY.tit Wed Dec 24 23:32:12 2003 +0000 +++ b/leim/CXTERM-DIC/CCDOSPY.tit Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -# $Id: CCDOSPY.tit,v 1.1 1999/10/08 20:06:27 fx Exp $ +# $Id: CCDOSPY.tit,v 1.2 2003/09/01 15:44:59 miles Exp $ # HANZI input table for cxterm # To be used by cxterm, convert me to .cit format first # .cit version 1
--- a/leim/CXTERM-DIC/Punct.tit Wed Dec 24 23:32:12 2003 +0000 +++ b/leim/CXTERM-DIC/Punct.tit Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -# $Id: Punct.tit,v 1.1 1999/10/08 20:06:50 fx Exp $ +# $Id: Punct.tit,v 1.2 2003/09/01 15:44:59 miles Exp $ # HANZI input table for cxterm # To be used by cxterm, convert me to .cit format first # .cit version 1
--- a/leim/CXTERM-DIC/QJ.tit Wed Dec 24 23:32:12 2003 +0000 +++ b/leim/CXTERM-DIC/QJ.tit Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -# $Id: QJ.tit,v 1.1 1999/10/08 20:06:51 fx Exp $ +# $Id: QJ.tit,v 1.2 2003/09/01 15:44:59 miles Exp $ # HANZI input table for cxterm # To be used by cxterm, convert me to .cit format first # .cit version 1
--- a/leim/CXTERM-DIC/SW.tit Wed Dec 24 23:32:12 2003 +0000 +++ b/leim/CXTERM-DIC/SW.tit Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -# $Id: SW.tit,v 1.1 1999/10/08 20:06:53 fx Exp $ +# $Id: SW.tit,v 1.2 2003/09/01 15:44:59 miles Exp $ # HANZI input table for cxterm # To be used by cxterm, convert me to .cit format first # .cit version 1
--- a/leim/CXTERM-DIC/TONEPY.tit Wed Dec 24 23:32:12 2003 +0000 +++ b/leim/CXTERM-DIC/TONEPY.tit Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -# $Id: TONEPY.tit,v 1.1 1999/10/08 20:06:56 fx Exp $ +# $Id: TONEPY.tit,v 1.2 2003/09/01 15:44:59 miles Exp $ # HANZI input table for cxterm # To be used by cxterm, convert me to .cit format first # .cit version 1
--- a/lib-src/b2m.pl Wed Dec 24 23:32:12 2003 +0000 +++ b/lib-src/b2m.pl Sun Dec 28 16:03:57 2003 +0000 @@ -30,7 +30,7 @@ use Date::Parse; my($whoami) = basename $0; -my($version) = '$Revision: 1.5 $'; +my($version) = '$Revision: 1.6 $'; my($usage) = "Usage: $whoami [--help] [--version] [--[no]full-headers] [Babyl-file] \tBy default, full headers are printed.\n";
--- a/lib-src/emacsclient.c Wed Dec 24 23:32:12 2003 +0000 +++ b/lib-src/emacsclient.c Sun Dec 28 16:03:57 2003 +0000 @@ -41,6 +41,54 @@ # include <pwd.h> #endif /* not VMS */ + +/****************************************/ + +#include <errno.h> +#include <signal.h> + +#ifndef INCLUDED_FCNTL +#define INCLUDED_FCNTL +#include <fcntl.h> +#endif + +#ifdef HAVE_TERMIOS +#ifndef NO_TERMIO +#include <termio.h> +#endif +#include <termios.h> +#endif /* not HAVE_TERMIOS */ + +#ifdef __GNU_LIBRARY__ +#include <sys/ioctl.h> +#include <termios.h> +#endif + +#if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H) +#include <unistd.h> +#endif + + + +/* Try to establish the correct character to disable terminal functions + in a system-independent manner. Note that USG (at least) define + _POSIX_VDISABLE as 0! */ + +#ifdef _POSIX_VDISABLE +#define CDISABLE _POSIX_VDISABLE +#else /* not _POSIX_VDISABLE */ +#ifdef CDEL +#undef CDISABLE +#define CDISABLE CDEL +#else /* not CDEL */ +#define CDISABLE 255 +#endif /* not CDEL */ +#endif /* not _POSIX_VDISABLE */ + + + +/****************************************/ + char *getenv (), *getwd (); char *getcwd (); @@ -63,6 +111,9 @@ /* The display on which Emacs should work. --display. */ char *display = NULL; +/* Nonzero means open a new Emacs frame on the current terminal. */ +int here = 0; + /* If non-NULL, the name of an editor to fallback to if the server is not running. --alternate-editor. */ const char * alternate_editor = NULL; @@ -78,6 +129,7 @@ { "eval", no_argument, NULL, 'e' }, { "help", no_argument, NULL, 'H' }, { "version", no_argument, NULL, 'V' }, + { "here", no_argument, NULL, 'h' }, { "alternate-editor", required_argument, NULL, 'a' }, { "socket-name", required_argument, NULL, 's' }, { "display", required_argument, NULL, 'd' }, @@ -95,7 +147,7 @@ while (1) { int opt = getopt_long (argc, argv, - "VHnea:s:d:", longopts, 0); + "VHnea:s:d:h", longopts, 0); if (opt == EOF) break; @@ -134,6 +186,10 @@ exit (0); break; + case 'h': + here = 1; + break; + case 'H': print_help_and_exit (); break; @@ -144,6 +200,12 @@ break; } } + + if (here) { + nowait = 0; + display = 0; + } + } void @@ -157,6 +219,7 @@ The following OPTIONS are accepted:\n\ -V, --version Just print a version info and return\n\ -H, --help Print this usage information message\n\ +-h, --here Open a new Emacs frame on the current terminal\n\ -n, --no-wait Don't wait for the server to return\n\ -e, --eval Evaluate the FILE arguments as ELisp expressions\n\ -d, --display=DISPLAY Visit the file in the given display\n\ @@ -247,6 +310,464 @@ } } + +#ifdef HAVE_TERMIOS + +/* Adapted from emacs_get_tty() in sysdep.c. */ +int +ec_get_tty (int fd, struct termios *settings) +{ + bzero (settings, sizeof (struct termios)); + if (tcgetattr (fd, settings) < 0) + return -1; + return 0; +} + +/* Adapted from emacs_set_tty() in sysdep.c. */ +int +ec_set_tty (int fd, struct termios *settings, int flushp) +{ + /* Set the primary parameters - baud rate, character size, etcetera. */ + + int i; + /* We have those nifty POSIX tcmumbleattr functions. + William J. Smith <wjs@wiis.wang.com> writes: + "POSIX 1003.1 defines tcsetattr to return success if it was + able to perform any of the requested actions, even if some + of the requested actions could not be performed. + We must read settings back to ensure tty setup properly. + AIX requires this to keep tty from hanging occasionally." */ + /* This make sure that we don't loop indefinitely in here. */ + for (i = 0 ; i < 10 ; i++) + if (tcsetattr (fd, flushp ? TCSAFLUSH : TCSADRAIN, settings) < 0) + { + if (errno == EINTR) + continue; + else + return -1; + } + else + { + struct termios new; + + bzero (&new, sizeof (new)); + /* Get the current settings, and see if they're what we asked for. */ + tcgetattr (fd, &new); + /* We cannot use memcmp on the whole structure here because under + * aix386 the termios structure has some reserved field that may + * not be filled in. + */ + if ( new.c_iflag == settings->c_iflag + && new.c_oflag == settings->c_oflag + && new.c_cflag == settings->c_cflag + && new.c_lflag == settings->c_lflag + && memcmp (new.c_cc, settings->c_cc, NCCS) == 0) + break; + else + continue; + } + return 0; +} + +int master; +char *pty_name; + +struct termios old_tty; +struct termios tty; +int old_tty_valid; + +int tty_erase_char; +int flow_control = 0; +int meta_key = 0; +char _sobuf[BUFSIZ]; +int emacs_pid; + +/* Adapted from init_sys_modes() in sysdep.c. */ +int +init_tty () +{ + if (! isatty (0)) + { + fprintf (stderr, "%s: Input is not a terminal", "init_tty"); + return 0; + } + + ec_get_tty (0, &old_tty); + old_tty_valid = 1; + tty = old_tty; + + tty_erase_char = old_tty.c_cc[VERASE]; + + tty.c_iflag |= (IGNBRK); /* Ignore break condition */ + tty.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ +#ifdef INLCR + tty.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */ +#endif +#ifdef ISTRIP + tty.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */ +#endif + tty.c_lflag &= ~ECHO; /* Disable echo */ + tty.c_lflag &= ~ICANON; /* Disable erase/kill processing */ +#ifdef IEXTEN + tty.c_lflag &= ~IEXTEN; /* Disable other editing characters. */ +#endif + tty.c_lflag |= ISIG; /* Enable signals */ + if (flow_control) + { + tty.c_iflag |= IXON; /* Enable start/stop output control */ +#ifdef IXANY + tty.c_iflag &= ~IXANY; +#endif /* IXANY */ + } + else + tty.c_iflag &= ~IXON; /* Disable start/stop output control */ + tty.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL + on output */ + tty.c_oflag &= ~TAB3; /* Disable tab expansion */ +#ifdef CS8 + if (meta_key) + { + tty.c_cflag |= CS8; /* allow 8th bit on input */ + tty.c_cflag &= ~PARENB; /* Don't check parity */ + } +#endif + tty.c_cc[VINTR] = CDISABLE; + tty.c_cc[VQUIT] = CDISABLE; + tty.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ + tty.c_cc[VTIME] = 0; /* no matter how long that takes. */ +#ifdef VSWTCH + tty.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use of C-z */ +#endif + +#ifdef VSUSP + tty.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */ +#endif /* VSUSP */ +#ifdef V_DSUSP + tty.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */ +#endif /* V_DSUSP */ +#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */ + tty.c_cc[VDSUSP] = CDISABLE; +#endif /* VDSUSP */ +#ifdef VLNEXT + tty.c_cc[VLNEXT] = CDISABLE; +#endif /* VLNEXT */ +#ifdef VREPRINT + tty.c_cc[VREPRINT] = CDISABLE; +#endif /* VREPRINT */ +#ifdef VWERASE + tty.c_cc[VWERASE] = CDISABLE; +#endif /* VWERASE */ +#ifdef VDISCARD + tty.c_cc[VDISCARD] = CDISABLE; +#endif /* VDISCARD */ + + if (flow_control) + { +#ifdef VSTART + tty.c_cc[VSTART] = '\021'; +#endif /* VSTART */ +#ifdef VSTOP + tty.c_cc[VSTOP] = '\023'; +#endif /* VSTOP */ + } + else + { +#ifdef VSTART + tty.c_cc[VSTART] = CDISABLE; +#endif /* VSTART */ +#ifdef VSTOP + tty.c_cc[VSTOP] = CDISABLE; +#endif /* VSTOP */ + } + +#ifdef SET_LINE_DISCIPLINE + /* Need to explicitly request TERMIODISC line discipline or + Ultrix's termios does not work correctly. */ + tty.c_line = SET_LINE_DISCIPLINE; +#endif + +#ifdef AIX +#ifndef IBMR2AIX + /* AIX enhanced edit loses NULs, so disable it. */ + tty.c_line = 0; + tty.c_iflag &= ~ASCEDIT; +#else + tty.c_cc[VSTRT] = 255; + tty.c_cc[VSTOP] = 255; + tty.c_cc[VSUSP] = 255; + tty.c_cc[VDSUSP] = 255; +#endif /* IBMR2AIX */ + if (flow_control) + { +#ifdef VSTART + tty.c_cc[VSTART] = '\021'; +#endif /* VSTART */ +#ifdef VSTOP + tty.c_cc[VSTOP] = '\023'; +#endif /* VSTOP */ + } + /* Also, PTY overloads NUL and BREAK. + don't ignore break, but don't signal either, so it looks like NUL. + This really serves a purpose only if running in an XTERM window + or via TELNET or the like, but does no harm elsewhere. */ + tty.c_iflag &= ~IGNBRK; + tty.c_iflag &= ~BRKINT; +#endif /* AIX */ + + ec_set_tty (0, &tty, 0); + + /* This code added to insure that, if flow-control is not to be used, + we have an unlocked terminal at the start. */ + +#ifdef TCXONC + if (!flow_control) ioctl (0, TCXONC, 1); +#endif +#ifndef APOLLO +#ifdef TIOCSTART + if (!flow_control) ioctl (0, TIOCSTART, 0); +#endif +#endif + +#if defined (HAVE_TERMIOS) || defined (HPUX9) +#ifdef TCOON + if (!flow_control) tcflow (0, TCOON); +#endif +#endif + +#ifdef _IOFBF + /* This symbol is defined on recent USG systems. + Someone says without this call USG won't really buffer the file + even with a call to setbuf. */ + setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf); +#else + setbuf (stdout, (char *) _sobuf); +#endif + + return 1; +} + +void +window_change () +{ + int width = 0, height = 0; + +#ifdef TIOCGWINSZ + { + /* BSD-style. */ + struct winsize size; + + if (ioctl (0, TIOCGWINSZ, &size) == -1) + width = height = 0; + else + { + width = size.ws_col; + height = size.ws_row; + } + } +#else +#ifdef TIOCGSIZE + { + /* SunOS - style. */ + struct ttysize size; + + if (ioctl (0, TIOCGSIZE, &size) == -1) + width = height = 0; + else + { + width = size.ts_cols; + height = size.ts_lines; + } + } +#endif /* not SunOS-style */ +#endif /* not BSD-style */ + +#ifdef TIOCSWINSZ + { + /* BSD-style. */ + struct winsize size; + size.ws_row = height; + size.ws_col = width; + + ioctl (master, TIOCSWINSZ, &size); + } +#else +#ifdef TIOCSSIZE + { + /* SunOS - style. */ + struct ttysize size; + size.ts_lines = height; + size.ts_cols = width; + + ioctl (master, TIOCGSIZE, &size); + } +#endif /* not SunOS-style */ +#endif /* not BSD-style */ + + if (width != 0 && height != 0) + kill (emacs_pid, SIGWINCH); +} + +int in_conversation = 0; +int quit_conversation = 0; + +SIGTYPE +hang_up_signal (int signalnum) +{ + int old_errno = errno; + + if (! in_conversation) + return; + + quit_conversation = 1; + + errno = old_errno; +} + +SIGTYPE +window_change_signal (int signalnum) +{ + int old_errno = errno; + + if (! in_conversation) + goto end; + + window_change(); + + end: + signal (SIGWINCH, window_change_signal); + errno = old_errno; +} + +int +init_signals () +{ + /* Set up signal handlers. */ + signal (SIGWINCH, window_change_signal); + signal (SIGHUP, hang_up_signal); + + return 1; +} + + + +/* Adapted from reset_sys_modes in sysdep.c. */ +int +reset_tty () +{ + fflush (stdout); +#ifdef BSD_SYSTEM +#ifndef BSD4_1 + /* Avoid possible loss of output when changing terminal modes. */ + fsync (fileno (stdout)); +#endif +#endif + +#ifdef F_SETFL +#ifdef O_NDELAY + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NDELAY); +#endif +#endif /* F_SETFL */ + + if (old_tty_valid) + while (ec_set_tty (0, &old_tty, 0) < 0 && errno == EINTR) + ; + + return 1; +} + + +int +init_pty () +{ + master = getpt (); + if (master < 0) + return 0; + + if (grantpt (master) < 0 || unlockpt (master) < 0) + goto close_master; + pty_name = strdup (ptsname (master)); + if (! pty_name) + goto close_master; + + /* Propagate window size. */ + window_change (); + + return 1; + + close_master: + close (master); + return 0; +} + +int +copy_from_to (int in, int out, int sigio) +{ + static char buf[BUFSIZ]; + int nread = read (in, &buf, BUFSIZ); + if (nread == 0) + return 1; /* EOF */ + else if (nread < 0 && errno != EAGAIN) + return 0; /* Error */ + else if (nread > 0) + { + int r = 0; + int written = 0; + + do { + r = write (out, &buf, nread); + } while ((r < 0 && errno == EAGAIN) + || (r > 0 && (written += r) && written != nread)); + + if (r < 0) + return 0; /* Error */ + + if (sigio) + { + kill (emacs_pid, SIGIO); + } + } + return 1; +} + +int +pty_conversation () +{ + fd_set set; + + in_conversation = 1; + + while (! quit_conversation) { + int res; + + FD_ZERO (&set); + FD_SET (master, &set); + FD_SET (1, &set); + res = select (FD_SETSIZE, &set, NULL, NULL, NULL); + if (res < 0) + { + if (errno != EINTR) + return 0; + } + else if (res > 0) + { + if (FD_ISSET (master, &set)) + { + /* Copy Emacs output to stdout. */ + if (! copy_from_to (master, 0, 0)) + return 1; + } + if (FD_ISSET (1, &set)) + { + /* Forward user input to Emacs. */ + if (! copy_from_to (1, master, 1)) + return 1; + } + } + } + return 1; +} + +#endif /* HAVE_TERMIOS */ #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM) @@ -312,7 +833,7 @@ /* Process options. */ decode_options (argc, argv); - if ((argc - optind < 1) && !eval) + if ((argc - optind < 1) && !eval && !here) { fprintf (stderr, "%s: file name or argument required\n", progname); fprintf (stderr, "Try `%s --help' for more information\n", progname); @@ -484,6 +1005,38 @@ fprintf (out, " "); } + if (here) + { + if (! init_signals ()) + { + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + fail (argc, argv); + } + + if (! init_tty ()) + { + reset_tty (); + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + fail (argc, argv); + } + + if (! init_pty ()) + { + reset_tty (); + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + fail (argc, argv); + } + + fprintf (out, "-pty "); + quote_file_name (pty_name, out); + fprintf (out, " "); + quote_file_name (getenv("TERM"), out); + fprintf (out, " "); + } + if ((argc - optind > 0)) { for (i = optind; i < argc; i++) @@ -512,11 +1065,14 @@ } else { - while ((str = fgets (string, BUFSIZ, stdin))) - { - quote_file_name (str, out); - } - fprintf (out, " "); + if (!here) + { + while ((str = fgets (string, BUFSIZ, stdin))) + { + quote_file_name (str, out); + } + fprintf (out, " "); + } } fprintf (out, "\n"); @@ -524,8 +1080,37 @@ /* Maybe wait for an answer. */ if (nowait) - return 0; + { + reset_tty (); + return 0; + } + if (here) + { + /* First of all, get the pid of the Emacs process. + XXX Is there is some nifty libc/kernel feature for doing this? + */ + str = fgets (string, BUFSIZ, in); + emacs_pid = atoi (str); + if (emacs_pid == 0) + { + reset_tty (); + fprintf (stderr, "%s: %s\n", argv[0], str); + fail (argc, argv); + } + + if (! pty_conversation ()) + { + reset_tty (); + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + fail (argc, argv); + } + close (master); + reset_tty (); + return 0; + } + if (!eval) { printf ("Waiting for Emacs..."); @@ -546,6 +1131,7 @@ printf ("\n"); fflush (stdout); + reset_tty (); return 0; }
--- a/lib-src/rcs2log Wed Dec 24 23:32:12 2003 +0000 +++ b/lib-src/rcs2log Sun Dec 28 16:03:57 2003 +0000 @@ -29,7 +29,7 @@ Report bugs to <bug-gnu-emacs@gnu.org>.' -Id='$Id: rcs2log,v 1.50 2002/02/03 17:31:31 eggert Exp $' +Id='$Id: rcs2log,v 1.51 2003/09/01 15:45:03 miles Exp $' # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2001, 2002 # Free Software Foundation, Inc.
--- a/lib-src/vcdiff Wed Dec 24 23:32:12 2003 +0000 +++ b/lib-src/vcdiff Sun Dec 28 16:03:57 2003 +0000 @@ -23,7 +23,7 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # -# $Id: vcdiff,v 1.7 2001/02/20 12:36:28 gerd Exp $ +# $Id: vcdiff,v 1.8 2003/09/01 15:45:03 miles Exp $ # DIFF="diff"
--- a/lisp/allout.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/allout.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Author: Ken Manheimer <klm@zope.com> ;; Maintainer: Ken Manheimer <klm@zope.com> ;; Created: Dec 1991 - first release to usenet -;; Version: $Id: allout.el,v 1.44 2003/09/01 15:45:04 miles Exp $|| +;; Version: $Id: allout.el,v 1.45 2003/10/16 16:28:30 eliz Exp $|| ;; Keywords: outlines mode wp languages ;; This file is part of GNU Emacs. @@ -508,7 +508,7 @@ ;;;_ : Version ;;;_ = allout-version (defvar allout-version - (let ((rcs-rev "$Revision: 1.44 $")) + (let ((rcs-rev "$Revision: 1.45 $")) (condition-case err (save-match-data (string-match "Revision: \\([0-9]+\\.[0-9]+\\)" rcs-rev)
--- a/lisp/calendar/todo-mode.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/calendar/todo-mode.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Author: Oliver Seidel <os10000@seidel-space.de> ;; [Not clear the above works, July 2000] ;; Created: 2 Aug 1997 -;; Version: $Id: todo-mode.el,v 1.50 2001/12/11 07:36:30 pj Exp $ +;; Version: $Id: todo-mode.el,v 1.51 2003/09/01 15:45:19 miles Exp $ ;; Keywords: calendar, todo ;; This file is part of GNU Emacs. @@ -97,7 +97,7 @@ ;; ;; Which version of todo-mode.el does this documentation refer to? ;; -;; $Id: todo-mode.el,v 1.50 2001/12/11 07:36:30 pj Exp $ +;; $Id: todo-mode.el,v 1.51 2003/09/01 15:45:19 miles Exp $ ;; ;; Pre-Requisites ;;
--- a/lisp/emacs-lisp/bytecomp.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/emacs-lisp/bytecomp.el Sun Dec 28 16:03:57 2003 +0000 @@ -10,7 +10,7 @@ ;;; This version incorporates changes up to version 2.10 of the ;;; Zawinski-Furuseth compiler. -(defconst byte-compile-version "$Revision: 2.138 $") +(defconst byte-compile-version "$Revision: 2.139 $") ;; This file is part of GNU Emacs.
--- a/lisp/emacs-lisp/cl-specs.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/emacs-lisp/cl-specs.el Sun Dec 28 16:03:57 2003 +0000 @@ -7,7 +7,7 @@ ;; LCD Archive Entry: ;; cl-specs.el|Daniel LaLiberte|liberte@holonexus.org ;; |Edebug specs for cl.el -;; |$Date: 2003/06/16 16:27:27 $|1.1| +;; |$Date: 2003/09/01 15:45:20 $|1.1| ;; This file is part of GNU Emacs.
--- a/lisp/emacs-lisp/eldoc.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/emacs-lisp/eldoc.el Sun Dec 28 16:03:57 2003 +0000 @@ -7,7 +7,7 @@ ;; Keywords: extensions ;; Created: 1995-10-06 -;; $Id: eldoc.el,v 1.26 2003/09/01 15:45:22 miles Exp $ +;; $Id: eldoc.el,v 1.27 2003/09/06 17:32:31 fx Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/forms.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/forms.el Sun Dec 28 16:03:57 2003 +0000 @@ -301,10 +301,10 @@ (provide 'forms) ;;; official (provide 'forms-mode) ;;; for compatibility -(defconst forms-version (substring "$Revision: 2.48 $" 11 -2) +(defconst forms-version (substring "$Revision: 2.49 $" 11 -2) "The version number of forms-mode (as string). The complete RCS id is: - $Id: forms.el,v 2.48 2003/05/29 23:53:21 monnier Exp $") + $Id: forms.el,v 2.49 2003/09/01 15:45:12 miles Exp $") (defcustom forms-mode-hook nil "Hook run upon entering Forms mode."
--- a/lisp/frame.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/frame.el Sun Dec 28 16:03:57 2003 +0000 @@ -558,6 +558,24 @@ (error "Invalid display, not HOST:SERVER or HOST:SERVER.SCREEN")) (make-frame (cons (cons 'display display) parameters))) +;;;###autoload +(defun make-frame-on-tty (device type &optional parameters) + "Make a frame on terminal DEVICE which is of type TYPE (e.g., \"xterm\"). +The optional third argument PARAMETERS specifies additional frame parameters. + +DEVICE must be a proxy psudo terminal created by emacsclient, +otherwise there will be problems with terminal input and window +resizes. (The kernel notifies processes about pending input or +terminal resizes only on the controlling terminal, so we need +emacsclient to sit on the real terminal device, create SIGIO +signals upon terminal input, and forward SIGWINCH signals to +us.)" + (unless device + (error "Invalid terminal device")) + (unless type + (error "Invalid terminal type")) + (make-frame `((tty . ,device) (tty-type . ,type) . ,parameters))) + (defun make-frame-command () "Make a new frame, and select it if the terminal displays only one frame." (interactive)
--- a/lisp/ldefs-boot.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/ldefs-boot.el Sun Dec 28 16:03:57 2003 +0000 @@ -78,7 +78,7 @@ (autoload (quote ada-mode) "ada-mode" "\ Ada mode is the major mode for editing Ada code. -This version was built on $Date: 2003/09/30 12:54:32 $. +This version was built on $Date: 2003/11/17 19:02:52 $. Bindings are as follows: (Note: 'LFD' is control-j.) \\{ada-mode-map}
--- a/lisp/mail/metamail.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/mail/metamail.el Sun Dec 28 16:03:57 2003 +0000 @@ -3,7 +3,7 @@ ;; Copyright (C) 1993, 1996 Free Software Foundation, Inc. ;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp> -;; Version: $Id: metamail.el,v 1.15 2003/02/04 13:14:00 lektu Exp $ +;; Version: $Id: metamail.el,v 1.16 2003/09/01 15:45:30 miles Exp $ ;; Keywords: mail, news, mime, multimedia ;; This file is part of GNU Emacs.
--- a/lisp/net/rlogin.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/net/rlogin.el Sun Dec 28 16:03:57 2003 +0000 @@ -6,7 +6,7 @@ ;; Maintainer: Noah Friedman <friedman@splode.com> ;; Keywords: unix, comm -;; $Id: rlogin.el,v 1.4 2003/05/06 17:46:28 lektu Exp $ +;; $Id: rlogin.el,v 1.5 2003/09/01 15:45:33 miles Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/obsolete/rsz-mini.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/obsolete/rsz-mini.el Sun Dec 28 16:03:57 2003 +0000 @@ -7,7 +7,7 @@ ;; Maintainer: Noah Friedman <friedman@splode.com> ;; Keywords: minibuffer, window, frame, display -;; $Id: rsz-mini.el,v 1.1 2001/08/30 07:29:18 gerd Exp $ +;; $Id: rsz-mini.el,v 1.2 2003/09/01 15:45:33 miles Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/progmodes/ada-mode.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/ada-mode.el Sun Dec 28 16:03:57 2003 +0000 @@ -1071,7 +1071,7 @@ ;;;###autoload (defun ada-mode () "Ada mode is the major mode for editing Ada code. -This version was built on $Date: 2003/09/01 15:45:34 $. +This version was built on $Date: 2003/09/30 12:54:32 $. Bindings are as follows: (Note: 'LFD' is control-j.) \\{ada-mode-map}
--- a/lisp/progmodes/ada-prj.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/ada-prj.el Sun Dec 28 16:03:57 2003 +0000 @@ -3,7 +3,7 @@ ;; Copyright (C) 1998, 99, 2000-2003 Free Software Foundation, Inc. ;; Author: Emmanuel Briot <briot@gnat.com> -;; Ada Core Technologies's version: $Revision: 1.12 $ +;; Ada Core Technologies's version: $Revision: 1.13 $ ;; Keywords: languages, ada, project file ;; This file is part of GNU Emacs.
--- a/lisp/progmodes/ada-stmt.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/ada-stmt.el Sun Dec 28 16:03:57 2003 +0000 @@ -3,7 +3,7 @@ ;; Copyright(C) 1987, 93, 94, 96, 97, 98, 99, 2000 ;; Free Software Foundation, Inc. -;; Ada Core Technologies's version: $Revision: 1.16 $ +;; Ada Core Technologies's version: $Revision: 1.17 $ ;; This file is part of GNU Emacs.
--- a/lisp/progmodes/autoconf.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/autoconf.el Sun Dec 28 16:03:57 2003 +0000 @@ -4,7 +4,7 @@ ;; Author: Dave Love <fx@gnu.org> ;; Keywords: languages -;; $Revision: 1.5 $ +;; $Revision: 1.6 $ ;; This file is part of GNU Emacs.
--- a/lisp/progmodes/delphi.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/delphi.el Sun Dec 28 16:03:57 2003 +0000 @@ -65,7 +65,7 @@ (provide 'delphi) (defconst delphi-version - (let ((revision "$Revision: 3.10 $")) + (let ((revision "$Revision: 3.11 $")) (string-match ": \\([^ ]+\\)" revision) (match-string 1 revision)) "Version of this delphi mode.")
--- a/lisp/progmodes/idlw-shell.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/idlw-shell.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Chris Chase <chase@att.com> ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu> ;; Version: 4.15 -;; Date: $Date: 2002/10/17 15:41:01 $ +;; Date: $Date: 2003/09/01 15:45:35 $ ;; Keywords: processes ;; This file is part of GNU Emacs.
--- a/lisp/progmodes/idlw-toolbar.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/idlw-toolbar.el Sun Dec 28 16:03:57 2003 +0000 @@ -4,7 +4,7 @@ ;; Author: Carsten Dominik <dominik@astro.uva.nl> ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu> ;; Version: 4.15 -;; Date: $Date: 2003/02/04 13:24:35 $ +;; Date: $Date: 2003/09/01 15:45:35 $ ;; Keywords: processes ;; This file is part of GNU Emacs.
--- a/lisp/progmodes/idlwave.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/idlwave.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Chris Chase <chase@att.com> ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu> ;; Version: 4.15 -;; Date: $Date: 2003/07/21 21:36:29 $ +;; Date: $Date: 2003/09/01 15:45:35 $ ;; Keywords: languages ;; This file is part of GNU Emacs.
--- a/lisp/progmodes/tcl.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/tcl.el Sun Dec 28 16:03:57 2003 +0000 @@ -6,7 +6,7 @@ ;; Author: Tom Tromey <tromey@redhat.com> ;; Chris Lindblad <cjl@lcs.mit.edu> ;; Keywords: languages tcl modes -;; Version: $Revision: 1.75 $ +;; Version: $Revision: 1.76 $ ;; This file is part of GNU Emacs.
--- a/lisp/progmodes/vhdl-mode.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/progmodes/vhdl-mode.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Authors: Reto Zimmermann <reto@gnu.org> ;; Rodney J. Whitby <software.vhdl-mode@rwhitby.net> ;; Maintainer: Reto Zimmermann <reto@gnu.org> -;; RCS: $Id: vhdl-mode.el,v 1.20 2003/03/05 07:50:38 lektu Exp $ +;; RCS: $Id: vhdl-mode.el,v 1.21 2003/09/01 15:45:35 miles Exp $ ;; Keywords: languages vhdl ;; WWW: http://opensource.ethz.ch/emacs/vhdl-mode.html
--- a/lisp/recentf.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/recentf.el Sun Dec 28 16:03:57 2003 +0000 @@ -8,7 +8,7 @@ ;; Maintainer: FSF ;; Keywords: files -(defconst recentf-version "$Revision: 1.27 $") +(defconst recentf-version "$Revision: 1.28 $") ;; This file is part of GNU Emacs.
--- a/lisp/server.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/server.el Sun Dec 28 16:03:57 2003 +0000 @@ -319,6 +319,17 @@ (server-select-display display) (error (process-send-string proc (nth 1 err)) (setq request ""))))) + ;; Open a new frame at the client. ARG is the name of the pseudo tty. + ((and (equal "-pty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) + (let ((pty (server-unquote-arg (match-string 1 request))) + (type (server-unquote-arg (match-string 2 request)))) + (setq request (substring request (match-end 0))) + (condition-case err + (let ((frame (make-terminal-frame `((tty . ,pty) (tty-type . ,type))))) + (process-send-string proc (concat (number-to-string (emacs-pid)) "\n")) + (select-frame frame)) + (error (process-send-string proc (nth 1 err)) + (setq request ""))))) ;; ARG is a line number option. ((string-match "\\`\\+[0-9]+\\'" arg) (setq lineno (string-to-int (substring arg 1)))) @@ -334,12 +345,15 @@ (if coding-system (setq arg (decode-coding-string arg coding-system))) (if eval - (let ((v (eval (car (read-from-string arg))))) - (when v - (with-temp-buffer - (let ((standard-output (current-buffer))) - (pp v) - (process-send-region proc (point-min) (point-max)))))) + (condition-case err + (let ((v (eval (car (read-from-string arg))))) + (when v + (with-temp-buffer + (let ((standard-output (current-buffer))) + (pp v) + (process-send-region proc (point-min) (point-max)))))) + (error (process-send-string proc (concat "*Error* " (error-message-string err))))) + ;; ARG is a file name. ;; Collapse multiple slashes to single slashes. (setq arg (command-line-normalize-file-name arg))
--- a/lisp/smerge-mode.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/smerge-mode.el Sun Dec 28 16:03:57 2003 +0000 @@ -4,7 +4,7 @@ ;; Author: Stefan Monnier <monnier@cs.yale.edu> ;; Keywords: merge diff3 cvs conflict -;; Revision: $Id$ +;; Revision: $Id: smerge-mode.el,v 1.24 2003/10/06 16:34:59 fx Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/type-break.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/type-break.el Sun Dec 28 16:03:57 2003 +0000 @@ -8,7 +8,7 @@ ;; Status: Works in GNU Emacs 19.25 or later, some versions of XEmacs ;; Created: 1994-07-13 -;; $Id: type-break.el,v 1.28 2003/05/28 11:25:44 rms Exp $ +;; $Id: type-break.el,v 1.29 2003/09/01 15:45:17 miles Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/vc-cvs.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/vc-cvs.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Author: FSF (see vc.el for full credits) ;; Maintainer: Andre Spiegel <spiegel@gnu.org> -;; $Id$ +;; $Id: vc-cvs.el,v 1.66 2003/10/01 13:22:53 fx Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/vc-hooks.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/vc-hooks.el Sun Dec 28 16:03:57 2003 +0000 @@ -6,7 +6,7 @@ ;; Author: FSF (see vc.el for full credits) ;; Maintainer: Andre Spiegel <spiegel@gnu.org> -;; $Id: vc-hooks.el,v 1.159 2003/08/30 10:56:38 eliz Exp $ +;; $Id: vc-hooks.el,v 1.160 2003/09/01 15:45:17 miles Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/vc-rcs.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/vc-rcs.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Author: FSF (see vc.el for full credits) ;; Maintainer: Andre Spiegel <spiegel@gnu.org> -;; $Id: vc-rcs.el,v 1.37 2003/05/08 19:24:56 monnier Exp $ +;; $Id: vc-rcs.el,v 1.38 2003/09/01 15:45:17 miles Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/vc-sccs.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/vc-sccs.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Author: FSF (see vc.el for full credits) ;; Maintainer: Andre Spiegel <spiegel@gnu.org> -;; $Id: vc-sccs.el,v 1.23 2003/08/12 18:01:21 spiegel Exp $ +;; $Id: vc-sccs.el,v 1.24 2003/09/01 15:45:17 miles Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/vc.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/vc.el Sun Dec 28 16:03:57 2003 +0000 @@ -7,7 +7,7 @@ ;; Maintainer: Andre Spiegel <spiegel@gnu.org> ;; Keywords: tools -;; $Id: vc.el,v 1.360 2003/09/01 15:45:17 miles Exp $ +;; $Id: vc.el,v 1.361 2003/12/24 23:18:10 uid66361 Exp $ ;; This file is part of GNU Emacs.
--- a/lisp/whitespace.el Wed Dec 24 23:32:12 2003 +0000 +++ b/lisp/whitespace.el Sun Dec 28 16:03:57 2003 +0000 @@ -5,7 +5,7 @@ ;; Author: Rajesh Vaidheeswarran <rv@gnu.org> ;; Keywords: convenience -;; $Id: whitespace.el,v 1.26 2003/09/01 15:45:18 miles Exp $ +;; $Id: whitespace.el,v 1.27 2003/09/29 18:05:31 rv Exp $ ;; This file is part of GNU Emacs. ;; GNU Emacs is free software; you can redistribute it and/or modify
--- a/lispintro/mkinstalldirs Wed Dec 24 23:32:12 2003 +0000 +++ b/lispintro/mkinstalldirs Sun Dec 28 16:03:57 2003 +0000 @@ -4,7 +4,7 @@ # Created: 1993-05-16 # Public domain -# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $ +# $Id: mkinstalldirs,v 1.1 2001/11/24 08:45:51 eliz Exp $ errstatus=0
--- a/lispref/mkinstalldirs Wed Dec 24 23:32:12 2003 +0000 +++ b/lispref/mkinstalldirs Sun Dec 28 16:03:57 2003 +0000 @@ -4,7 +4,7 @@ # Created: 1993-05-16 # Public domain -# $Id: mkinstalldirs,v 1.10 1996/05/03 07:37:52 friedman Exp $ +# $Id: mkinstalldirs,v 1.1 2000/07/28 12:48:04 gerd Exp $ errstatus=0
--- a/man/eshell.texi Wed Dec 24 23:32:12 2003 +0000 +++ b/man/eshell.texi Sun Dec 28 16:03:57 2003 +0000 @@ -1,5 +1,5 @@ \input texinfo @c -*-texinfo-*- -@c "@(#)$Name: $:$Id: eshell.texi,v 1.19 2003/09/01 15:45:45 miles Exp $" +@c "@(#)$Name: $:$Id: eshell.texi,v 1.20 2003/11/26 17:12:11 ttn Exp $" @c %**start of header @setfilename ../info/eshell @settitle Eshell: The Emacs Shell
--- a/man/info.texi Wed Dec 24 23:32:12 2003 +0000 +++ b/man/info.texi Sun Dec 28 16:03:57 2003 +0000 @@ -6,7 +6,7 @@ @syncodeindex vr cp @syncodeindex ky cp @comment %**end of header -@comment $Id: info.texi,v 1.36 2003/09/21 20:13:23 karl Exp $ +@comment $Id: info.texi,v 1.37 2003/10/27 00:01:25 karl Exp $ @copying This file describes how to use Info, the on-line, menu-driven GNU
--- a/man/mh-e.texi Wed Dec 24 23:32:12 2003 +0000 +++ b/man/mh-e.texi Sun Dec 28 16:03:57 2003 +0000 @@ -1,5 +1,5 @@ \input texinfo @c -*-texinfo-*- -@c $Id: mh-e.texi,v 1.14 2003/02/04 14:53:28 lektu Exp $ +@c $Id: mh-e.texi,v 1.15 2003/09/01 15:45:46 miles Exp $ @c %**start of header @setfilename ../info/mh-e @settitle mh-e
--- a/man/pcl-cvs.texi Wed Dec 24 23:32:12 2003 +0000 +++ b/man/pcl-cvs.texi Sun Dec 28 16:03:57 2003 +0000 @@ -1,5 +1,5 @@ \input texinfo @c -*-texinfo-*- -@c "@(#)$Name: $:$Id: pcl-cvs.texi,v 1.22 2003/09/29 13:44:26 ttn Exp $" +@c "@(#)$Name: $:$Id: pcl-cvs.texi,v 1.23 2003/09/30 20:40:50 rms Exp $" @c %**start of header @setfilename ../info/pcl-cvs @settitle PCL-CVS --- Emacs Front-End to CVS
--- a/man/speedbar.texi Wed Dec 24 23:32:12 2003 +0000 +++ b/man/speedbar.texi Sun Dec 28 16:03:57 2003 +0000 @@ -1,5 +1,5 @@ \input texinfo @c -*-texinfo-*- -@c $Id: speedbar.texi,v 1.12 2003/09/01 15:45:46 miles Exp $ +@c $Id: speedbar.texi,v 1.13 2003/10/08 22:02:52 nickrob Exp $ @setfilename ../info/speedbar @settitle Speedbar: File/Tag summarizing utility
--- a/man/woman.texi Wed Dec 24 23:32:12 2003 +0000 +++ b/man/woman.texi Sun Dec 28 16:03:57 2003 +0000 @@ -1,5 +1,5 @@ \input texinfo @c -*-texinfo-*- -@c $Id: woman.texi,v 1.15 2003/09/30 20:42:15 rms Exp $ +@c $Id: woman.texi,v 1.16 2003/11/02 07:01:19 eliz Exp $ @c %**start of header @setfilename ../info/woman @settitle WoMan: Browse Unix Manual Pages ``W.O. (without) Man''
--- a/mkinstalldirs Wed Dec 24 23:32:12 2003 +0000 +++ b/mkinstalldirs Sun Dec 28 16:03:57 2003 +0000 @@ -4,7 +4,7 @@ # Created: 1993-05-16 # Public domain -# $Id: mkinstalldirs,v 1.1 2001/02/02 13:04:53 gerd Exp $ +# $Id: mkinstalldirs,v 1.2 2001/02/02 13:09:26 gerd Exp $ errstatus=0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nt/.arch-inventory Sun Dec 28 16:03:57 2003 +0000 @@ -0,0 +1,3 @@ +source ^subdirs\.el$ + +# arch-tag: 01b87183-9d94-4b6b-93cb-fece25c4eec9
--- a/oldXMenu/Activate.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/Activate.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/emacs/emacs/oldXMenu/Activate.c,v 1.5 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/Activate.c,v 1.6 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ #include "copyright.h"
--- a/oldXMenu/AddPane.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/AddPane.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/AddPane.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/AddPane.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/AddSel.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/AddSel.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/AddSel.c,v 1.3 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/AddSel.c,v 1.4 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/ChgPane.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/ChgPane.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/ChgPane.c,v 1.1 1999/10/03 19:34:53 fx Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/ChgPane.c,v 1.2 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/ChgSel.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/ChgSel.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/ChgSel.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/ChgSel.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/Create.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/Create.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/emacs/emacs/oldXMenu/Create.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/Create.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ #include "copyright.h"
--- a/oldXMenu/DelPane.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/DelPane.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/DelPane.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/DelPane.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/DelSel.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/DelSel.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/DelSel.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/DelSel.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/Destroy.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/Destroy.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/Destroy.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/Destroy.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/Error.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/Error.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/Error.c,v 1.1 1999/10/03 19:35:00 fx Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/Error.c,v 1.2 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/EvHand.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/EvHand.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/EvHand.c,v 1.1 1999/10/03 19:35:01 fx Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/EvHand.c,v 1.2 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/FindPane.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/FindPane.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/FindPane.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/FindPane.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/FindSel.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/FindSel.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/FindSel.c,v 1.1 1999/10/03 19:35:03 fx Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/FindSel.c,v 1.2 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/InsPane.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/InsPane.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/InsPane.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/InsPane.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/InsSel.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/InsSel.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/InsSel.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/InsSel.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/Internal.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/Internal.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/Internal.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/Internal.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/Locate.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/Locate.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/Locate.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/Locate.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/Post.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/Post.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/Post.c,v 1.3 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/Post.c,v 1.4 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/Recomp.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/Recomp.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/Recomp.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/Recomp.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/SetAEQ.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/SetAEQ.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/SetAEQ.c,v 1.1 1999/10/03 19:35:12 fx Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/SetAEQ.c,v 1.2 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/SetFrz.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/SetFrz.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/SetFrz.c,v 1.1 1999/10/03 19:35:13 fx Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/SetFrz.c,v 1.2 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/SetPane.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/SetPane.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/SetPane.c,v 1.1 1999/10/03 19:35:14 fx Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/SetPane.c,v 1.2 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/SetSel.c Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/SetSel.c Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/SetSel.c,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/SetSel.c,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/X10.h Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/X10.h Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/emacs/emacs/oldXMenu/X10.h,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/X10.h,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* * Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology *
--- a/oldXMenu/XMenu.h Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/XMenu.h Sun Dec 28 16:03:57 2003 +0000 @@ -1,6 +1,6 @@ #include "copyright.h" -/* $Header: /cvsroot/emacs/emacs/oldXMenu/XMenu.h,v 1.3 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/XMenu.h,v 1.4 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/XMenuInt.h Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/XMenuInt.h Sun Dec 28 16:03:57 2003 +0000 @@ -1,5 +1,5 @@ -/* $Header: /cvsroot/emacs/emacs/oldXMenu/XMenuInt.h,v 1.2 2003/02/04 14:19:01 lektu Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/XMenuInt.h,v 1.3 2003/09/01 15:45:47 miles Exp $ */ /* Copyright Massachusetts Institute of Technology 1985 */ /*
--- a/oldXMenu/copyright.h Wed Dec 24 23:32:12 2003 +0000 +++ b/oldXMenu/copyright.h Sun Dec 28 16:03:57 2003 +0000 @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/emacs/emacs/oldXMenu/copyright.h,v 1.1 1999/10/03 19:35:25 fx Exp $ */ +/* $Header: /cvsroot/emacs/emacs/oldXMenu/copyright.h,v 1.2 2003/09/01 15:45:47 miles Exp $ */ /* Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
--- a/src/Makefile.in Wed Dec 24 23:32:12 2003 +0000 +++ b/src/Makefile.in Sun Dec 28 16:03:57 2003 +0000 @@ -1047,7 +1047,7 @@ charset.o: charset.c charset.h buffer.h coding.h composite.h disptab.h \ $(config_h) coding.o: coding.c coding.h ccl.h buffer.h charset.h intervals.h composite.h window.h $(config_h) -cm.o: cm.c cm.h termhooks.h $(config_h) +cm.o: cm.c frame.h cm.h termhooks.h systty.h termchar.h $(config_h) cmds.o: cmds.c syntax.h buffer.h charset.h commands.h window.h $(config_h) \ msdos.h dispextern.h pre-crt0.o: pre-crt0.c @@ -1055,7 +1055,7 @@ CRT0_COMPILE ${srcdir}/ecrt0.c dired.o: dired.c commands.h buffer.h $(config_h) charset.h coding.h regex.h \ systime.h -dispnew.o: dispnew.c systty.h systime.h commands.h process.h frame.h \ +dispnew.o: dispnew.c systty.h systime.h commands.h process.h frame.h \ window.h buffer.h dispextern.h termchar.h termopts.h termhooks.h cm.h \ disptab.h \ xterm.h blockinput.h atimer.h charset.h msdos.h composite.h keyboard.h \ @@ -1073,12 +1073,12 @@ filelock.o: filelock.c buffer.h systime.h epaths.h $(config_h) filemode.o: filemode.c $(config_h) frame.o: frame.c xterm.h window.h frame.h termhooks.h commands.h keyboard.h \ - blockinput.h atimer.h systime.h buffer.h charset.h fontset.h \ + blockinput.h systty.h atimer.h systime.h buffer.h charset.h fontset.h \ msdos.h dosfns.h dispextern.h $(config_h) fontset.o: dispextern.h fontset.h fontset.c ccl.h buffer.h charset.h frame.h \ keyboard.h $(config_h) getloadavg.o: getloadavg.c $(config_h) -indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \ +indent.o: indent.c frame.h window.h systty.h indent.h buffer.h $(config_h) termchar.h \ termopts.h disptab.h region-cache.h charset.h composite.h dispextern.h \ keyboard.h insdel.o: insdel.c window.h buffer.h $(INTERVAL_SRC) blockinput.h charset.h \ @@ -1110,7 +1110,7 @@ keyboard.h $(config_h) regex.o: regex.c syntax.h buffer.h $(config_h) regex.h category.h charset.h region-cache.o: region-cache.c buffer.h region-cache.h -scroll.o: scroll.c termchar.h dispextern.h frame.h msdos.h keyboard.h \ +scroll.o: scroll.c systty.h termchar.h dispextern.h frame.h msdos.h keyboard.h \ $(config_h) search.o: search.c regex.h commands.h buffer.h region-cache.h syntax.h \ blockinput.h atimer.h systime.h category.h charset.h composite.h $(config_h) @@ -1120,7 +1120,7 @@ sysdep.o: sysdep.c syssignal.h systty.h systime.h syswait.h blockinput.h \ process.h dispextern.h termhooks.h termchar.h termopts.h \ frame.h atimer.h window.h msdos.h dosfns.h keyboard.h $(config_h) -term.o: term.c termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \ +term.o: term.c systty.h termchar.h termhooks.h termopts.h $(config_h) cm.h frame.h \ disptab.h dispextern.h keyboard.h charset.h coding.h ccl.h msdos.h termcap.o: termcap.c $(config_h) terminfo.o: terminfo.c $(config_h) @@ -1134,17 +1134,18 @@ msdos.h $(config_h) widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \ $(srcdir)/../lwlib/lwlib.h $(config_h) -window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \ +window.o: window.c indent.h commands.h frame.h window.h buffer.h systty.h termchar.h \ termhooks.h disptab.h keyboard.h dispextern.h msdos.h composite.h \ $(config_h) xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h coding.h \ - termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \ + systty.h termchar.h frame.h window.h disptab.h termhooks.h charset.h $(config_h) \ msdos.h composite.h fontset.h blockinput.h atimer.h systime.h keymap.h xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \ - window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h $(config_h) + window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h \ + systty.h termchar.h $(config_h) xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \ $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \ - charset.h gtkutil.h $(config_h) + charset.h gtkutil.h systty.h termchar.h $(config_h) xmenu.o: xmenu.c xterm.h termhooks.h window.h dispextern.h frame.h buffer.h \ keyboard.h $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h \ gtkutil.h msdos.h coding.h $(config_h) @@ -1176,7 +1177,7 @@ fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \ frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h print.o: print.c process.h frame.h window.h buffer.h keyboard.h charset.h \ - $(config_h) dispextern.h msdos.h composite.h + $(config_h) dispextern.h msdos.h composite.h systty.h termchar.h intervals.h lread.o: lread.c commands.h keyboard.h buffer.h epaths.h charset.h $(config_h) \ termhooks.h coding.h msdos.h
--- a/src/cm.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/cm.c Sun Dec 28 16:03:57 2003 +0000 @@ -22,8 +22,16 @@ #include <config.h> #include <stdio.h> + +/* For CURTTY */ +#include "lisp.h" +#include "frame.h" + #include "cm.h" #include "termhooks.h" +#include "systty.h" /* For emacs_tty in termchar.h */ +#include "termchar.h" + /* For now, don't try to include termcap.h. On some systems, configure finds a non-standard termcap.h that the main build @@ -41,6 +49,7 @@ extern char *BC, *UP; + int cost; /* sums up costs */ /* ARGSUSED */ @@ -52,13 +61,16 @@ return c; } +/* The terminal to use for low-level output. */ +struct tty_output * current_tty; + int cmputc (c) char c; { - if (termscript) - fputc (c & 0177, termscript); - putchar (c & 0177); + if (TTY_TERMSCRIPT (current_tty)) + putc (c & 0177, TTY_TERMSCRIPT (current_tty)); + putc (c & 0177, TTY_OUTPUT (current_tty)); return c; } @@ -71,9 +83,9 @@ */ static -at (row, col) { - curY = row; - curX = col; +at (tty, row, col) { + curY (tty) = row; + curX (tty) = col; } /* @@ -81,8 +93,8 @@ */ static -addcol (n) { - curX += n; +addcol (tty, n) { + curX (tty) += n; /* * If cursor hit edge of screen, what happened? @@ -92,21 +104,21 @@ * of the last line. */ - if (curX == Wcm.cm_cols) { + if (curX (tty) == tty->Wcm->cm_cols) { /* * Well, if magicwrap, still there, past the edge of the * screen (!). If autowrap, on the col 0 of the next line. * Otherwise on last column. */ - if (Wcm.cm_magicwrap) + if (tty->Wcm->cm_magicwrap) ; /* "limbo" */ - else if (Wcm.cm_autowrap) { - curX = 0; - curY++; /* Beware end of screen! */ + else if (tty->Wcm->cm_autowrap) { + curX (tty) = 0; + curY (tty) ++; /* Beware end of screen! */ } else - curX--; + curX (tty)--; } } #endif @@ -122,20 +134,21 @@ * after we reach the last column; this takes us to a known state. */ void -cmcheckmagic () +cmcheckmagic (tty) + struct tty_output *tty; { - if (curX == FrameCols) + if (curX (tty) == FrameCols (tty)) { - if (!MagicWrap || curY >= FrameRows - 1) + if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1) abort (); - if (termscript) - putc ('\r', termscript); - putchar ('\r'); - if (termscript) - putc ('\n', termscript); - putchar ('\n'); - curX = 0; - curY++; + if (TTY_TERMSCRIPT (tty)) + putc ('\r', TTY_TERMSCRIPT (tty)); + putc ('\r', TTY_OUTPUT (tty)); + if (TTY_TERMSCRIPT (tty)) + putc ('\n', TTY_TERMSCRIPT (tty)); + putc ('\n', TTY_OUTPUT (tty)); + curX (tty) = 0; + curY (tty)++; } } @@ -147,21 +160,21 @@ */ void -cmcostinit () +cmcostinit (struct tty_output *tty) { char *p; #define COST(x,e) (x ? (cost = 0, tputs (x, 1, e), cost) : BIG) #define CMCOST(x,e) ((x == 0) ? BIG : (p = tgoto(x, 0, 0), COST(p ,e))) - Wcm.cc_up = COST (Wcm.cm_up, evalcost); - Wcm.cc_down = COST (Wcm.cm_down, evalcost); - Wcm.cc_left = COST (Wcm.cm_left, evalcost); - Wcm.cc_right = COST (Wcm.cm_right, evalcost); - Wcm.cc_home = COST (Wcm.cm_home, evalcost); - Wcm.cc_cr = COST (Wcm.cm_cr, evalcost); - Wcm.cc_ll = COST (Wcm.cm_ll, evalcost); - Wcm.cc_tab = Wcm.cm_tabwidth ? COST (Wcm.cm_tab, evalcost) : BIG; + tty->Wcm->cc_up = COST (tty->Wcm->cm_up, evalcost); + tty->Wcm->cc_down = COST (tty->Wcm->cm_down, evalcost); + tty->Wcm->cc_left = COST (tty->Wcm->cm_left, evalcost); + tty->Wcm->cc_right = COST (tty->Wcm->cm_right, evalcost); + tty->Wcm->cc_home = COST (tty->Wcm->cm_home, evalcost); + tty->Wcm->cc_cr = COST (tty->Wcm->cm_cr, evalcost); + tty->Wcm->cc_ll = COST (tty->Wcm->cm_ll, evalcost); + tty->Wcm->cc_tab = tty->Wcm->cm_tabwidth ? COST (tty->Wcm->cm_tab, evalcost) : BIG; /* * These last three are actually minimum costs. When (if) they are @@ -172,9 +185,9 @@ * cursor motion seem to take straight numeric values. --ACT) */ - Wcm.cc_abs = CMCOST (Wcm.cm_abs, evalcost); - Wcm.cc_habs = CMCOST (Wcm.cm_habs, evalcost); - Wcm.cc_vabs = CMCOST (Wcm.cm_vabs, evalcost); + tty->Wcm->cc_abs = CMCOST (tty->Wcm->cm_abs, evalcost); + tty->Wcm->cc_habs = CMCOST (tty->Wcm->cm_habs, evalcost); + tty->Wcm->cc_vabs = CMCOST (tty->Wcm->cm_vabs, evalcost); #undef CMCOST #undef COST @@ -187,8 +200,7 @@ */ static int -calccost (srcy, srcx, dsty, dstx, doit) - int srcy, srcx, dsty, dstx, doit; +calccost (struct tty_output *tty, int srcy, int srcx, int dsty, int dstx, int doit) { register int deltay, deltax, @@ -205,16 +217,16 @@ don't believe the cursor position: give up here and force use of absolute positioning. */ - if (curX == Wcm.cm_cols) + if (curX (tty) == tty->Wcm->cm_cols) goto fail; totalcost = 0; if ((deltay = dsty - srcy) == 0) goto x; if (deltay < 0) - p = Wcm.cm_up, c = Wcm.cc_up, deltay = -deltay; + p = tty->Wcm->cm_up, c = tty->Wcm->cc_up, deltay = -deltay; else - p = Wcm.cm_down, c = Wcm.cc_down; + p = tty->Wcm->cm_down, c = tty->Wcm->cc_down; if (c == BIG) { /* caint get thar from here */ if (doit) printf ("OOPS"); @@ -223,16 +235,16 @@ totalcost = c * deltay; if (doit) while (--deltay >= 0) - tputs (p, 1, cmputc); + emacs_tputs (tty, p, 1, cmputc); x: if ((deltax = dstx - srcx) == 0) goto done; if (deltax < 0) { - p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax; + p = tty->Wcm->cm_left, c = tty->Wcm->cc_left, deltax = -deltax; goto dodelta; /* skip all the tab junk */ } /* Tabs (the toughie) */ - if (Wcm.cc_tab >= BIG || !Wcm.cm_usetabs) + if (tty->Wcm->cc_tab >= BIG || !tty->Wcm->cm_usetabs) goto olddelta; /* forget it! */ /* @@ -243,12 +255,12 @@ * we will put into tabx (for ntabs) and tab2x (for n2tabs)). */ - ntabs = (deltax + srcx % Wcm.cm_tabwidth) / Wcm.cm_tabwidth; + ntabs = (deltax + srcx % tty->Wcm->cm_tabwidth) / tty->Wcm->cm_tabwidth; n2tabs = ntabs + 1; - tabx = (srcx / Wcm.cm_tabwidth + ntabs) * Wcm.cm_tabwidth; - tab2x = tabx + Wcm.cm_tabwidth; + tabx = (srcx / tty->Wcm->cm_tabwidth + ntabs) * tty->Wcm->cm_tabwidth; + tab2x = tabx + tty->Wcm->cm_tabwidth; - if (tab2x >= Wcm.cm_cols) /* too far (past edge) */ + if (tab2x >= tty->Wcm->cm_cols) /* too far (past edge) */ n2tabs = 0; /* @@ -257,11 +269,11 @@ */ /* cost for ntabs + cost for right motion */ - tabcost = ntabs ? ntabs * Wcm.cc_tab + (dstx - tabx) * Wcm.cc_right + tabcost = ntabs ? ntabs * tty->Wcm->cc_tab + (dstx - tabx) * tty->Wcm->cc_right : BIG; /* cost for n2tabs + cost for left motion */ - c = n2tabs ? n2tabs * Wcm.cc_tab + (tab2x - dstx) * Wcm.cc_left + c = n2tabs ? n2tabs * tty->Wcm->cc_tab + (tab2x - dstx) * tty->Wcm->cc_left : BIG; if (c < tabcost) /* then cheaper to overshoot & back up */ @@ -274,11 +286,11 @@ * See if tabcost is less than just moving right */ - if (tabcost < (deltax * Wcm.cc_right)) { + if (tabcost < (deltax * tty->Wcm->cc_right)) { totalcost += tabcost; /* use the tabs */ if (doit) while (--ntabs >= 0) - tputs (Wcm.cm_tab, 1, cmputc); + emacs_tputs (tty, tty->Wcm->cm_tab, 1, cmputc); srcx = tabx; } @@ -291,9 +303,9 @@ goto done; olddelta: if (deltax > 0) - p = Wcm.cm_right, c = Wcm.cc_right; + p = tty->Wcm->cm_right, c = tty->Wcm->cc_right; else - p = Wcm.cm_left, c = Wcm.cc_left, deltax = -deltax; + p = tty->Wcm->cm_left, c = tty->Wcm->cc_left, deltax = -deltax; dodelta: if (c == BIG) { /* caint get thar from here */ @@ -305,7 +317,7 @@ totalcost += c * deltax; if (doit) while (--deltax >= 0) - tputs (p, 1, cmputc); + emacs_tputs (tty, p, 1, cmputc); done: return totalcost; } @@ -323,7 +335,8 @@ #define USECR 3 void -cmgoto (row, col) +cmgoto (tty, row, col) + struct tty_output *tty; int row, col; { int homecost, @@ -336,47 +349,47 @@ *dcm; /* First the degenerate case */ - if (row == curY && col == curX) /* already there */ + if (row == curY (tty) && col == curX (tty)) /* already there */ return; - if (curY >= 0 && curX >= 0) + if (curY (tty) >= 0 && curX (tty) >= 0) { /* We may have quick ways to go to the upper-left, bottom-left, * start-of-line, or start-of-next-line. Or it might be best to * start where we are. Examine the options, and pick the cheapest. */ - relcost = calccost (curY, curX, row, col, 0); + relcost = calccost (tty, curY (tty), curX (tty), row, col, 0); use = USEREL; - if ((homecost = Wcm.cc_home) < BIG) - homecost += calccost (0, 0, row, col, 0); + if ((homecost = tty->Wcm->cc_home) < BIG) + homecost += calccost (tty, 0, 0, row, col, 0); if (homecost < relcost) - relcost = homecost, use = USEHOME; - if ((llcost = Wcm.cc_ll) < BIG) - llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0); + relcost = homecost, use = USEHOME; + if ((llcost = tty->Wcm->cc_ll) < BIG) + llcost += calccost (tty, tty->Wcm->cm_rows - 1, 0, row, col, 0); if (llcost < relcost) - relcost = llcost, use = USELL; - if ((crcost = Wcm.cc_cr) < BIG) { - if (Wcm.cm_autolf) - if (curY + 1 >= Wcm.cm_rows) - crcost = BIG; + relcost = llcost, use = USELL; + if ((crcost = tty->Wcm->cc_cr) < BIG) { + if (tty->Wcm->cm_autolf) + if (curY (tty) + 1 >= tty->Wcm->cm_rows) + crcost = BIG; else - crcost += calccost (curY + 1, 0, row, col, 0); + crcost += calccost (tty, curY (tty) + 1, 0, row, col, 0); else - crcost += calccost (curY, 0, row, col, 0); + crcost += calccost (tty, curY (tty), 0, row, col, 0); } if (crcost < relcost) relcost = crcost, use = USECR; - directcost = Wcm.cc_abs, dcm = Wcm.cm_abs; - if (row == curY && Wcm.cc_habs < BIG) - directcost = Wcm.cc_habs, dcm = Wcm.cm_habs; - else if (col == curX && Wcm.cc_vabs < BIG) - directcost = Wcm.cc_vabs, dcm = Wcm.cm_vabs; + directcost = tty->Wcm->cc_abs, dcm = tty->Wcm->cm_abs; + if (row == curY (tty) && tty->Wcm->cc_habs < BIG) + directcost = tty->Wcm->cc_habs, dcm = tty->Wcm->cm_habs; + else if (col == curX (tty) && tty->Wcm->cc_vabs < BIG) + directcost = tty->Wcm->cc_vabs, dcm = tty->Wcm->cm_vabs; } else { directcost = 0, relcost = 100000; - dcm = Wcm.cm_abs; + dcm = tty->Wcm->cm_abs; } /* @@ -387,13 +400,14 @@ { /* compute REAL direct cost */ cost = 0; - p = dcm == Wcm.cm_habs ? tgoto (dcm, row, col) : - tgoto (dcm, col, row); - tputs (p, 1, evalcost); + p = dcm == tty->Wcm->cm_habs + ? tgoto (dcm, row, col) + : tgoto (dcm, col, row); + emacs_tputs (tty, p, 1, evalcost); if (cost <= relcost) { /* really is cheaper */ - tputs (p, 1, cmputc); - curY = row, curX = col; + emacs_tputs (tty, p, 1, cmputc); + curY (tty) = row, curX (tty) = col; return; } } @@ -401,25 +415,25 @@ switch (use) { case USEHOME: - tputs (Wcm.cm_home, 1, cmputc); - curY = 0, curX = 0; + emacs_tputs (tty, tty->Wcm->cm_home, 1, cmputc); + curY (tty) = 0, curX (tty) = 0; break; case USELL: - tputs (Wcm.cm_ll, 1, cmputc); - curY = Wcm.cm_rows - 1, curX = 0; + emacs_tputs (tty, tty->Wcm->cm_ll, 1, cmputc); + curY (tty) = tty->Wcm->cm_rows - 1, curX (tty) = 0; break; case USECR: - tputs (Wcm.cm_cr, 1, cmputc); - if (Wcm.cm_autolf) - curY++; - curX = 0; + emacs_tputs (tty, tty->Wcm->cm_cr, 1, cmputc); + if (tty->Wcm->cm_autolf) + curY (tty)++; + curX (tty) = 0; break; } - (void) calccost (curY, curX, row, col, 1); - curY = row, curX = col; + (void) calccost (tty, curY (tty), curX (tty), row, col, 1); + curY (tty) = row, curX (tty) = col; } /* Clear out all terminal info. @@ -427,9 +441,9 @@ */ void -Wcm_clear () +Wcm_clear (struct tty_output *tty) { - bzero (&Wcm, sizeof Wcm); + bzero (tty->Wcm, sizeof (struct cm)); UP = 0; BC = 0; } @@ -442,21 +456,21 @@ */ int -Wcm_init () +Wcm_init (struct tty_output *tty) { #if 0 - if (Wcm.cm_abs && !Wcm.cm_ds) + if (tty->Wcm->cm_abs && !tty->Wcm->cm_ds) return 0; #endif - if (Wcm.cm_abs) + if (tty->Wcm->cm_abs) return 0; /* Require up and left, and, if no absolute, down and right */ - if (!Wcm.cm_up || !Wcm.cm_left) + if (!tty->Wcm->cm_up || !tty->Wcm->cm_left) return - 1; - if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right)) + if (!tty->Wcm->cm_abs && (!tty->Wcm->cm_down || !tty->Wcm->cm_right)) return - 1; /* Check that we know the size of the screen.... */ - if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0) + if (tty->Wcm->cm_rows <= 0 || tty->Wcm->cm_cols <= 0) return - 2; return 0; }
--- a/src/cm.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/cm.h Sun Dec 28 16:03:57 2003 +0000 @@ -98,76 +98,78 @@ int cc_vabs; }; -extern struct cm Wcm; /* Terminal capabilities */ extern char PC; /* Pad character */ /* Shorthand */ #ifndef NoCMShortHand -#define curY Wcm.cm_curY -#define curX Wcm.cm_curX -#define Up Wcm.cm_up -#define Down Wcm.cm_down -#define Left Wcm.cm_left -#define Right Wcm.cm_right -#define Tab Wcm.cm_tab -#define BackTab Wcm.cm_backtab -#define TabWidth Wcm.cm_tabwidth -#define CR Wcm.cm_cr -#define Home Wcm.cm_home -#define LastLine Wcm.cm_ll -#define AbsPosition Wcm.cm_abs -#define ColPosition Wcm.cm_habs -#define RowPosition Wcm.cm_vabs -#define MultiUp Wcm.cm_multiup -#define MultiDown Wcm.cm_multidown -#define MultiLeft Wcm.cm_multileft -#define MultiRight Wcm.cm_multiright -#define AutoWrap Wcm.cm_autowrap -#define MagicWrap Wcm.cm_magicwrap -#define UseTabs Wcm.cm_usetabs -#define FrameRows Wcm.cm_rows -#define FrameCols Wcm.cm_cols +#define curY(tty) (tty)->Wcm->cm_curY +#define curX(tty) (tty)->Wcm->cm_curX +#define Up(tty) (tty)->Wcm->cm_up +#define Down(tty) (tty)->Wcm->cm_down +#define Left(tty) (tty)->Wcm->cm_left +#define Right(tty) (tty)->Wcm->cm_right +#define Tab(tty) (tty)->Wcm->cm_tab +#define BackTab(tty) (tty)->Wcm->cm_backtab +#define TabWidth(tty) (tty)->Wcm->cm_tabwidth +#define CR(tty) (tty)->Wcm->cm_cr +#define Home(tty) (tty)->Wcm->cm_home +#define LastLine(tty) (tty)->Wcm->cm_ll +#define AbsPosition(tty) (tty)->Wcm->cm_abs +#define ColPosition(tty) (tty)->Wcm->cm_habs +#define RowPosition(tty) (tty)->Wcm->cm_vabs +#define MultiUp(tty) (tty)->Wcm->cm_multiup +#define MultiDown(tty) (tty)->Wcm->cm_multidown +#define MultiLeft(tty) (tty)->Wcm->cm_multileft +#define MultiRight(tty) (tty)->Wcm->cm_multiright +#define AutoWrap(tty) (tty)->Wcm->cm_autowrap +#define MagicWrap(tty) (tty)->Wcm->cm_magicwrap +#define UseTabs(tty) (tty)->Wcm->cm_usetabs +#define FrameRows(tty) (tty)->Wcm->cm_rows +#define FrameCols(tty) (tty)->Wcm->cm_cols -#define UpCost Wcm.cc_up -#define DownCost Wcm.cc_down -#define LeftCost Wcm.cc_left -#define RightCost Wcm.cc_right -#define HomeCost Wcm.cc_home -#define CRCost Wcm.cc_cr -#define LastLineCost Wcm.cc_ll -#define TabCost Wcm.cc_tab -#define BackTabCost Wcm.cc_backtab -#define AbsPositionCost Wcm.cc_abs -#define ColPositionCost Wcm.cc_habs -#define RowPositionCost Wcm.cc_vabs -#define MultiUpCost Wcm.cc_multiup -#define MultiDownCost Wcm.cc_multidown -#define MultiLeftCost Wcm.cc_multileft -#define MultiRightCost Wcm.cc_multiright +#define UpCost(tty) (tty)->Wcm->cc_up +#define DownCost(tty) (tty)->Wcm->cc_down +#define LeftCost(tty) (tty)->Wcm->cc_left +#define RightCost(tty) (tty)->Wcm->cc_right +#define HomeCost(tty) (tty)->Wcm->cc_home +#define CRCost(tty) (tty)->Wcm->cc_cr +#define LastLineCost(tty) (tty)->Wcm->cc_ll +#define TabCost(tty) (tty)->Wcm->cc_tab +#define BackTabCost(tty) (tty)->Wcm->cc_backtab +#define AbsPositionCost(tty) (tty)->Wcm->cc_abs +#define ColPositionCost(tty) (tty)->Wcm->cc_habs +#define RowPositionCost(tty) (tty)->Wcm->cc_vabs +#define MultiUpCost(tty) (tty)->Wcm->cc_multiup +#define MultiDownCost(tty) (tty)->Wcm->cc_multidown +#define MultiLeftCost(tty) (tty)->Wcm->cc_multileft +#define MultiRightCost(tty) (tty)->Wcm->cc_multiright #endif -#define cmat(row,col) (curY = (row), curX = (col)) -#define cmplus(n) \ - { \ - if ((curX += (n)) >= FrameCols && !MagicWrap) \ - { \ - if (Wcm.cm_losewrap) losecursor (); \ - else if (AutoWrap) curX = 0, curY++; \ - else curX--; \ - } \ +#define cmat(tty,row,col) (curY(tty) = (row), curX(tty) = (col)) +#define cmplus(tty,n) \ + { \ + if ((curX (tty) += (n)) >= FrameCols (tty) && !MagicWrap (tty)) \ + { \ + if ((tty)->Wcm->cm_losewrap) losecursor (tty); \ + else if (AutoWrap (tty)) curX (tty) = 0, curY (tty)++; \ + else curX (tty)--; \ + } \ } -#define losecursor() (curX = -1, curY = -1) +#define losecursor(tty) (curX(tty) = -1, curY(tty) = -1) extern int cost; extern int evalcost (); -extern void cmcheckmagic (); -extern int cmputc (); -extern void cmcostinit (); -extern void cmgoto (); -extern void Wcm_clear (); -extern int Wcm_init (); +#define emacs_tputs(tty, str, affcnt, putc) (current_tty = (tty), tputs (str, affcnt, putc)) + +extern struct tty_output *current_tty; +extern void cmcheckmagic P_ ((struct tty_output *)); +extern int cmputc P_ ((int)); +extern void cmcostinit P_ ((struct tty_output *tty)); +extern void cmgoto P_ ((struct tty_output *, int, int)); +extern void Wcm_clear P_ ((struct tty_output *tty)); +extern int Wcm_init P_ ((struct tty_output *tty)); /* arch-tag: acc1535a-7136-49d6-b22d-9bc85702251b (do not change this comment) */
--- a/src/dispextern.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/dispextern.h Sun Dec 28 16:03:57 2003 +0000 @@ -2555,10 +2555,10 @@ /* Defined in sysdep.c */ -void get_frame_size P_ ((int *, int *)); +void get_tty_size P_ ((struct tty_output *, int *, int *)); void request_sigio P_ ((void)); void unrequest_sigio P_ ((void)); -int tabs_safe_p P_ ((void)); +int tabs_safe_p P_ ((struct tty_output *)); void init_baud_rate P_ ((void)); void init_sigio P_ ((int)); @@ -2730,9 +2730,9 @@ extern void update_end P_ ((struct frame *)); extern void set_terminal_window P_ ((int)); extern void set_scroll_region P_ ((int, int)); -extern void turn_off_insert P_ ((void)); -extern void turn_off_highlight P_ ((void)); -extern void background_highlight P_ ((void)); +extern void turn_off_insert P_ ((struct tty_output *)); +extern void turn_off_highlight P_ ((struct tty_output *)); +extern void background_highlight P_ ((struct tty_output *)); extern void clear_frame P_ ((void)); extern void clear_end_of_line P_ ((int)); extern void clear_end_of_line_raw P_ ((int)); @@ -2742,11 +2742,12 @@ extern int per_line_cost P_ ((char *)); extern void calculate_costs P_ ((struct frame *)); extern void set_tty_color_mode P_ ((struct frame *, Lisp_Object)); -extern void tty_setup_colors P_ ((int)); -extern void term_init P_ ((char *)); +extern void tty_setup_colors P_ ((struct tty_output *, int)); +extern struct tty_output *term_init P_ ((char *, char *)); +extern struct tty_output *term_dummy_init P_ ((void)); extern void fatal P_ ((/* char *, ... */)); void cursor_to P_ ((int, int)); -extern int tty_capable_p P_ ((struct frame *, unsigned, unsigned long, unsigned long)); +extern int tty_capable_p P_ ((struct tty_output *, unsigned, unsigned long, unsigned long)); /* Defined in scroll.c */
--- a/src/dispnew.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/dispnew.c Sun Dec 28 16:03:57 2003 +0000 @@ -29,6 +29,7 @@ #endif #include "lisp.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "termopts.h" #include "termhooks.h" @@ -258,14 +259,6 @@ struct frame *last_nonminibuf_frame; -/* Stdio stream being used for copy of all output. */ - -FILE *termscript; - -/* Structure for info on cursor positioning. */ - -struct cm Wcm; - /* 1 means SIGWINCH happened when not safe. */ int delayed_size_change; @@ -1397,7 +1390,7 @@ { int c = glyph->u.ch; int face_id = glyph->face_id; - if (must_write_spaces) + if (TTY_MUST_WRITE_SPACES (CURTTY ())) c -= SPACEGLYPH; hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c; hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id; @@ -1429,7 +1422,7 @@ int glyph_table_len = GLYPH_TABLE_LENGTH; /* Ignore trailing and leading spaces if we can. */ - if (!must_write_spaces) + if (!TTY_MUST_WRITE_SPACES (CURTTY ())) { /* Skip from the end over trailing spaces. */ while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1))) @@ -1643,8 +1636,10 @@ #if GLYPH_DEBUG -/* Flush standard output. This is sometimes useful to call from - the debugger. */ +/* Flush standard output. This is sometimes useful to call from the debugger. + XXX Maybe this should be changed to flush the current terminal instead of + stdout. +*/ void flush_stdout () @@ -3322,7 +3317,7 @@ clear_frame (); clear_current_matrices (f); update_end (f); - fflush (stdout); + fflush (TTY_OUTPUT (FRAME_TTY (f))); windows_or_buffers_changed++; /* Mark all windows as inaccurate, so that every window will have its redisplay done. */ @@ -3462,7 +3457,7 @@ /* If we can't insert glyphs, we can use this method only at the end of a line. */ - if (!char_ins_del_ok) + if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))) if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n') return 0; @@ -3659,7 +3654,7 @@ rif->update_window_end_hook (w, 1, 0); update_end (f); updated_row = NULL; - fflush (stdout); + fflush (TTY_OUTPUT (CURTTY ())); TRACE ((stderr, "direct output for insert\n")); mark_window_display_accurate (it.window, 1); @@ -3750,7 +3745,7 @@ cursor_to (y, x); } - fflush (stdout); + fflush (TTY_OUTPUT (CURTTY ())); redisplay_performed_directly_p = 1; return 1; } @@ -3841,9 +3836,9 @@ paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p); update_end (f); - if (termscript) - fflush (termscript); - fflush (stdout); + if (TTY_TERMSCRIPT (FRAME_TTY (f))) + fflush (TTY_TERMSCRIPT (FRAME_TTY (f))); + fflush (TTY_OUTPUT (FRAME_TTY (f))); /* Check window matrices for lost pointers. */ #if GLYPH_DEBUG @@ -5075,7 +5070,7 @@ } /* If we cannot insert/delete lines, it's no use trying it. */ - if (!line_ins_del_ok) + if (!TTY_LINE_INS_DEL_OK (FRAME_TTY (f))) inhibit_id_p = 1; /* See if any of the desired lines are enabled; don't compute for @@ -5103,18 +5098,18 @@ Also flush out if likely to have more than 1k buffered otherwise. I'm told that some telnet connections get really screwed by more than 1k output at once. */ - int outq = PENDING_OUTPUT_COUNT (stdout); + int outq = PENDING_OUTPUT_COUNT (TTY_OUTPUT (FRAME_TTY (f))); if (outq > 900 || (outq > 20 && ((i - 1) % preempt_count == 0))) { - fflush (stdout); + fflush (TTY_OUTPUT (FRAME_TTY (f))); if (preempt_count == 1) { #ifdef EMACS_OUTQSIZE if (EMACS_OUTQSIZE (0, &outq) < 0) /* Probably not a tty. Ignore the error and reset the outq count. */ - outq = PENDING_OUTPUT_COUNT (stdout); + outq = PENDING_OUTPUT_COUNT (TTY_OUTPUT (FRAME_TTY (f))); #endif outq *= 10; if (baud_rate <= outq && baud_rate > 0) @@ -5293,21 +5288,23 @@ } /* If changed lines are few, don't allow preemption, don't scroll. */ - if ((!scroll_region_ok && changed_lines < baud_rate / 2400) + if ((!TTY_SCROLL_REGION_OK (FRAME_TTY (frame)) + && changed_lines < baud_rate / 2400) || unchanged_at_bottom == FRAME_LINES (frame)) return 1; window_size = (FRAME_LINES (frame) - unchanged_at_top - unchanged_at_bottom); - if (scroll_region_ok) + if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame))) free_at_end_vpos -= unchanged_at_bottom; - else if (memory_below_frame) + else if (TTY_MEMORY_BELOW_FRAME (FRAME_TTY (frame))) free_at_end_vpos = -1; /* If large window, fast terminal and few lines in common between current frame and desired frame, don't bother with i/d calc. */ - if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400 + if (!TTY_SCROLL_REGION_OK (FRAME_TTY (frame)) + && window_size >= 18 && baud_rate > 2400 && (window_size >= 10 * scrolling_max_lines_saved (unchanged_at_top, FRAME_LINES (frame) - unchanged_at_bottom, @@ -5387,7 +5384,7 @@ struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos); struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos); int must_write_whole_line_p; - int write_spaces_p = must_write_spaces; + int write_spaces_p = TTY_MUST_WRITE_SPACES (FRAME_TTY (f)); int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background != FACE_TTY_DEFAULT_BG_COLOR); @@ -5466,7 +5463,7 @@ nlen--; /* If there's no i/d char, quickly do the best we can without it. */ - if (!char_ins_del_ok) + if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))) { int i, j; @@ -5569,7 +5566,8 @@ tem = (nlen - nsp) - (olen - osp); if (endmatch && tem - && (!char_ins_del_ok || endmatch <= char_ins_del_cost (f)[tem])) + && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)) + || endmatch <= char_ins_del_cost (f)[tem])) endmatch = 0; /* nsp - osp is the distance to insert or delete. @@ -5578,7 +5576,7 @@ Is it worth it? */ if (nsp != osp - && (!char_ins_del_ok + && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)) || begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp])) { begmatch = 0; @@ -5891,28 +5889,34 @@ #endif int old_errno = errno; - get_frame_size (&width, &height); - - /* The frame size change obviously applies to a termcap-controlled - frame. Find such a frame in the list, and assume it's the only - one (since the redisplay code always writes to stdout, not a - FILE * specified in the frame structure). Record the new size, - but don't reallocate the data structures now. Let that be done - later outside of the signal handler. */ - - { - Lisp_Object tail, frame; - - FOR_EACH_FRAME (tail, frame) - { - if (FRAME_TERMCAP_P (XFRAME (frame))) - { - change_frame_size (XFRAME (frame), height, width, 0, 1, 0); - break; - } - } + struct tty_output *tty; + + /* The frame size change obviously applies to a single + termcap-controlled terminal, but we can't decide which. + Therefore, we resize the frames corresponding to each tty. + + XXX In fact we only get the signal for the initial terminal. + */ + for (tty = tty_list; tty; tty = tty->next) { + + get_tty_size (tty, &width, &height); + + { + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + { + if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty) + { + /* Record the new sizes, but don't reallocate the data structures + now. Let that be done later outside of the signal handler. */ + change_frame_size (XFRAME (frame), height, width, 0, 1, 0); + break; + } + } + } } - + signal (SIGWINCH, window_change_signal); errno = old_errno; } @@ -5967,10 +5971,11 @@ { Lisp_Object tail, frame; - if (! FRAME_WINDOW_P (f)) + if (FRAME_MSDOS_P (f)) { - /* When using termcap, or on MS-DOS, all frames use - the same screen, so a change in size affects all frames. */ + /* On MS-DOS, all frames use the same screen, so a change in + size affects all frames. Termcap now supports multiple + ttys. */ FOR_EACH_FRAME (tail, frame) if (! FRAME_WINDOW_P (XFRAME (frame))) change_frame_size_1 (XFRAME (frame), newheight, newwidth, @@ -6050,7 +6055,7 @@ newheight - FRAME_TOP_MARGIN (f), 0); if (FRAME_TERMCAP_P (f) && !pretend) - FrameRows = newheight; + FrameRows (FRAME_TTY (f)) = newheight; } if (new_frame_total_cols != FRAME_TOTAL_COLS (f)) @@ -6060,7 +6065,7 @@ set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_total_cols, 0); if (FRAME_TERMCAP_P (f) && !pretend) - FrameCols = newwidth; + FrameCols (FRAME_TTY (f)) = newwidth; if (WINDOWP (f->tool_bar_window)) XSETFASTINT (XWINDOW (f->tool_bar_window)->total_cols, newwidth); @@ -6110,14 +6115,15 @@ (file) Lisp_Object file; { - if (termscript != 0) fclose (termscript); - termscript = 0; + if (TTY_TERMSCRIPT (CURTTY ()) != 0) + fclose (TTY_TERMSCRIPT (CURTTY ())); + TTY_TERMSCRIPT (CURTTY ()) = 0; if (! NILP (file)) { file = Fexpand_file_name (file, Qnil); - termscript = fopen (SDATA (file), "w"); - if (termscript == 0) + TTY_TERMSCRIPT (CURTTY ()) = fopen (SDATA (file), "w"); + if (TTY_TERMSCRIPT (CURTTY ()) == 0) report_file_error ("Opening termscript", Fcons (file, Qnil)); } return Qnil; @@ -6133,14 +6139,15 @@ { /* ??? Perhaps we should do something special for multibyte strings here. */ CHECK_STRING (string); - fwrite (SDATA (string), 1, SBYTES (string), stdout); - fflush (stdout); - if (termscript) + if (TTY_TERMSCRIPT (CURTTY ())) { fwrite (SDATA (string), 1, SBYTES (string), - termscript); - fflush (termscript); + TTY_TERMSCRIPT (CURTTY ())); + fflush (TTY_TERMSCRIPT (CURTTY ())); } + fwrite (SDATA (string), 1, SBYTES (string), + TTY_OUTPUT (CURTTY ())); + fflush (TTY_OUTPUT (CURTTY ())); return Qnil; } @@ -6158,7 +6165,7 @@ putchar (07); else ring_bell (); - fflush (stdout); + fflush (TTY_OUTPUT (CURTTY ())); } else bitch_at_user (); @@ -6175,7 +6182,7 @@ error ("Keyboard macro terminated by a command ringing the bell"); else ring_bell (); - fflush (stdout); + fflush (TTY_OUTPUT (CURTTY ())); } @@ -6460,8 +6467,6 @@ Initialization ***********************************************************************/ -char *terminal_type; - /* Initialization done when Emacs fork is started, before doing stty. Determine terminal type and set terminal_driver. Then invoke its decoding routine to set up variables in the terminal package. */ @@ -6469,6 +6474,8 @@ void init_display () { + char *terminal_type; + #ifdef HAVE_X_WINDOWS extern int display_arg; #endif @@ -6478,7 +6485,6 @@ SET_CHAR_GLYPH_FROM_GLYPH (space_glyph, ' '); space_glyph.charpos = -1; - meta_key = 0; inverse_video = 0; cursor_in_echo_area = 0; terminal_type = (char *) 0; @@ -6590,7 +6596,7 @@ } #endif /* VMS */ - term_init (terminal_type); + term_init (0, terminal_type); { struct frame *sf = SELECTED_FRAME ();
--- a/src/emacs.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/emacs.c Sun Dec 28 16:03:57 2003 +0000 @@ -1564,9 +1564,9 @@ if (!noninteractive) { #ifdef VMS - init_vms_input ();/* init_display calls get_frame_size, that needs this. */ + init_vms_input ();/* init_display calls get_tty_size, that needs this. */ #endif /* VMS */ - init_display (); /* Determine terminal type. init_sys_modes uses results. */ + init_display (); /* Determine terminal type. Calls init_sys_modes. */ } #ifndef MAC_OS8 /* Called before init_window_once for Mac OS Classic. */ @@ -1575,7 +1575,7 @@ #ifdef VMS init_vmsproc (); /* And this too. */ #endif /* VMS */ - init_sys_modes (); /* Init system terminal modes (RAW or CBREAK, etc.). */ + /* init_sys_modes (); */ /* Init system terminal modes (RAW or CBREAK, etc.). */ #if defined (HAVE_X_WINDOWS) || defined (WINDOWSNT) init_xfns (); #endif /* HAVE_X_WINDOWS */ @@ -1992,7 +1992,7 @@ && tpgrp == pgrp) { fflush (stdout); - reset_sys_modes (); + reset_all_sys_modes (); if (sig && sig != SIGTERM) fprintf (stderr, "Fatal error (%d)", sig); }
--- a/src/frame.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/frame.c Sun Dec 28 16:03:57 2003 +0000 @@ -42,6 +42,8 @@ #include "fontset.h" #endif #include "blockinput.h" +#include "systty.h" /* For emacs_tty in termchar.h */ +#include "termchar.h" #include "termhooks.h" #include "dispextern.h" #include "window.h" @@ -106,13 +108,12 @@ Lisp_Object Qleft_fringe, Qright_fringe; Lisp_Object Qbuffer_predicate, Qbuffer_list; Lisp_Object Qtty_color_mode; +Lisp_Object Qtty, Qtty_type; Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth; Lisp_Object Qface_set_after_frame_default; - -Lisp_Object Vterminal_frame; Lisp_Object Vdefault_frame_alist; Lisp_Object Vdefault_frame_scroll_bars; Lisp_Object Vmouse_position_function; @@ -180,8 +181,6 @@ Lisp_Object Vemacs_iconified; Lisp_Object Vframe_list; -struct x_output tty_display; - extern Lisp_Object Vminibuffer_list; extern Lisp_Object get_minibuffer (); extern Lisp_Object Fhandle_switch_frame (); @@ -474,17 +473,26 @@ } #endif /* HAVE_WINDOW_SYSTEM */ -/* Construct a frame that refers to the terminal (stdin and stdout). */ +/* Construct a frame that refers to a terminal. */ static int terminal_frame_count; struct frame * -make_terminal_frame () +make_terminal_frame (tty_name, tty_type) + char *tty_name; + char *tty_type; { register struct frame *f; Lisp_Object frame; char name[20]; - + struct tty_output *tty; + + /* init_term may throw an error, so create the tty first. */ + if (initialized) + tty = term_init (tty_name, tty_type); + else + tty = term_dummy_init (); + #ifdef MULTI_KBOARD if (!initial_kboard) { @@ -537,12 +545,14 @@ #else #ifdef WINDOWSNT f->output_method = output_termcap; - f->output_data.x = &tty_display; + f->output_data.x = &tty_display; /* XXX */ #else #ifdef MAC_OS8 make_mac_terminal_frame (f); #else - f->output_data.x = &tty_display; + f->output_method = output_termcap; + f->output_data.tty = tty; + f->output_data.tty->top_frame = frame; #ifdef CANNOT_DUMP FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR; FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR; @@ -559,11 +569,19 @@ DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame, 1, 1, 0, - doc: /* Create an additional terminal frame. -You can create multiple frames on a text-only terminal in this way. -Only the selected terminal frame is actually displayed. + doc: /* Create an additional terminal frame, possibly on another terminal. This function takes one argument, an alist specifying frame parameters. -In practice, generally you don't need to specify any parameters. + +You can create multiple frames on a single text-only terminal, but +only one of them (the selected terminal frame) is actually displayed. + +In practice, generally you don't need to specify any parameters, +except when you want to create a new frame on another terminal. +In that case, the `tty' parameter specifies the device file to open, +and the `tty-type' parameter specifies the terminal type. Example: + + (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm"))) + Note that changing the size of one terminal frame automatically affects all. */) (parms) Lisp_Object parms; @@ -587,10 +605,54 @@ #endif #endif /* not MSDOS */ - f = make_terminal_frame (); - - change_frame_size (f, FRAME_LINES (sf), - FRAME_COLS (sf), 0, 0, 0); + { + Lisp_Object tty, tty_type; + char *name = 0, *type = 0; + + /* XXX Ugh, there must be a better way to do this. */ + tty = Fassq (Qtty, parms); + if (EQ (tty, Qnil)) + tty = Fassq (Qtty, XFRAME (selected_frame)->param_alist); + if (EQ (tty, Qnil)) + tty = Fassq (Qtty, Vdefault_frame_alist); + if (! EQ (tty, Qnil)) + tty = XCDR (tty); + if (EQ (tty, Qnil) || !STRINGP (tty)) + tty = Qnil; + + tty_type = Fassq (Qtty_type, parms); + if (EQ (tty_type, Qnil)) + tty_type = Fassq (Qtty_type, Vdefault_frame_alist); + if (EQ (tty_type, Qnil)) + tty_type = Fassq (Qtty, XFRAME (selected_frame)->param_alist); + if (! EQ (tty_type, Qnil)) + tty_type = XCDR (tty_type); + if (EQ (tty_type, Qnil) || !STRINGP (tty_type)) + tty_type = Qnil; + + if (! EQ (tty, Qnil)) + { + name = (char *) alloca (SBYTES (tty) + 1); + strncpy (name, SDATA (tty), SBYTES (tty)); + name[SBYTES (tty)] = 0; + } + + if (! EQ (tty_type, Qnil)) + { + type = (char *) alloca (SBYTES (tty_type) + 1); + strncpy (type, SDATA (tty_type), SBYTES (tty_type)); + type[SBYTES (tty_type)] = 0; + } + + f = make_terminal_frame (name, type); + } + + { + int width, height; + get_tty_size (FRAME_TTY (f), &width, &height); + change_frame_size (f, height, width, 0, 0, 0); + } + adjust_glyphs (f); calculate_costs (f); XSETFRAME (frame, f); @@ -694,6 +756,15 @@ if (!for_deletion && FRAME_HAS_MINIBUF_P (sf)) resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1); + if (FRAME_TERMCAP_P (XFRAME (selected_frame)) + && FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (selected_frame)) == FRAME_TTY (XFRAME (frame))) + { + XFRAME (selected_frame)->async_visible = 2; /* obscured */ + XFRAME (frame)->async_visible = 1; + FRAME_TTY (XFRAME (frame))->top_frame = frame; + } + selected_frame = frame; if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) last_nonminibuf_frame = XFRAME (selected_frame); @@ -927,7 +998,10 @@ f = XCAR (tail); if (passed - && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame))) + && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame))) + || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))) { /* Decide whether this frame is eligible to be returned. */ @@ -1004,7 +1078,10 @@ if (EQ (frame, f) && !NILP (prev)) return prev; - if (FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame))) + if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame))) + || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))) { /* Decide whether this frame is eligible to be returned, according to minibuf. */ @@ -1231,7 +1308,7 @@ { FOR_EACH_FRAME (tail, frame1) { - if (! EQ (frame, frame1)) + if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1))) break; } } @@ -1304,6 +1381,26 @@ x_destroy_window (f); #endif + if (FRAME_TERMCAP_P (f)) + { + /* See if the terminal needs to be closed. */ + Lisp_Object tail, frame1; + int delete = 1; + + FOR_EACH_FRAME (tail, frame1) + { + if (!FRAME_LIVE_P (XFRAME (frame1)) && + FRAME_TERMCAP_P (XFRAME (frame1)) && + FRAME_TTY (XFRAME (frame1)) == FRAME_TTY (f)) + { + delete = 0; + break; + } + } + if (delete) + delete_tty (FRAME_TTY (f)); + } + f->output_data.nothing = 0; /* If we've deleted the last_nonminibuf_frame, then try to find @@ -3937,6 +4034,10 @@ staticpro (&Qbackground_mode); Qtty_color_mode = intern ("tty-color-mode"); staticpro (&Qtty_color_mode); + Qtty = intern ("tty"); + staticpro (&Qtty); + Qtty_type = intern ("tty-type"); + staticpro (&Qtty_type); Qface_set_after_frame_default = intern ("face-set-after-frame-default"); staticpro (&Qface_set_after_frame_default); @@ -4025,9 +4126,6 @@ = intern ("inhibit-default-face-x-resources"); staticpro (&Qinhibit_default_face_x_resources); - DEFVAR_LISP ("terminal-frame", &Vterminal_frame, - doc: /* The initial frame-object, which represents Emacs's stdout. */); - DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified, doc: /* Non-nil if all of emacs is iconified and frame updates are not needed. */); Vemacs_iconified = Qnil;
--- a/src/frame.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/frame.h Sun Dec 28 16:03:57 2003 +0000 @@ -28,9 +28,7 @@ /* Miscellanea. */ -/* Nonzero means don't assume anything about current contents of - actual terminal frame */ - +/* Nonzero means there is at least one garbaged frame. */ extern int frame_garbaged; /* Nonzero means FRAME_MESSAGE_BUF (selected_frame) is being used by @@ -71,7 +69,7 @@ #if !defined(HAVE_X_WINDOWS) -#define PIX_TYPE int +#define PIX_TYPE unsigned long /* A (mostly empty) x_output structure definition for building Emacs on Unix and GNU/Linux without X support. */ @@ -84,11 +82,15 @@ #endif /* ! HAVE_X_WINDOWS */ -#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel) -#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel) +#define FRAME_FOREGROUND_PIXEL(f) \ + (((f)->output_method == output_termcap) \ + ? ((f)->output_data.tty->foreground_pixel) \ + : ((f)->output_data.x->foreground_pixel)) -/* A structure describing a termcap frame display. */ -extern struct x_output tty_display; +#define FRAME_BACKGROUND_PIXEL(f) \ + (((f)->output_method == output_termcap) \ + ? ((f)->output_data.tty->background_pixel) \ + : ((f)->output_data.x->background_pixel)) #endif /* ! MSDOS && ! WINDOWSNT && ! MAC_OS */ @@ -283,12 +285,15 @@ enum output_method output_method; /* A structure of auxiliary data used for displaying the contents. + struct tty_output is used for terminal frames; + it is defined in term.h. struct x_output is used for X window frames; it is defined in xterm.h. struct w32_output is used for W32 window frames; it is defined in w32term.h. */ union output_data { + struct tty_output *tty; struct x_output *x; struct w32_output *w32; struct mac_output *mac; @@ -336,13 +341,13 @@ frame becomes visible again, it must be marked as garbaged. The FRAME_SAMPLE_VISIBILITY macro takes care of this. - On Windows NT/9X, to avoid wasting effort updating visible frames - that are actually completely obscured by other windows on the - display, we bend the meaning of visible slightly: if greater than - 1, then the frame is obscured - we still consider it to be - "visible" as seen from lisp, but we don't bother updating it. We - must take care to garbage the frame when it ceaces to be obscured - though. Note that these semantics are only used on NT/9X. + On ttys and on Windows NT/9X, to avoid wasting effort updating + visible frames that are actually completely obscured by other + windows on the display, we bend the meaning of visible slightly: + if greater than 1, then the frame is obscured - we still consider + it to be "visible" as seen from lisp, but we don't bother + updating it. We must take care to garbage the frame when it + ceaces to be obscured though. iconified is nonzero if the frame is currently iconified. @@ -736,7 +741,10 @@ Also, if a frame used to be invisible, but has just become visible, it must be marked as garbaged, since redisplay hasn't been keeping - up its contents. */ + up its contents. + + Note that a tty frame is visible if and only if it is the topmost + frame. */ #define FRAME_SAMPLE_VISIBILITY(f) \ (((f)->async_visible && (f)->visible != (f)->async_visible) ? \ @@ -779,7 +787,7 @@ extern struct frame *last_nonminibuf_frame; -extern struct frame *make_terminal_frame P_ ((void)); +extern struct frame *make_terminal_frame P_ ((char *tty, char *tty_type)); extern struct frame *make_frame P_ ((int)); #ifdef HAVE_WINDOW_SYSTEM extern struct frame *make_minibuffer_frame P_ ((void)); @@ -792,8 +800,6 @@ extern Lisp_Object Vframe_list; extern Lisp_Object Vdefault_frame_alist; -extern Lisp_Object Vterminal_frame; - extern Lisp_Object Vmouse_highlight; /* The currently selected frame. */
--- a/src/indent.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/indent.c Sun Dec 28 16:03:57 2003 +0000 @@ -28,6 +28,7 @@ #include "keyboard.h" #include "frame.h" #include "window.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "termopts.h" #include "disptab.h"
--- a/src/keyboard.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/keyboard.c Sun Dec 28 16:03:57 2003 +0000 @@ -22,9 +22,10 @@ #include <config.h> #include <signal.h> #include <stdio.h> +#include "lisp.h" +#include "systty.h" /* This must be included befor termchar.h. */ #include "termchar.h" #include "termopts.h" -#include "lisp.h" #include "termhooks.h" #include "macros.h" #include "keyboard.h" @@ -55,7 +56,6 @@ #endif /* not MSDOS */ #include "syssignal.h" -#include "systty.h" #include <sys/types.h> #ifdef HAVE_UNISTD_H @@ -89,9 +89,6 @@ int interrupt_input_pending; -/* File descriptor to use for input. */ -extern int input_fd; - #ifdef HAVE_WINDOW_SYSTEM /* Make all keyboard buffers much bigger when using X windows. */ #ifdef MAC_OS8 @@ -464,11 +461,6 @@ /* Nonzero if input is available. */ int input_pending; -/* 1 if should obey 0200 bit in input chars as "Meta", 2 if should - keep 0200 bit in input chars. 0 to ignore the 0200 bit. */ - -int meta_key; - /* Non-zero means force key bindings update in parse_menu_item. */ int update_menu_bindings; @@ -6463,7 +6455,7 @@ /* If input is being read as it arrives, and we have none, there is none. */ if (*addr > 0 || (interrupt_input && ! interrupts_deferred)) return; - + /* Try to read some input and see how much we get. */ gobble_input (0); *addr = (!NILP (Vquit_flag) @@ -6582,13 +6574,13 @@ struct input_event buf[KBD_BUFFER_SIZE]; register int i; int nread; - + for (i = 0; i < KBD_BUFFER_SIZE; i++) EVENT_INIT (buf[i]); if (read_socket_hook) /* No need for FIONREAD or fcntl; just say don't wait. */ - nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE, expected); + nread = (*read_socket_hook) (buf, KBD_BUFFER_SIZE, expected); else { /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than @@ -6596,8 +6588,9 @@ of characters on some systems when input is stuffed at us. */ unsigned char cbuf[KBD_BUFFER_SIZE - 1]; int n_to_read; - - /* Determine how many characters we should *try* to read. */ + struct tty_output *tty; + Lisp_Object frame; + #ifdef WINDOWSNT return 0; #else /* not WINDOWSNT */ @@ -6605,99 +6598,140 @@ n_to_read = dos_keysns (); if (n_to_read == 0) return 0; + + cbuf[0] = dos_keyread (); + nread = 1; + #else /* not MSDOS */ + + nread = 0; + + /* Try to read from each available tty, until one succeeds. */ + for (tty = tty_list; tty; tty = tty->next) { + + if (! tty->term_initted) + continue; + + /* Determine how many characters we should *try* to read. */ #ifdef FIONREAD - /* Find out how much input is available. */ - if (ioctl (input_fd, FIONREAD, &n_to_read) < 0) - /* Formerly simply reported no input, but that sometimes led to - a failure of Emacs to terminate. - SIGHUP seems appropriate if we can't reach the terminal. */ - /* ??? Is it really right to send the signal just to this process - rather than to the whole process group? - Perhaps on systems with FIONREAD Emacs is alone in its group. */ - { - if (! noninteractive) - kill (getpid (), SIGHUP); - else - n_to_read = 0; - } - if (n_to_read == 0) - return 0; - if (n_to_read > sizeof cbuf) - n_to_read = sizeof cbuf; + /* Find out how much input is available. */ + if (ioctl (fileno (TTY_INPUT (tty)), FIONREAD, &n_to_read) < 0) + { + /* Formerly simply reported no input, but that sometimes led to + a failure of Emacs to terminate. + SIGHUP seems appropriate if we can't reach the terminal. */ + /* ??? Is it really right to send the signal just to this process + rather than to the whole process group? + Perhaps on systems with FIONREAD Emacs is alone in its group. */ + /* It appears to be the case, see narrow_foreground_group. */ + if (! noninteractive) + { + if (! tty_list->next) + kill (getpid (), SIGHUP); /* This was the last terminal. */ + else + n_to_read = 0; /* XXX tty should be closed here. */ + } + else + { + n_to_read = 0; + } + } + if (n_to_read == 0) + continue; + if (n_to_read > sizeof cbuf) + n_to_read = sizeof cbuf; #else /* no FIONREAD */ #if defined (USG) || defined (DGUX) || defined(CYGWIN) - /* Read some input if available, but don't wait. */ - n_to_read = sizeof cbuf; - fcntl (input_fd, F_SETFL, O_NDELAY); + /* Read some input if available, but don't wait. */ + n_to_read = sizeof cbuf; + fcntl (fileno (TTY_INPUT (tty)), F_SETFL, O_NDELAY); #else - you lose; -#endif -#endif + you lose; +#endif +#endif + + /* Now read; for one reason or another, this will not block. + NREAD is set to the number of chars read. */ + do + { + nread = emacs_read (fileno (TTY_INPUT (tty)), cbuf, n_to_read); + /* POSIX infers that processes which are not in the session leader's + process group won't get SIGHUP's at logout time. BSDI adheres to + this part standard and returns -1 from read (0) with errno==EIO + when the control tty is taken away. + Jeffrey Honig <jch@bsdi.com> says this is generally safe. */ + if (nread == -1 && errno == EIO) + { + if (! tty_list->next) + kill (0, SIGHUP); /* This was the last terminal. */ + else + ; /* XXX tty should be closed here. */ + } +#if defined (AIX) && (! defined (aix386) && defined (_BSD)) + /* The kernel sometimes fails to deliver SIGHUP for ptys. + This looks incorrect, but it isn't, because _BSD causes + O_NDELAY to be defined in fcntl.h as O_NONBLOCK, + and that causes a value other than 0 when there is no input. */ + if (nread == 0) + { + if (! tty_list->next) + kill (0, SIGHUP); /* This was the last terminal. */ + else + ; /* XXX tty should be closed here. */ + } +#endif + } + while ( + /* We used to retry the read if it was interrupted. + But this does the wrong thing when O_NDELAY causes + an EAGAIN error. Does anybody know of a situation + where a retry is actually needed? */ +#if 0 + nread < 0 && (errno == EAGAIN +#ifdef EFAULT + || errno == EFAULT +#endif +#ifdef EBADSLT + || errno == EBADSLT +#endif + ) +#else + 0 +#endif + ); + +#ifndef FIONREAD +#if defined (USG) || defined (DGUX) || defined (CYGWIN) + fcntl (fileno (TTY_INPUT (tty)), F_SETFL, 0); +#endif /* USG or DGUX or CYGWIN */ +#endif /* no FIONREAD */ + + if (nread > 0) + break; + } /* for each tty */ + + if (nread <= 0) + return 0; + #endif /* not MSDOS */ #endif /* not WINDOWSNT */ - /* Now read; for one reason or another, this will not block. - NREAD is set to the number of chars read. */ - do - { -#ifdef MSDOS - cbuf[0] = dos_keyread (); - nread = 1; -#else - nread = emacs_read (input_fd, cbuf, n_to_read); -#endif - /* POSIX infers that processes which are not in the session leader's - process group won't get SIGHUP's at logout time. BSDI adheres to - this part standard and returns -1 from read (0) with errno==EIO - when the control tty is taken away. - Jeffrey Honig <jch@bsdi.com> says this is generally safe. */ - if (nread == -1 && errno == EIO) - kill (0, SIGHUP); -#if defined (AIX) && (! defined (aix386) && defined (_BSD)) - /* The kernel sometimes fails to deliver SIGHUP for ptys. - This looks incorrect, but it isn't, because _BSD causes - O_NDELAY to be defined in fcntl.h as O_NONBLOCK, - and that causes a value other than 0 when there is no input. */ - if (nread == 0) - kill (0, SIGHUP); -#endif - } - while ( - /* We used to retry the read if it was interrupted. - But this does the wrong thing when O_NDELAY causes - an EAGAIN error. Does anybody know of a situation - where a retry is actually needed? */ -#if 0 - nread < 0 && (errno == EAGAIN -#ifdef EFAULT - || errno == EFAULT -#endif -#ifdef EBADSLT - || errno == EBADSLT -#endif - ) -#else - 0 -#endif - ); - -#ifndef FIONREAD -#if defined (USG) || defined (DGUX) || defined (CYGWIN) - fcntl (input_fd, F_SETFL, 0); -#endif /* USG or DGUX or CYGWIN */ -#endif /* no FIONREAD */ + /* Select frame corresponding to the active tty. Note that the + value of selected_frame is not reliable here, redisplay tends + to temporarily change it. But tty should always be non-NULL. */ + frame = (tty ? tty->top_frame : selected_frame); + for (i = 0; i < nread; i++) { buf[i].kind = ASCII_KEYSTROKE_EVENT; buf[i].modifiers = 0; - if (meta_key == 1 && (cbuf[i] & 0x80)) + if (tty->meta_key == 1 && (cbuf[i] & 0x80)) buf[i].modifiers = meta_modifier; - if (meta_key != 2) + if (tty->meta_key != 2) cbuf[i] &= ~0x80; - buf[i].code = cbuf[i]; - buf[i].frame_or_window = selected_frame; + buf[i].code = cbuf[i]; + buf[i].frame_or_window = frame; buf[i].arg = Qnil; } } @@ -10058,6 +10092,9 @@ int width, height; struct gcpro gcpro1; + if (tty_list && tty_list->next) + error ("Suspend is not supported with multiple ttys"); + if (!NILP (stuffstring)) CHECK_STRING (stuffstring); @@ -10066,12 +10103,12 @@ call1 (Vrun_hooks, intern ("suspend-hook")); GCPRO1 (stuffstring); - get_frame_size (&old_width, &old_height); - reset_sys_modes (); + get_tty_size (CURTTY (), &old_width, &old_height); + reset_all_sys_modes (); /* sys_suspend can get an error if it tries to fork a subshell and the system resources aren't available for that. */ record_unwind_protect ((Lisp_Object (*) P_ ((Lisp_Object))) init_sys_modes, - Qnil); + (Lisp_Object)CURTTY()); /* XXX */ stuff_buffered_input (stuffstring); if (cannot_suspend) sys_subshell (); @@ -10082,7 +10119,7 @@ /* Check if terminal/window size has changed. Note that this is not useful when we are running directly with a window system; but suspend should be disabled in that case. */ - get_frame_size (&width, &height); + get_tty_size (CURTTY (), &width, &height); if (width != old_width || height != old_height) change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0); @@ -10206,7 +10243,7 @@ sigblock (sigmask (SIGINT)); fflush (stdout); - reset_sys_modes (); + reset_all_sys_modes (); #ifdef SIGTSTP /* Support possible in later USG versions */ /* @@ -10285,7 +10322,7 @@ printf ("Continuing...\n"); #endif /* not MSDOS */ fflush (stdout); - init_sys_modes (); + init_all_sys_modes (); sigfree (); } else @@ -10372,7 +10409,7 @@ #ifndef DOS_NT /* this causes startup screen to be restored and messes with the mouse */ - reset_sys_modes (); + reset_all_sys_modes (); #endif #ifdef SIGIO @@ -10400,17 +10437,17 @@ flow_control = !NILP (flow); if (NILP (meta)) - meta_key = 0; + FRAME_TTY (SELECTED_FRAME ())->meta_key = 0; else if (EQ (meta, Qt)) - meta_key = 1; + FRAME_TTY (SELECTED_FRAME ())->meta_key = 1; else - meta_key = 2; + FRAME_TTY (SELECTED_FRAME ())->meta_key = 2; if (!NILP (quit)) /* Don't let this value be out of range. */ - quit_char = XINT (quit) & (meta_key ? 0377 : 0177); + quit_char = XINT (quit) & (FRAME_TTY (SELECTED_FRAME ())->meta_key ? 0377 : 0177); #ifndef DOS_NT - init_sys_modes (); + init_all_sys_modes (); #endif #ifdef POLL_FOR_INPUT @@ -10440,7 +10477,9 @@ val[0] = interrupt_input ? Qt : Qnil; val[1] = flow_control ? Qt : Qnil; - val[2] = meta_key == 2 ? make_number (0) : meta_key == 1 ? Qt : Qnil; + val[2] = FRAME_TTY (SELECTED_FRAME ())->meta_key == 2 + ? make_number (0) + : FRAME_TTY (SELECTED_FRAME ())->meta_key == 1 ? Qt : Qnil; XSETFASTINT (val[3], quit_char); return Flist (sizeof (val) / sizeof (val[0]), val);
--- a/src/lisp.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/lisp.h Sun Dec 28 16:03:57 2003 +0000 @@ -2931,25 +2931,27 @@ EXFUN (Fx_popup_dialog, 2); extern void syms_of_xmenu P_ ((void)); +/* defined in termchar.h */ +struct tty_output; + /* defined in sysdep.c */ extern void stuff_char P_ ((char c)); extern void init_sigio P_ ((int)); extern void request_sigio P_ ((void)); extern void unrequest_sigio P_ ((void)); -extern void reset_sys_modes P_ ((void)); extern void sys_subshell P_ ((void)); extern void sys_suspend P_ ((void)); extern void discard_tty_input P_ ((void)); -extern void init_sys_modes P_ ((void)); -extern void reset_sys_modes P_ ((void)); -extern void get_frame_size P_ ((int *, int *)); +extern void init_sys_modes P_ ((struct tty_output *)); +extern void reset_sys_modes P_ ((struct tty_output *)); +extern void init_all_sys_modes P_ ((void)); +extern void reset_all_sys_modes P_ ((void)); extern void wait_for_termination P_ ((int)); extern void flush_pending_output P_ ((int)); extern void child_setup_tty P_ ((int)); extern void setup_pty P_ ((int)); extern int set_window_size P_ ((int, int, int)); extern void create_process P_ ((Lisp_Object, char **, Lisp_Object)); -extern int tabs_safe_p P_ ((void)); extern void init_baud_rate P_ ((void)); extern int emacs_open P_ ((const char *, int, int)); extern int emacs_close P_ ((int));
--- a/src/macterm.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/macterm.c Sun Dec 28 16:03:57 2003 +0000 @@ -7598,7 +7598,7 @@ /* Emacs calls this whenever it wants to read an input event from the user. */ int -XTread_socket (int sd, struct input_event *bufp, int numchars, int expected) +XTread_socket (struct input_event *bufp, int numchars, int expected) { int count = 0; #if USE_CARBON_EVENTS @@ -8674,12 +8674,13 @@ redeem_scroll_bar_hook = XTredeem_scroll_bar; judge_scroll_bars_hook = XTjudge_scroll_bars; - scroll_region_ok = 1; /* we'll scroll partial frames */ - char_ins_del_ok = 1; - line_ins_del_ok = 1; /* we'll just blt 'em */ - fast_clear_end_of_line = 1; /* X does this well */ - memory_below_frame = 0; /* we don't remember what scrolls - off the bottom */ + TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */ + TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1; + TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */ + TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */ + TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what + scrolls off the + bottom */ baud_rate = 19200; x_noop_count = 0;
--- a/src/macterm.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/macterm.h Sun Dec 28 16:03:57 2003 +0000 @@ -406,9 +406,6 @@ #define FRAME_MAC_WINDOW(f) ((f)->output_data.mac->mWP) #define FRAME_X_WINDOW(f) ((f)->output_data.mac->mWP) -#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel) -#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel) - #define FRAME_FONT(f) ((f)->output_data.mac->font) #define FRAME_FONTSET(f) ((f)->output_data.mac->fontset)
--- a/src/msdos.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/msdos.c Sun Dec 28 16:03:57 2003 +0000 @@ -2580,7 +2580,7 @@ set_terminal_modes_hook = IT_set_terminal_modes; reset_terminal_modes_hook = IT_reset_terminal_modes; set_terminal_window_hook = IT_set_terminal_window; - char_ins_del_ok = 0; + TTY_CHAR_INS_DEL_OK (CURTTY ()) = 0; #endif }
--- a/src/print.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/print.c Sun Dec 28 16:03:57 2003 +0000 @@ -30,6 +30,7 @@ #include "window.h" #include "process.h" #include "dispextern.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "intervals.h"
--- a/src/regex.c Wed Dec 24 23:32:12 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6335 +0,0 @@ -/* Extended regular expression matching and search library, version - 0.12. (Implements POSIX draft P1003.2/D11.2, except for some of the - internationalization features.) - - Copyright (C) 1993,94,95,96,97,98,99,2000 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ - -/* TODO: - - structure the opcode space into opcode+flag. - - merge with glibc's regex.[ch]. - - replace (succeed_n + jump_n + set_number_at) with something that doesn't - need to modify the compiled regexp so that re_match can be reentrant. - - get rid of on_failure_jump_smart by doing the optimization in re_comp - rather than at run-time, so that re_match can be reentrant. -*/ - -/* AIX requires this to be the first thing in the file. */ -#if defined _AIX && !defined REGEX_MALLOC - #pragma alloca -#endif - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#if defined STDC_HEADERS && !defined emacs -# include <stddef.h> -#else -/* We need this for `regex.h', and perhaps for the Emacs include files. */ -# include <sys/types.h> -#endif - -/* Whether to use ISO C Amendment 1 wide char functions. - Those should not be used for Emacs since it uses its own. */ -#if defined _LIBC -#define WIDE_CHAR_SUPPORT 1 -#else -#define WIDE_CHAR_SUPPORT \ - (HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_BTOWC && !emacs) -#endif - -/* For platform which support the ISO C amendement 1 functionality we - support user defined character classes. */ -#if WIDE_CHAR_SUPPORT -/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ -# include <wchar.h> -# include <wctype.h> -#endif - -#ifdef _LIBC -/* We have to keep the namespace clean. */ -# define regfree(preg) __regfree (preg) -# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) -# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) -# define regerror(errcode, preg, errbuf, errbuf_size) \ - __regerror(errcode, preg, errbuf, errbuf_size) -# define re_set_registers(bu, re, nu, st, en) \ - __re_set_registers (bu, re, nu, st, en) -# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ - __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) -# define re_match(bufp, string, size, pos, regs) \ - __re_match (bufp, string, size, pos, regs) -# define re_search(bufp, string, size, startpos, range, regs) \ - __re_search (bufp, string, size, startpos, range, regs) -# define re_compile_pattern(pattern, length, bufp) \ - __re_compile_pattern (pattern, length, bufp) -# define re_set_syntax(syntax) __re_set_syntax (syntax) -# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ - __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) -# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) - -/* Make sure we call libc's function even if the user overrides them. */ -# define btowc __btowc -# define iswctype __iswctype -# define wctype __wctype - -# define WEAK_ALIAS(a,b) weak_alias (a, b) - -/* We are also using some library internals. */ -# include <locale/localeinfo.h> -# include <locale/elem-hash.h> -# include <langinfo.h> -#else -# define WEAK_ALIAS(a,b) -#endif - -/* This is for other GNU distributions with internationalized messages. */ -#if HAVE_LIBINTL_H || defined _LIBC -# include <libintl.h> -#else -# define gettext(msgid) (msgid) -#endif - -#ifndef gettext_noop -/* This define is so xgettext can find the internationalizable - strings. */ -# define gettext_noop(String) String -#endif - -/* The `emacs' switch turns on certain matching commands - that make sense only in Emacs. */ -#ifdef emacs - -# include "lisp.h" -# include "buffer.h" - -/* Make syntax table lookup grant data in gl_state. */ -# define SYNTAX_ENTRY_VIA_PROPERTY - -# include "syntax.h" -# include "charset.h" -# include "category.h" - -# ifdef malloc -# undef malloc -# endif -# define malloc xmalloc -# ifdef realloc -# undef realloc -# endif -# define realloc xrealloc -# ifdef free -# undef free -# endif -# define free xfree - -/* Converts the pointer to the char to BEG-based offset from the start. */ -# define PTR_TO_OFFSET(d) POS_AS_IN_BUFFER (POINTER_TO_OFFSET (d)) -# define POS_AS_IN_BUFFER(p) ((p) + (NILP (re_match_object) || BUFFERP (re_match_object))) - -# define RE_MULTIBYTE_P(bufp) ((bufp)->multibyte) -# define RE_STRING_CHAR(p, s) \ - (multibyte ? (STRING_CHAR (p, s)) : (*(p))) -# define RE_STRING_CHAR_AND_LENGTH(p, s, len) \ - (multibyte ? (STRING_CHAR_AND_LENGTH (p, s, len)) : ((len) = 1, *(p))) - -/* Set C a (possibly multibyte) character before P. P points into a - string which is the virtual concatenation of STR1 (which ends at - END1) or STR2 (which ends at END2). */ -# define GET_CHAR_BEFORE_2(c, p, str1, end1, str2, end2) \ - do { \ - if (multibyte) \ - { \ - re_char *dtemp = (p) == (str2) ? (end1) : (p); \ - re_char *dlimit = ((p) > (str2) && (p) <= (end2)) ? (str2) : (str1); \ - re_char *d0 = dtemp; \ - PREV_CHAR_BOUNDARY (d0, dlimit); \ - c = STRING_CHAR (d0, dtemp - d0); \ - } \ - else \ - (c = ((p) == (str2) ? (end1) : (p))[-1]); \ - } while (0) - - -#else /* not emacs */ - -/* If we are not linking with Emacs proper, - we can't use the relocating allocator - even if config.h says that we can. */ -# undef REL_ALLOC - -# if defined STDC_HEADERS || defined _LIBC -# include <stdlib.h> -# else -char *malloc (); -char *realloc (); -# endif - -/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. - If nothing else has been done, use the method below. */ -# ifdef INHIBIT_STRING_HEADER -# if !(defined HAVE_BZERO && defined HAVE_BCOPY) -# if !defined bzero && !defined bcopy -# undef INHIBIT_STRING_HEADER -# endif -# endif -# endif - -/* This is the normal way of making sure we have memcpy, memcmp and bzero. - This is used in most programs--a few other programs avoid this - by defining INHIBIT_STRING_HEADER. */ -# ifndef INHIBIT_STRING_HEADER -# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC -# include <string.h> -# ifndef bzero -# ifndef _LIBC -# define bzero(s, n) (memset (s, '\0', n), (s)) -# else -# define bzero(s, n) __bzero (s, n) -# endif -# endif -# else -# include <strings.h> -# ifndef memcmp -# define memcmp(s1, s2, n) bcmp (s1, s2, n) -# endif -# ifndef memcpy -# define memcpy(d, s, n) (bcopy (s, d, n), (d)) -# endif -# endif -# endif - -/* Define the syntax stuff for \<, \>, etc. */ - -/* Sword must be nonzero for the wordchar pattern commands in re_match_2. */ -enum syntaxcode { Swhitespace = 0, Sword = 1 }; - -# ifdef SWITCH_ENUM_BUG -# define SWITCH_ENUM_CAST(x) ((int)(x)) -# else -# define SWITCH_ENUM_CAST(x) (x) -# endif - -/* Dummy macros for non-Emacs environments. */ -# define BASE_LEADING_CODE_P(c) (0) -# define CHAR_CHARSET(c) 0 -# define CHARSET_LEADING_CODE_BASE(c) 0 -# define MAX_MULTIBYTE_LENGTH 1 -# define RE_MULTIBYTE_P(x) 0 -# define WORD_BOUNDARY_P(c1, c2) (0) -# define CHAR_HEAD_P(p) (1) -# define SINGLE_BYTE_CHAR_P(c) (1) -# define SAME_CHARSET_P(c1, c2) (1) -# define MULTIBYTE_FORM_LENGTH(p, s) (1) -# define PREV_CHAR_BOUNDARY(p, limit) ((p)--) -# define STRING_CHAR(p, s) (*(p)) -# define RE_STRING_CHAR STRING_CHAR -# define CHAR_STRING(c, s) (*(s) = (c), 1) -# define STRING_CHAR_AND_LENGTH(p, s, actual_len) ((actual_len) = 1, *(p)) -# define RE_STRING_CHAR_AND_LENGTH STRING_CHAR_AND_LENGTH -# define GET_CHAR_BEFORE_2(c, p, str1, end1, str2, end2) \ - (c = ((p) == (str2) ? *((end1) - 1) : *((p) - 1))) -# define MAKE_CHAR(charset, c1, c2) (c1) -#endif /* not emacs */ - -#ifndef RE_TRANSLATE -# define RE_TRANSLATE(TBL, C) ((unsigned char)(TBL)[C]) -# define RE_TRANSLATE_P(TBL) (TBL) -#endif - -/* Get the interface, including the syntax bits. */ -#include "regex.h" - -/* isalpha etc. are used for the character classes. */ -#include <ctype.h> - -#ifdef emacs - -/* 1 if C is an ASCII character. */ -# define IS_REAL_ASCII(c) ((c) < 0200) - -/* 1 if C is a unibyte character. */ -# define ISUNIBYTE(c) (SINGLE_BYTE_CHAR_P ((c))) - -/* The Emacs definitions should not be directly affected by locales. */ - -/* In Emacs, these are only used for single-byte characters. */ -# define ISDIGIT(c) ((c) >= '0' && (c) <= '9') -# define ISCNTRL(c) ((c) < ' ') -# define ISXDIGIT(c) (((c) >= '0' && (c) <= '9') \ - || ((c) >= 'a' && (c) <= 'f') \ - || ((c) >= 'A' && (c) <= 'F')) - -/* This is only used for single-byte characters. */ -# define ISBLANK(c) ((c) == ' ' || (c) == '\t') - -/* The rest must handle multibyte characters. */ - -# define ISGRAPH(c) (SINGLE_BYTE_CHAR_P (c) \ - ? (c) > ' ' && !((c) >= 0177 && (c) <= 0237) \ - : 1) - -# define ISPRINT(c) (SINGLE_BYTE_CHAR_P (c) \ - ? (c) >= ' ' && !((c) >= 0177 && (c) <= 0237) \ - : 1) - -# define ISALNUM(c) (IS_REAL_ASCII (c) \ - ? (((c) >= 'a' && (c) <= 'z') \ - || ((c) >= 'A' && (c) <= 'Z') \ - || ((c) >= '0' && (c) <= '9')) \ - : SYNTAX (c) == Sword) - -# define ISALPHA(c) (IS_REAL_ASCII (c) \ - ? (((c) >= 'a' && (c) <= 'z') \ - || ((c) >= 'A' && (c) <= 'Z')) \ - : SYNTAX (c) == Sword) - -# define ISLOWER(c) (LOWERCASEP (c)) - -# define ISPUNCT(c) (IS_REAL_ASCII (c) \ - ? ((c) > ' ' && (c) < 0177 \ - && !(((c) >= 'a' && (c) <= 'z') \ - || ((c) >= 'A' && (c) <= 'Z') \ - || ((c) >= '0' && (c) <= '9'))) \ - : SYNTAX (c) != Sword) - -# define ISSPACE(c) (SYNTAX (c) == Swhitespace) - -# define ISUPPER(c) (UPPERCASEP (c)) - -# define ISWORD(c) (SYNTAX (c) == Sword) - -#else /* not emacs */ - -/* Jim Meyering writes: - - "... Some ctype macros are valid only for character codes that - isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when - using /bin/cc or gcc but without giving an ansi option). So, all - ctype uses should be through macros like ISPRINT... If - STDC_HEADERS is defined, then autoconf has verified that the ctype - macros don't need to be guarded with references to isascii. ... - Defining isascii to 1 should let any compiler worth its salt - eliminate the && through constant folding." - Solaris defines some of these symbols so we must undefine them first. */ - -# undef ISASCII -# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) -# define ISASCII(c) 1 -# else -# define ISASCII(c) isascii(c) -# endif - -/* 1 if C is an ASCII character. */ -# define IS_REAL_ASCII(c) ((c) < 0200) - -/* This distinction is not meaningful, except in Emacs. */ -# define ISUNIBYTE(c) 1 - -# 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 - -# undef ISPRINT -# 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)) - -# define ISWORD(c) ISALPHA(c) - -# ifdef _tolower -# define TOLOWER(c) _tolower(c) -# else -# define TOLOWER(c) tolower(c) -# endif - -/* How many characters in the character set. */ -# define CHAR_SET_SIZE 256 - -# ifdef SYNTAX_TABLE - -extern char *re_syntax_table; - -# else /* not SYNTAX_TABLE */ - -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 = 0; c < CHAR_SET_SIZE; ++c) - if (ISALNUM (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 */ - -#ifndef NULL -# define NULL (void *)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) -# define REGEX_FREE free - -#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> -# endif /* 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), \ - memcpy (destination, source, osize)) - -/* No need to do anything to free, after alloca. */ -# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ - -#endif /* not REGEX_MALLOC */ - -/* Define how to allocate the failure stack. */ - -#if defined REL_ALLOC && defined REGEX_MALLOC - -# define REGEX_ALLOCATE_STACK(size) \ - r_alloc (&failure_stack_ptr, (size)) -# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ - r_re_alloc (&failure_stack_ptr, (nsize)) -# define REGEX_FREE_STACK(ptr) \ - r_alloc_free (&failure_stack_ptr) - -#else /* not using relocating allocator */ - -# ifdef REGEX_MALLOC - -# define REGEX_ALLOCATE_STACK malloc -# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) -# define REGEX_FREE_STACK free - -# else /* not REGEX_MALLOC */ - -# define REGEX_ALLOCATE_STACK alloca - -# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ - REGEX_REALLOCATE (source, osize, nsize) -/* No need to explicitly free anything. */ -# define REGEX_FREE_STACK(arg) ((void)0) - -# endif /* not REGEX_MALLOC */ -#endif /* not using relocating allocator */ - - -/* 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 RETALLOC_IF(addr, n, t) \ - if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), 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)) - -#undef MAX -#undef MIN -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -/* Type of source-pattern and string chars. */ -typedef const unsigned char re_char; - -typedef char boolean; -#define false 0 -#define true 1 - -static int re_match_2_internal _RE_ARGS ((struct re_pattern_buffer *bufp, - re_char *string1, int size1, - re_char *string2, int size2, - int pos, - struct re_registers *regs, - int stop)); - -/* 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. */ - -typedef enum -{ - no_op = 0, - - /* Succeed right away--no more backtracking. */ - succeed, - - /* Followed by one byte giving n, then by n literal bytes. */ - exactn, - - /* 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. - - If the length byte has the 0x80 bit set, then that stuff - is followed by a range table: - 2 bytes of flags for character sets (low 8 bits, high 8 bits) - See RANGE_TABLE_WORK_BITS below. - 2 bytes, the number of pairs that follow (upto 32767) - pairs, each 2 multibyte characters, - each multibyte character represented as 3 bytes. */ - 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. */ - 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. */ - 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, - - /* 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, - - /* Just like `on_failure_jump', except that it checks that we - don't get stuck in an infinite loop (matching an empty string - indefinitely). */ - on_failure_jump_loop, - - /* Just like `on_failure_jump_loop', except that it checks for - a different kind of loop (the kind that shows up with non-greedy - operators). This operation has to be immediately preceded - by a `no_op'. */ - on_failure_jump_nastyloop, - - /* A smart `on_failure_jump' used for greedy * and + operators. - It analyses the loop before which it is put and if the - loop does not require backtracking, it changes itself to - `on_failure_keep_string_jump' and short-circuits the loop, - else it just defaults to changing itself into `on_failure_jump'. - It assumes that it is pointing to just past a `jump'. */ - on_failure_jump_smart, - - /* Followed by two-byte relative address and two-byte number n. - After matching N times, jump to the address upon failure. - Does not work if N starts at 0: use on_failure_jump_loop - instead. */ - 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, - - 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. */ - - /* 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 - -#ifdef emacs - ,before_dot, /* Succeeds if before point. */ - at_dot, /* Succeeds if at point. */ - after_dot, /* Succeeds if after point. */ - - /* Matches any character whose category-set contains the specified - category. The operator is followed by a byte which contains a - category code (mnemonic ASCII character). */ - categoryspec, - - /* Matches any character whose category-set does not contain the - specified category. The operator is followed by a byte which - contains the category code (mnemonic ASCII character). */ - notcategoryspec -#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 _RE_ARGS ((int *dest, re_char *source)); -static void -extract_number (dest, source) - int *dest; - re_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 _RE_ARGS ((int *destination, - re_char **source)); -static void -extract_number_and_incr (destination, source) - int *destination; - re_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 */ - -/* Store a multibyte character in three contiguous bytes starting - DESTINATION, and increment DESTINATION to the byte after where the - character is stored. Therefore, DESTINATION must be an lvalue. */ - -#define STORE_CHARACTER_AND_INCR(destination, character) \ - do { \ - (destination)[0] = (character) & 0377; \ - (destination)[1] = ((character) >> 8) & 0377; \ - (destination)[2] = (character) >> 16; \ - (destination) += 3; \ - } while (0) - -/* Put into DESTINATION a character stored in three contiguous bytes - starting at SOURCE. */ - -#define EXTRACT_CHARACTER(destination, source) \ - do { \ - (destination) = ((source)[0] \ - | ((source)[1] << 8) \ - | ((source)[2] << 16)); \ - } while (0) - - -/* Macros for charset. */ - -/* Size of bitmap of charset P in bytes. P is a start of charset, - i.e. *P is (re_opcode_t) charset or (re_opcode_t) charset_not. */ -#define CHARSET_BITMAP_SIZE(p) ((p)[1] & 0x7F) - -/* Nonzero if charset P has range table. */ -#define CHARSET_RANGE_TABLE_EXISTS_P(p) ((p)[1] & 0x80) - -/* Return the address of range table of charset P. But not the start - of table itself, but the before where the number of ranges is - stored. `2 +' means to skip re_opcode_t and size of bitmap, - and the 2 bytes of flags at the start of the range table. */ -#define CHARSET_RANGE_TABLE(p) (&(p)[4 + CHARSET_BITMAP_SIZE (p)]) - -/* Extract the bit flags that start a range table. */ -#define CHARSET_RANGE_TABLE_BITS(p) \ - ((p)[2 + CHARSET_BITMAP_SIZE (p)] \ - + (p)[3 + CHARSET_BITMAP_SIZE (p)] * 0x100) - -/* Test if C is listed in the bitmap of charset P. */ -#define CHARSET_LOOKUP_BITMAP(p, c) \ - ((c) < CHARSET_BITMAP_SIZE (p) * BYTEWIDTH \ - && (p)[2 + (c) / BYTEWIDTH] & (1 << ((c) % BYTEWIDTH))) - -/* Return the address of end of RANGE_TABLE. COUNT is number of - ranges (which is a pair of (start, end)) in the RANGE_TABLE. `* 2' - is start of range and end of range. `* 3' is size of each start - and end. */ -#define CHARSET_RANGE_TABLE_END(range_table, count) \ - ((range_table) + (count) * 2 * 3) - -/* Test if C is in RANGE_TABLE. A flag NOT is negated if C is in. - COUNT is number of ranges in RANGE_TABLE. */ -#define CHARSET_LOOKUP_RANGE_TABLE_RAW(not, c, range_table, count) \ - do \ - { \ - re_wchar_t range_start, range_end; \ - re_char *p; \ - re_char *range_table_end \ - = CHARSET_RANGE_TABLE_END ((range_table), (count)); \ - \ - for (p = (range_table); p < range_table_end; p += 2 * 3) \ - { \ - EXTRACT_CHARACTER (range_start, p); \ - EXTRACT_CHARACTER (range_end, p + 3); \ - \ - if (range_start <= (c) && (c) <= range_end) \ - { \ - (not) = !(not); \ - break; \ - } \ - } \ - } \ - while (0) - -/* Test if C is in range table of CHARSET. The flag NOT is negated if - C is listed in it. */ -#define CHARSET_LOOKUP_RANGE_TABLE(not, c, charset) \ - do \ - { \ - /* Number of ranges in range table. */ \ - int count; \ - re_char *range_table = CHARSET_RANGE_TABLE (charset); \ - \ - EXTRACT_NUMBER_AND_INCR (count, range_table); \ - CHARSET_LOOKUP_RANGE_TABLE_RAW ((not), (c), range_table, count); \ - } \ - while (0) - -/* 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 = -100000; - -# define DEBUG_STATEMENT(e) e -# define DEBUG_PRINT1(x) if (debug > 0) printf (x) -# define DEBUG_PRINT2(x1, x2) if (debug > 0) printf (x1, x2) -# define DEBUG_PRINT3(x1, x2, x3) if (debug > 0) printf (x1, x2, x3) -# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug > 0) printf (x1, x2, x3, x4) -# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ - if (debug > 0) print_partial_compiled_pattern (s, e) -# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ - if (debug > 0) print_double_string (w, s1, sz1, s2, sz2) - - -/* 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; - putchar (i - 1); - while (i < (1 << BYTEWIDTH) && fastmap[i]) - { - was_a_range = 1; - i++; - } - if (was_a_range) - { - printf ("-"); - putchar (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) - re_char *start; - re_char *end; -{ - int mcnt, mcnt2; - re_char *p = start; - re_char *pend = end; - - if (start == NULL) - { - fprintf (stderr, "(null)\n"); - return; - } - - /* Loop over pattern commands. */ - while (p < pend) - { - fprintf (stderr, "%d:\t", p - start); - - switch ((re_opcode_t) *p++) - { - case no_op: - fprintf (stderr, "/no_op"); - break; - - case succeed: - fprintf (stderr, "/succeed"); - break; - - case exactn: - mcnt = *p++; - fprintf (stderr, "/exactn/%d", mcnt); - do - { - fprintf (stderr, "/%c", *p++); - } - while (--mcnt); - break; - - case start_memory: - fprintf (stderr, "/start_memory/%d", *p++); - break; - - case stop_memory: - fprintf (stderr, "/stop_memory/%d", *p++); - break; - - case duplicate: - fprintf (stderr, "/duplicate/%d", *p++); - break; - - case anychar: - fprintf (stderr, "/anychar"); - break; - - case charset: - case charset_not: - { - register int c, last = -100; - register int in_range = 0; - int length = CHARSET_BITMAP_SIZE (p - 1); - int has_range_table = CHARSET_RANGE_TABLE_EXISTS_P (p - 1); - - fprintf (stderr, "/charset [%s", - (re_opcode_t) *(p - 1) == charset_not ? "^" : ""); - - if (p + *p >= pend) - fprintf (stderr, " !extends past end of pattern! "); - - for (c = 0; c < 256; c++) - if (c / 8 < length - && (p[1 + (c/8)] & (1 << (c % 8)))) - { - /* Are we starting a range? */ - if (last + 1 == c && ! in_range) - { - fprintf (stderr, "-"); - in_range = 1; - } - /* Have we broken a range? */ - else if (last + 1 != c && in_range) - { - fprintf (stderr, "%c", last); - in_range = 0; - } - - if (! in_range) - fprintf (stderr, "%c", c); - - last = c; - } - - if (in_range) - fprintf (stderr, "%c", last); - - fprintf (stderr, "]"); - - p += 1 + length; - - if (has_range_table) - { - int count; - fprintf (stderr, "has-range-table"); - - /* ??? Should print the range table; for now, just skip it. */ - p += 2; /* skip range table bits */ - EXTRACT_NUMBER_AND_INCR (count, p); - p = CHARSET_RANGE_TABLE_END (p, count); - } - } - break; - - case begline: - fprintf (stderr, "/begline"); - break; - - case endline: - fprintf (stderr, "/endline"); - break; - - case on_failure_jump: - extract_number_and_incr (&mcnt, &p); - fprintf (stderr, "/on_failure_jump to %d", p + mcnt - start); - break; - - case on_failure_keep_string_jump: - extract_number_and_incr (&mcnt, &p); - fprintf (stderr, "/on_failure_keep_string_jump to %d", p + mcnt - start); - break; - - case on_failure_jump_nastyloop: - extract_number_and_incr (&mcnt, &p); - fprintf (stderr, "/on_failure_jump_nastyloop to %d", p + mcnt - start); - break; - - case on_failure_jump_loop: - extract_number_and_incr (&mcnt, &p); - fprintf (stderr, "/on_failure_jump_loop to %d", p + mcnt - start); - break; - - case on_failure_jump_smart: - extract_number_and_incr (&mcnt, &p); - fprintf (stderr, "/on_failure_jump_smart to %d", p + mcnt - start); - break; - - case jump: - extract_number_and_incr (&mcnt, &p); - fprintf (stderr, "/jump to %d", p + mcnt - start); - break; - - case succeed_n: - extract_number_and_incr (&mcnt, &p); - extract_number_and_incr (&mcnt2, &p); - fprintf (stderr, "/succeed_n to %d, %d times", p - 2 + mcnt - start, mcnt2); - break; - - case jump_n: - extract_number_and_incr (&mcnt, &p); - extract_number_and_incr (&mcnt2, &p); - fprintf (stderr, "/jump_n to %d, %d times", p - 2 + mcnt - start, mcnt2); - break; - - case set_number_at: - extract_number_and_incr (&mcnt, &p); - extract_number_and_incr (&mcnt2, &p); - fprintf (stderr, "/set_number_at location %d to %d", p - 2 + mcnt - start, mcnt2); - break; - - case wordbound: - fprintf (stderr, "/wordbound"); - break; - - case notwordbound: - fprintf (stderr, "/notwordbound"); - break; - - case wordbeg: - fprintf (stderr, "/wordbeg"); - break; - - case wordend: - fprintf (stderr, "/wordend"); - - case syntaxspec: - fprintf (stderr, "/syntaxspec"); - mcnt = *p++; - fprintf (stderr, "/%d", mcnt); - break; - - case notsyntaxspec: - fprintf (stderr, "/notsyntaxspec"); - mcnt = *p++; - fprintf (stderr, "/%d", mcnt); - break; - -# ifdef emacs - case before_dot: - fprintf (stderr, "/before_dot"); - break; - - case at_dot: - fprintf (stderr, "/at_dot"); - break; - - case after_dot: - fprintf (stderr, "/after_dot"); - break; - - case categoryspec: - fprintf (stderr, "/categoryspec"); - mcnt = *p++; - fprintf (stderr, "/%d", mcnt); - break; - - case notcategoryspec: - fprintf (stderr, "/notcategoryspec"); - mcnt = *p++; - fprintf (stderr, "/%d", mcnt); - break; -# endif /* emacs */ - - case begbuf: - fprintf (stderr, "/begbuf"); - break; - - case endbuf: - fprintf (stderr, "/endbuf"); - break; - - default: - fprintf (stderr, "?%d", *(p-1)); - } - - fprintf (stderr, "\n"); - } - - fprintf (stderr, "%d:\tend of pattern.\n", p - start); -} - - -void -print_compiled_pattern (bufp) - struct re_pattern_buffer *bufp; -{ - re_char *buffer = bufp->buffer; - - print_partial_compiled_pattern (buffer, buffer + bufp->used); - printf ("%ld bytes used/%ld 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 ("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: %lx\n", bufp->syntax); - fflush (stdout); - /* Perhaps we should print the translate table? */ -} - - -void -print_double_string (where, string1, size1, string2, size2) - re_char *where; - re_char *string1; - re_char *string2; - int size1; - int size2; -{ - int this_char; - - if (where == NULL) - printf ("(null)"); - else - { - if (FIRST_STRING_P (where)) - { - for (this_char = where - string1; this_char < size1; this_char++) - putchar (string1[this_char]); - - where = string2; - } - - for (this_char = where - string2; this_char < size2; this_char++) - putchar (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. */ -/* This has no initializer because initialized variables in Emacs - become read-only after dumping. */ -reg_syntax_t re_syntax_options; - - -/* 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; -} -WEAK_ALIAS (__re_set_syntax, re_set_syntax) - -/* 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. - POSIX doesn't require that we do anything for REG_NOERROR, - but why not be nice? */ - -static const char *re_error_msgid[] = - { - gettext_noop ("Success"), /* REG_NOERROR */ - gettext_noop ("No match"), /* REG_NOMATCH */ - gettext_noop ("Invalid regular expression"), /* REG_BADPAT */ - gettext_noop ("Invalid collation character"), /* REG_ECOLLATE */ - gettext_noop ("Invalid character class name"), /* REG_ECTYPE */ - gettext_noop ("Trailing backslash"), /* REG_EESCAPE */ - gettext_noop ("Invalid back reference"), /* REG_ESUBREG */ - gettext_noop ("Unmatched [ or [^"), /* REG_EBRACK */ - gettext_noop ("Unmatched ( or \\("), /* REG_EPAREN */ - gettext_noop ("Unmatched \\{"), /* REG_EBRACE */ - gettext_noop ("Invalid content of \\{\\}"), /* REG_BADBR */ - gettext_noop ("Invalid range end"), /* REG_ERANGE */ - gettext_noop ("Memory exhausted"), /* REG_ESPACE */ - gettext_noop ("Invalid preceding regular expression"), /* REG_BADRPT */ - gettext_noop ("Premature end of regular expression"), /* REG_EEND */ - gettext_noop ("Regular expression too big"), /* REG_ESIZE */ - gettext_noop ("Unmatched ) or \\)"), /* REG_ERPAREN */ - }; - -/* Avoiding alloca during matching, to placate r_alloc. */ - -/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the - searching and matching functions should not call alloca. On some - systems, alloca is implemented in terms of malloc, and if we're - using the relocating allocator routines, then malloc could cause a - relocation, which might (if the strings being searched are in the - ralloc heap) shift the data out from underneath the regexp - routines. - - Here's another reason to avoid allocation: Emacs - processes input from X in a signal handler; processing X input may - call malloc; if input arrives while a matching routine is calling - malloc, then we're scrod. But Emacs can't just block input while - calling matching routines; then we don't notice interrupts when - they come in. So, Emacs blocks input around all regexp calls - except the matching calls, which it leaves unprotected, in the - faith that they will not malloc. */ - -/* Normally, this is fine. */ -#define MATCH_MAY_ALLOCATE - -/* When using GNU C, we are not REALLY using the C alloca, no matter - what config.h may say. So don't take precautions for it. */ -#ifdef __GNUC__ -# undef C_ALLOCA -#endif - -/* The match routines may not allocate if (1) they would do it with malloc - and (2) it's not safe for them to use malloc. - Note that if REL_ALLOC is defined, matching would not use malloc for the - failure stack, but we would still use it for the register vectors; - so REL_ALLOC should not affect this. */ -#if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs -# undef MATCH_MAY_ALLOCATE -#endif - - -/* 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_STACK. */ - - -/* Approximate 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 20 -#endif - -/* Roughly the maximum number of failure points on the stack. Would be - exactly that if always used TYPICAL_FAILURE_SIZE items each time we failed. - This is a variable only so users of regex can assign to it; we never - change it ourselves. We always multiply it by TYPICAL_FAILURE_SIZE - before using it, so it should probably be a byte-count instead. */ -# if defined MATCH_MAY_ALLOCATE -/* Note that 4400 was enough to cause a crash on Alpha OSF/1, - whose default stack limit is 2mb. In order for a larger - value to work reliably, you have to try to make it accord - with the process stack limit. */ -size_t re_max_failures = 40000; -# else -size_t re_max_failures = 4000; -# endif - -union fail_stack_elt -{ - re_char *pointer; - /* This should be the biggest `int' that's no bigger than a pointer. */ - long integer; -}; - -typedef union fail_stack_elt fail_stack_elt_t; - -typedef struct -{ - fail_stack_elt_t *stack; - size_t size; - size_t avail; /* Offset of next open position. */ - size_t frame; /* Offset of the cur constructed frame. */ -} fail_stack_type; - -#define FAIL_STACK_EMPTY() (fail_stack.frame == 0) -#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) - - -/* Define macros to initialize and free the failure stack. - Do `return -2' if the alloc fails. */ - -#ifdef MATCH_MAY_ALLOCATE -# define INIT_FAIL_STACK() \ - do { \ - fail_stack.stack = (fail_stack_elt_t *) \ - REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * TYPICAL_FAILURE_SIZE \ - * sizeof (fail_stack_elt_t)); \ - \ - if (fail_stack.stack == NULL) \ - return -2; \ - \ - fail_stack.size = INIT_FAILURE_ALLOC; \ - fail_stack.avail = 0; \ - fail_stack.frame = 0; \ - } while (0) - -# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) -#else -# define INIT_FAIL_STACK() \ - do { \ - fail_stack.avail = 0; \ - fail_stack.frame = 0; \ - } while (0) - -# define RESET_FAIL_STACK() ((void)0) -#endif - - -/* Double the size of FAIL_STACK, up to a limit - which allows 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_STACK requires `destination' be declared. */ - -/* Factor to increase the failure stack size by - when we increase it. - This used to be 2, but 2 was too wasteful - because the old discarded stacks added up to as much space - were as ultimate, maximum-size stack. */ -#define FAIL_STACK_GROWTH_FACTOR 4 - -#define GROW_FAIL_STACK(fail_stack) \ - (((fail_stack).size * sizeof (fail_stack_elt_t) \ - >= re_max_failures * TYPICAL_FAILURE_SIZE) \ - ? 0 \ - : ((fail_stack).stack \ - = (fail_stack_elt_t *) \ - REGEX_REALLOCATE_STACK ((fail_stack).stack, \ - (fail_stack).size * sizeof (fail_stack_elt_t), \ - MIN (re_max_failures * TYPICAL_FAILURE_SIZE, \ - ((fail_stack).size * sizeof (fail_stack_elt_t) \ - * FAIL_STACK_GROWTH_FACTOR))), \ - \ - (fail_stack).stack == NULL \ - ? 0 \ - : ((fail_stack).size \ - = (MIN (re_max_failures * TYPICAL_FAILURE_SIZE, \ - ((fail_stack).size * sizeof (fail_stack_elt_t) \ - * FAIL_STACK_GROWTH_FACTOR)) \ - / sizeof (fail_stack_elt_t)), \ - 1))) - - -/* Push a pointer value onto the failure stack. - Assumes the variable `fail_stack'. Probably should only - be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_POINTER(item) \ - fail_stack.stack[fail_stack.avail++].pointer = (item) - -/* This pushes an integer-valued item onto the failure stack. - Assumes the variable `fail_stack'. Probably should only - be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_INT(item) \ - fail_stack.stack[fail_stack.avail++].integer = (item) - -/* Push a fail_stack_elt_t value onto the failure stack. - Assumes the variable `fail_stack'. Probably should only - be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_ELT(item) \ - fail_stack.stack[fail_stack.avail++] = (item) - -/* These three POP... operations complement the three PUSH... operations. - All assume that `fail_stack' is nonempty. */ -#define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer -#define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer -#define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] - -/* Individual items aside from the registers. */ -#define NUM_NONREG_ITEMS 3 - -/* Used to examine the stack (to detect infinite loops). */ -#define FAILURE_PAT(h) fail_stack.stack[(h) - 1].pointer -#define FAILURE_STR(h) (fail_stack.stack[(h) - 2].pointer) -#define NEXT_FAILURE_HANDLE(h) fail_stack.stack[(h) - 3].integer -#define TOP_FAILURE_HANDLE() fail_stack.frame - - -#define ENSURE_FAIL_STACK(space) \ -while (REMAINING_AVAIL_SLOTS <= space) { \ - if (!GROW_FAIL_STACK (fail_stack)) \ - return -2; \ - DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", (fail_stack).size);\ - DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ -} - -/* Push register NUM onto the stack. */ -#define PUSH_FAILURE_REG(num) \ -do { \ - char *destination; \ - ENSURE_FAIL_STACK(3); \ - DEBUG_PRINT4 (" Push reg %d (spanning %p -> %p)\n", \ - num, regstart[num], regend[num]); \ - PUSH_FAILURE_POINTER (regstart[num]); \ - PUSH_FAILURE_POINTER (regend[num]); \ - PUSH_FAILURE_INT (num); \ -} while (0) - -/* Change the counter's value to VAL, but make sure that it will - be reset when backtracking. */ -#define PUSH_NUMBER(ptr,val) \ -do { \ - char *destination; \ - int c; \ - ENSURE_FAIL_STACK(3); \ - EXTRACT_NUMBER (c, ptr); \ - DEBUG_PRINT4 (" Push number %p = %d -> %d\n", ptr, c, val); \ - PUSH_FAILURE_INT (c); \ - PUSH_FAILURE_POINTER (ptr); \ - PUSH_FAILURE_INT (-1); \ - STORE_NUMBER (ptr, val); \ -} while (0) - -/* Pop a saved register off the stack. */ -#define POP_FAILURE_REG_OR_COUNT() \ -do { \ - int reg = POP_FAILURE_INT (); \ - if (reg == -1) \ - { \ - /* It's a counter. */ \ - /* Here, we discard `const', making re_match non-reentrant. */ \ - unsigned char *ptr = (unsigned char*) POP_FAILURE_POINTER (); \ - reg = POP_FAILURE_INT (); \ - STORE_NUMBER (ptr, reg); \ - DEBUG_PRINT3 (" Pop counter %p = %d\n", ptr, reg); \ - } \ - else \ - { \ - regend[reg] = POP_FAILURE_POINTER (); \ - regstart[reg] = POP_FAILURE_POINTER (); \ - DEBUG_PRINT4 (" Pop reg %d (spanning %p -> %p)\n", \ - reg, regstart[reg], regend[reg]); \ - } \ -} while (0) - -/* Check that we are not stuck in an infinite loop. */ -#define CHECK_INFINITE_LOOP(pat_cur, string_place) \ -do { \ - int failure = TOP_FAILURE_HANDLE (); \ - /* Check for infinite matching loops */ \ - while (failure > 0 \ - && (FAILURE_STR (failure) == string_place \ - || FAILURE_STR (failure) == NULL)) \ - { \ - assert (FAILURE_PAT (failure) >= bufp->buffer \ - && FAILURE_PAT (failure) <= bufp->buffer + bufp->used); \ - if (FAILURE_PAT (failure) == pat_cur) \ - { \ - cycle = 1; \ - break; \ - } \ - DEBUG_PRINT2 (" Other pattern: %p\n", FAILURE_PAT (failure)); \ - failure = NEXT_FAILURE_HANDLE(failure); \ - } \ - DEBUG_PRINT2 (" Other string: %p\n", FAILURE_STR (failure)); \ -} while (0) - -/* Push the information about the state we will need - if we ever fail back to it. - - Requires variables fail_stack, regstart, regend and - num_regs be declared. GROW_FAIL_STACK requires `destination' be - declared. - - Does `return FAILURE_CODE' if runs out of memory. */ - -#define PUSH_FAILURE_POINT(pattern, string_place) \ -do { \ - char *destination; \ - /* Must be int, so when we don't save any registers, the arithmetic \ - of 0 + -1 isn't done as unsigned. */ \ - \ - DEBUG_STATEMENT (nfailure_points_pushed++); \ - DEBUG_PRINT1 ("\nPUSH_FAILURE_POINT:\n"); \ - DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail); \ - DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ - \ - ENSURE_FAIL_STACK (NUM_NONREG_ITEMS); \ - \ - DEBUG_PRINT1 ("\n"); \ - \ - DEBUG_PRINT2 (" Push frame index: %d\n", fail_stack.frame); \ - PUSH_FAILURE_INT (fail_stack.frame); \ - \ - DEBUG_PRINT2 (" Push string %p: `", string_place); \ - DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, size2);\ - DEBUG_PRINT1 ("'\n"); \ - PUSH_FAILURE_POINTER (string_place); \ - \ - DEBUG_PRINT2 (" Push pattern %p: ", pattern); \ - DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern, pend); \ - PUSH_FAILURE_POINTER (pattern); \ - \ - /* Close the frame by moving the frame pointer past it. */ \ - fail_stack.frame = fail_stack.avail; \ -} while (0) - -/* Estimate the size of data pushed by a typical failure stack entry. - An estimate is all we need, because all we use this for - is to choose a limit for how big to make the failure stack. */ -/* BEWARE, the value `20' is hard-coded in emacs.c:main(). */ -#define TYPICAL_FAILURE_SIZE 20 - -/* 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. - REGSTART, REGEND -- arrays of string positions. - - Also assumes the variables `fail_stack' and (if debugging), `bufp', - `pend', `string1', `size1', `string2', and `size2'. */ - -#define POP_FAILURE_POINT(str, pat) \ -do { \ - 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); \ - \ - /* Pop the saved registers. */ \ - while (fail_stack.frame < fail_stack.avail) \ - POP_FAILURE_REG_OR_COUNT (); \ - \ - pat = POP_FAILURE_POINTER (); \ - DEBUG_PRINT2 (" Popping pattern %p: ", pat); \ - DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ - \ - /* 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. */ \ - str = POP_FAILURE_POINTER (); \ - DEBUG_PRINT2 (" Popping string %p: `", str); \ - DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ - DEBUG_PRINT1 ("'\n"); \ - \ - fail_stack.frame = POP_FAILURE_INT (); \ - DEBUG_PRINT2 (" Popping frame index: %d\n", fail_stack.frame); \ - \ - assert (fail_stack.avail >= 0); \ - assert (fail_stack.frame <= fail_stack.avail); \ - \ - DEBUG_STATEMENT (nfailure_points_popped++); \ -} while (0) /* POP_FAILURE_POINT */ - - - -/* Registers are set to a sentinel when they haven't yet matched. */ -#define REG_UNSET(e) ((e) == NULL) - -/* Subroutine declarations and macros for regex_compile. */ - -static reg_errcode_t regex_compile _RE_ARGS ((re_char *pattern, size_t size, - reg_syntax_t syntax, - struct re_pattern_buffer *bufp)); -static void store_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, int arg)); -static void store_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, - int arg1, int arg2)); -static void insert_op1 _RE_ARGS ((re_opcode_t op, unsigned char *loc, - int arg, unsigned char *end)); -static void insert_op2 _RE_ARGS ((re_opcode_t op, unsigned char *loc, - int arg1, int arg2, unsigned char *end)); -static boolean at_begline_loc_p _RE_ARGS ((re_char *pattern, - re_char *p, - reg_syntax_t syntax)); -static boolean at_endline_loc_p _RE_ARGS ((re_char *p, - re_char *pend, - reg_syntax_t syntax)); -static re_char *skip_one_char _RE_ARGS ((re_char *p)); -static int analyse_first _RE_ARGS ((re_char *p, re_char *pend, - char *fastmap, const int multibyte)); - -/* Fetch the next character in the uncompiled pattern, with no - translation. */ -#define PATFETCH(c) \ - do { \ - int len; \ - if (p == pend) return REG_EEND; \ - c = RE_STRING_CHAR_AND_LENGTH (p, pend - p, len); \ - p += len; \ - } while (0) - - -/* 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. */ -#ifndef TRANSLATE -# define TRANSLATE(d) \ - (RE_TRANSLATE_P (translate) ? RE_TRANSLATE (translate, (d)) : (d)) -#endif - - -/* 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 ((size_t) (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^15 bytes turns out to - be too small, many things would have to change. */ -# define MAX_BUF_SIZE (1L << 15) - -#if 0 /* This is when we thought it could be 2^16 bytes. */ -/* Any other compiler which, like MSC, has allocation limit below 2^16 - bytes will have to use approach similar to what was done below for - MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up - reallocating to 0 bytes. Such thing is not going to work too well. - You have been warned!! */ -#if defined _MSC_VER && !defined WIN32 -/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. */ -# define MAX_BUF_SIZE 65500L -#else -# define MAX_BUF_SIZE (1L << 16) -#endif -#endif /* 0 */ - -/* 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. */ -#if __BOUNDED_POINTERS__ -# define SET_HIGH_BOUND(P) (__ptrhigh (P) = __ptrlow (P) + bufp->allocated) -# define MOVE_BUFFER_POINTER(P) \ - (__ptrlow (P) += incr, SET_HIGH_BOUND (P), __ptrvalue (P) += incr) -# define ELSE_EXTEND_BUFFER_HIGH_BOUND \ - else \ - { \ - SET_HIGH_BOUND (b); \ - SET_HIGH_BOUND (begalt); \ - if (fixup_alt_jump) \ - SET_HIGH_BOUND (fixup_alt_jump); \ - if (laststart) \ - SET_HIGH_BOUND (laststart); \ - if (pending_exact) \ - SET_HIGH_BOUND (pending_exact); \ - } -#else -# define MOVE_BUFFER_POINTER(P) (P) += incr -# define ELSE_EXTEND_BUFFER_HIGH_BOUND -#endif -#define EXTEND_BUFFER() \ - do { \ - re_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; \ - RETALLOC (bufp->buffer, bufp->allocated, unsigned char); \ - if (bufp->buffer == NULL) \ - return REG_ESPACE; \ - /* If the buffer moved, move all the pointers into it. */ \ - if (old_buffer != bufp->buffer) \ - { \ - int incr = bufp->buffer - old_buffer; \ - MOVE_BUFFER_POINTER (b); \ - MOVE_BUFFER_POINTER (begalt); \ - if (fixup_alt_jump) \ - MOVE_BUFFER_POINTER (fixup_alt_jump); \ - if (laststart) \ - MOVE_BUFFER_POINTER (laststart); \ - if (pending_exact) \ - MOVE_BUFFER_POINTER (pending_exact); \ - } \ - ELSE_EXTEND_BUFFER_HIGH_BOUND \ - } 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 int 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. */ -/* int may be not enough when sizeof(int) == 2. */ -typedef long pattern_offset_t; - -typedef struct -{ - pattern_offset_t begalt_offset; - pattern_offset_t fixup_alt_jump; - 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]) - -/* Explicit quit checking is only used on NTemacs. */ -#if defined WINDOWSNT && defined emacs && defined QUIT -extern int immediate_quit; -# define IMMEDIATE_QUIT_CHECK \ - do { \ - if (immediate_quit) QUIT; \ - } while (0) -#else -# define IMMEDIATE_QUIT_CHECK ((void)0) -#endif - -/* Structure to manage work area for range table. */ -struct range_table_work_area -{ - int *table; /* actual work area. */ - int allocated; /* allocated size for work area in bytes. */ - int used; /* actually used size in words. */ - int bits; /* flag to record character classes */ -}; - -/* Make sure that WORK_AREA can hold more N multibyte characters. - This is used only in set_image_of_range and set_image_of_range_1. - It expects WORK_AREA to be a pointer. - If it can't get the space, it returns from the surrounding function. */ - -#define EXTEND_RANGE_TABLE(work_area, n) \ - do { \ - if (((work_area)->used + (n)) * sizeof (int) > (work_area)->allocated) \ - { \ - extend_range_table_work_area (work_area); \ - if ((work_area)->table == 0) \ - return (REG_ESPACE); \ - } \ - } while (0) - -#define SET_RANGE_TABLE_WORK_AREA_BIT(work_area, bit) \ - (work_area).bits |= (bit) - -/* Bits used to implement the multibyte-part of the various character classes - such as [:alnum:] in a charset's range table. */ -#define BIT_WORD 0x1 -#define BIT_LOWER 0x2 -#define BIT_PUNCT 0x4 -#define BIT_SPACE 0x8 -#define BIT_UPPER 0x10 -#define BIT_MULTIBYTE 0x20 - -/* Set a range START..END to WORK_AREA. - The range is passed through TRANSLATE, so START and END - should be untranslated. */ -#define SET_RANGE_TABLE_WORK_AREA(work_area, start, end) \ - do { \ - int tem; \ - tem = set_image_of_range (&work_area, start, end, translate); \ - if (tem > 0) \ - FREE_STACK_RETURN (tem); \ - } while (0) - -/* Free allocated memory for WORK_AREA. */ -#define FREE_RANGE_TABLE_WORK_AREA(work_area) \ - do { \ - if ((work_area).table) \ - free ((work_area).table); \ - } while (0) - -#define CLEAR_RANGE_TABLE_WORK_USED(work_area) ((work_area).used = 0, (work_area).bits = 0) -#define RANGE_TABLE_WORK_USED(work_area) ((work_area).used) -#define RANGE_TABLE_WORK_BITS(work_area) ((work_area).bits) -#define RANGE_TABLE_WORK_ELT(work_area, i) ((work_area).table[i]) - - -/* Set the bit for character C in a list. */ -#define SET_LIST_BIT(c) (b[((c)) / BYTEWIDTH] |= 1 << ((c) % BYTEWIDTH)) - - -/* Get the next unsigned number in the uncompiled pattern. */ -#define GET_UNSIGNED_NUMBER(num) \ - do { if (p != pend) \ - { \ - PATFETCH (c); \ - if (c == ' ') \ - FREE_STACK_RETURN (REG_BADBR); \ - while ('0' <= c && c <= '9') \ - { \ - int prev; \ - if (num < 0) \ - num = 0; \ - prev = num; \ - num = num * 10 + c - '0'; \ - if (num / 10 != prev) \ - FREE_STACK_RETURN (REG_BADBR); \ - if (p == pend) \ - break; \ - PATFETCH (c); \ - } \ - if (c == ' ') \ - FREE_STACK_RETURN (REG_BADBR); \ - } \ - } while (0) - -#if WIDE_CHAR_SUPPORT -/* The GNU C library provides support for user-defined character classes - and the functions from ISO C amendement 1. */ -# ifdef CHARCLASS_NAME_MAX -# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX -# else -/* This shouldn't happen but some implementation might still have this - problem. Use a reasonable default value. */ -# define CHAR_CLASS_MAX_LENGTH 256 -# endif -typedef wctype_t re_wctype_t; -typedef wchar_t re_wchar_t; -# define re_wctype wctype -# define re_iswctype iswctype -# define re_wctype_to_bit(cc) 0 -#else -# define CHAR_CLASS_MAX_LENGTH 9 /* Namely, `multibyte'. */ -# define btowc(c) c - -/* Character classes. */ -typedef enum { RECC_ERROR = 0, - RECC_ALNUM, RECC_ALPHA, RECC_WORD, - RECC_GRAPH, RECC_PRINT, - RECC_LOWER, RECC_UPPER, - RECC_PUNCT, RECC_CNTRL, - RECC_DIGIT, RECC_XDIGIT, - RECC_BLANK, RECC_SPACE, - RECC_MULTIBYTE, RECC_NONASCII, - RECC_ASCII, RECC_UNIBYTE -} re_wctype_t; - -typedef int re_wchar_t; - -/* Map a string to the char class it names (if any). */ -static re_wctype_t -re_wctype (str) - re_char *str; -{ - const char *string = str; - if (STREQ (string, "alnum")) return RECC_ALNUM; - else if (STREQ (string, "alpha")) return RECC_ALPHA; - else if (STREQ (string, "word")) return RECC_WORD; - else if (STREQ (string, "ascii")) return RECC_ASCII; - else if (STREQ (string, "nonascii")) return RECC_NONASCII; - else if (STREQ (string, "graph")) return RECC_GRAPH; - else if (STREQ (string, "lower")) return RECC_LOWER; - else if (STREQ (string, "print")) return RECC_PRINT; - else if (STREQ (string, "punct")) return RECC_PUNCT; - else if (STREQ (string, "space")) return RECC_SPACE; - else if (STREQ (string, "upper")) return RECC_UPPER; - else if (STREQ (string, "unibyte")) return RECC_UNIBYTE; - else if (STREQ (string, "multibyte")) return RECC_MULTIBYTE; - else if (STREQ (string, "digit")) return RECC_DIGIT; - else if (STREQ (string, "xdigit")) return RECC_XDIGIT; - else if (STREQ (string, "cntrl")) return RECC_CNTRL; - else if (STREQ (string, "blank")) return RECC_BLANK; - else return 0; -} - -/* True iff CH is in the char class CC. */ -static boolean -re_iswctype (ch, cc) - int ch; - re_wctype_t cc; -{ - switch (cc) - { - case RECC_ALNUM: return ISALNUM (ch); - case RECC_ALPHA: return ISALPHA (ch); - case RECC_BLANK: return ISBLANK (ch); - case RECC_CNTRL: return ISCNTRL (ch); - case RECC_DIGIT: return ISDIGIT (ch); - case RECC_GRAPH: return ISGRAPH (ch); - case RECC_LOWER: return ISLOWER (ch); - case RECC_PRINT: return ISPRINT (ch); - case RECC_PUNCT: return ISPUNCT (ch); - case RECC_SPACE: return ISSPACE (ch); - case RECC_UPPER: return ISUPPER (ch); - case RECC_XDIGIT: return ISXDIGIT (ch); - case RECC_ASCII: return IS_REAL_ASCII (ch); - case RECC_NONASCII: return !IS_REAL_ASCII (ch); - case RECC_UNIBYTE: return ISUNIBYTE (ch); - case RECC_MULTIBYTE: return !ISUNIBYTE (ch); - case RECC_WORD: return ISWORD (ch); - case RECC_ERROR: return false; - default: - abort(); - } -} - -/* Return a bit-pattern to use in the range-table bits to match multibyte - chars of class CC. */ -static int -re_wctype_to_bit (cc) - re_wctype_t cc; -{ - switch (cc) - { - case RECC_NONASCII: case RECC_PRINT: case RECC_GRAPH: - case RECC_MULTIBYTE: return BIT_MULTIBYTE; - case RECC_ALPHA: case RECC_ALNUM: case RECC_WORD: return BIT_WORD; - case RECC_LOWER: return BIT_LOWER; - case RECC_UPPER: return BIT_UPPER; - case RECC_PUNCT: return BIT_PUNCT; - case RECC_SPACE: return BIT_SPACE; - case RECC_ASCII: case RECC_DIGIT: case RECC_XDIGIT: case RECC_CNTRL: - case RECC_BLANK: case RECC_UNIBYTE: case RECC_ERROR: return 0; - default: - abort(); - } -} -#endif - -/* Filling in the work area of a range. */ - -/* Actually extend the space in WORK_AREA. */ - -static void -extend_range_table_work_area (work_area) - struct range_table_work_area *work_area; -{ - work_area->allocated += 16 * sizeof (int); - if (work_area->table) - work_area->table - = (int *) realloc (work_area->table, work_area->allocated); - else - work_area->table - = (int *) malloc (work_area->allocated); -} - -#ifdef emacs - -/* Carefully find the ranges of codes that are equivalent - under case conversion to the range start..end when passed through - TRANSLATE. Handle the case where non-letters can come in between - two upper-case letters (which happens in Latin-1). - Also handle the case of groups of more than 2 case-equivalent chars. - - The basic method is to look at consecutive characters and see - if they can form a run that can be handled as one. - - Returns -1 if successful, REG_ESPACE if ran out of space. */ - -static int -set_image_of_range_1 (work_area, start, end, translate) - RE_TRANSLATE_TYPE translate; - struct range_table_work_area *work_area; - re_wchar_t start, end; -{ - /* `one_case' indicates a character, or a run of characters, - each of which is an isolate (no case-equivalents). - This includes all ASCII non-letters. - - `two_case' indicates a character, or a run of characters, - each of which has two case-equivalent forms. - This includes all ASCII letters. - - `strange' indicates a character that has more than one - case-equivalent. */ - - enum case_type {one_case, two_case, strange}; - - /* Describe the run that is in progress, - which the next character can try to extend. - If run_type is strange, that means there really is no run. - If run_type is one_case, then run_start...run_end is the run. - If run_type is two_case, then the run is run_start...run_end, - and the case-equivalents end at run_eqv_end. */ - - enum case_type run_type = strange; - int run_start, run_end, run_eqv_end; - - Lisp_Object eqv_table; - - if (!RE_TRANSLATE_P (translate)) - { - EXTEND_RANGE_TABLE (work_area, 2); - work_area->table[work_area->used++] = (start); - work_area->table[work_area->used++] = (end); - return -1; - } - - eqv_table = XCHAR_TABLE (translate)->extras[2]; - - for (; start <= end; start++) - { - enum case_type this_type; - int eqv = RE_TRANSLATE (eqv_table, start); - int minchar, maxchar; - - /* Classify this character */ - if (eqv == start) - this_type = one_case; - else if (RE_TRANSLATE (eqv_table, eqv) == start) - this_type = two_case; - else - this_type = strange; - - if (start < eqv) - minchar = start, maxchar = eqv; - else - minchar = eqv, maxchar = start; - - /* Can this character extend the run in progress? */ - if (this_type == strange || this_type != run_type - || !(minchar == run_end + 1 - && (run_type == two_case - ? maxchar == run_eqv_end + 1 : 1))) - { - /* No, end the run. - Record each of its equivalent ranges. */ - if (run_type == one_case) - { - EXTEND_RANGE_TABLE (work_area, 2); - work_area->table[work_area->used++] = run_start; - work_area->table[work_area->used++] = run_end; - } - else if (run_type == two_case) - { - EXTEND_RANGE_TABLE (work_area, 4); - work_area->table[work_area->used++] = run_start; - work_area->table[work_area->used++] = run_end; - work_area->table[work_area->used++] - = RE_TRANSLATE (eqv_table, run_start); - work_area->table[work_area->used++] - = RE_TRANSLATE (eqv_table, run_end); - } - run_type = strange; - } - - if (this_type == strange) - { - /* For a strange character, add each of its equivalents, one - by one. Don't start a range. */ - do - { - EXTEND_RANGE_TABLE (work_area, 2); - work_area->table[work_area->used++] = eqv; - work_area->table[work_area->used++] = eqv; - eqv = RE_TRANSLATE (eqv_table, eqv); - } - while (eqv != start); - } - - /* Add this char to the run, or start a new run. */ - else if (run_type == strange) - { - /* Initialize a new range. */ - run_type = this_type; - run_start = start; - run_end = start; - run_eqv_end = RE_TRANSLATE (eqv_table, run_end); - } - else - { - /* Extend a running range. */ - run_end = minchar; - run_eqv_end = RE_TRANSLATE (eqv_table, run_end); - } - } - - /* If a run is still in progress at the end, finish it now - by recording its equivalent ranges. */ - if (run_type == one_case) - { - EXTEND_RANGE_TABLE (work_area, 2); - work_area->table[work_area->used++] = run_start; - work_area->table[work_area->used++] = run_end; - } - else if (run_type == two_case) - { - EXTEND_RANGE_TABLE (work_area, 4); - work_area->table[work_area->used++] = run_start; - work_area->table[work_area->used++] = run_end; - work_area->table[work_area->used++] - = RE_TRANSLATE (eqv_table, run_start); - work_area->table[work_area->used++] - = RE_TRANSLATE (eqv_table, run_end); - } - - return -1; -} - -#endif /* emacs */ - -/* Record the the image of the range start..end when passed through - TRANSLATE. This is not necessarily TRANSLATE(start)..TRANSLATE(end) - and is not even necessarily contiguous. - Normally we approximate it with the smallest contiguous range that contains - all the chars we need. However, for Latin-1 we go to extra effort - to do a better job. - - This function is not called for ASCII ranges. - - Returns -1 if successful, REG_ESPACE if ran out of space. */ - -static int -set_image_of_range (work_area, start, end, translate) - RE_TRANSLATE_TYPE translate; - struct range_table_work_area *work_area; - re_wchar_t start, end; -{ - re_wchar_t cmin, cmax; - -#ifdef emacs - /* For Latin-1 ranges, use set_image_of_range_1 - to get proper handling of ranges that include letters and nonletters. - For a range that includes the whole of Latin-1, this is not necessary. - For other character sets, we don't bother to get this right. */ - if (RE_TRANSLATE_P (translate) && start < 04400 - && !(start < 04200 && end >= 04377)) - { - int newend; - int tem; - newend = end; - if (newend > 04377) - newend = 04377; - tem = set_image_of_range_1 (work_area, start, newend, translate); - if (tem > 0) - return tem; - - start = 04400; - if (end < 04400) - return -1; - } -#endif - - EXTEND_RANGE_TABLE (work_area, 2); - work_area->table[work_area->used++] = (start); - work_area->table[work_area->used++] = (end); - - cmin = -1, cmax = -1; - - if (RE_TRANSLATE_P (translate)) - { - int ch; - - for (ch = start; ch <= end; ch++) - { - re_wchar_t c = TRANSLATE (ch); - if (! (start <= c && c <= end)) - { - if (cmin == -1) - cmin = c, cmax = c; - else - { - cmin = MIN (cmin, c); - cmax = MAX (cmax, c); - } - } - } - - if (cmin != -1) - { - EXTEND_RANGE_TABLE (work_area, 2); - work_area->table[work_area->used++] = (cmin); - work_area->table[work_area->used++] = (cmax); - } - } - - return -1; -} - -#ifndef MATCH_MAY_ALLOCATE - -/* If we cannot allocate large objects within re_match_2_internal, - we make the fail stack and register vectors global. - The fail stack, we grow to the maximum size when a regexp - is compiled. - The register vectors, we adjust in size each time we - compile a regexp, according to the number of registers it needs. */ - -static fail_stack_type fail_stack; - -/* Size with which the following vectors are currently allocated. - That is so we can make them bigger as needed, - but never make them smaller. */ -static int regs_allocated_size; - -static re_char ** regstart, ** regend; -static re_char **best_regstart, **best_regend; - -/* Make the register vectors big enough for NUM_REGS registers, - but don't make them smaller. */ - -static -regex_grow_registers (num_regs) - int num_regs; -{ - if (num_regs > regs_allocated_size) - { - RETALLOC_IF (regstart, num_regs, re_char *); - RETALLOC_IF (regend, num_regs, re_char *); - RETALLOC_IF (best_regstart, num_regs, re_char *); - RETALLOC_IF (best_regend, num_regs, re_char *); - - regs_allocated_size = num_regs; - } -} - -#endif /* not MATCH_MAY_ALLOCATE */ - -static boolean group_in_compile_stack _RE_ARGS ((compile_stack_type - compile_stack, - regnum_t regnum)); - -/* `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' field is neither examined nor set. */ - -/* Insert the `jump' from the end of last alternative to "here". - The space for the jump has already been allocated. */ -#define FIXUP_ALT_JUMP() \ -do { \ - if (fixup_alt_jump) \ - STORE_JUMP (jump, fixup_alt_jump, b); \ -} while (0) - - -/* Return, freeing storage we allocated. */ -#define FREE_STACK_RETURN(value) \ - do { \ - FREE_RANGE_TABLE_WORK_AREA (range_table_work); \ - free (compile_stack.stack); \ - return value; \ - } while (0) - -static reg_errcode_t -regex_compile (pattern, size, syntax, bufp) - re_char *pattern; - size_t size; - reg_syntax_t syntax; - struct re_pattern_buffer *bufp; -{ - /* We fetch characters from PATTERN here. */ - register re_wchar_t c, c1; - - /* A random temporary spot in PATTERN. */ - re_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. */ -#ifdef AIX - /* `const' makes AIX compiler fail. */ - unsigned char *p = pattern; -#else - re_char *p = pattern; -#endif - re_char *pend = pattern + size; - - /* How to translate the characters in the pattern. */ - RE_TRANSLATE_TYPE 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. */ - re_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; - - /* Work area for range table of charset. */ - struct range_table_work_area range_table_work; - - /* If the object matched can contain multibyte characters. */ - const boolean multibyte = RE_MULTIBYTE_P (bufp); - -#ifdef DEBUG - debug++; - DEBUG_PRINT1 ("\nCompiling pattern: "); - if (debug > 0) - { - unsigned debug_count; - - for (debug_count = 0; debug_count < size; debug_count++) - putchar (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; - - range_table_work.table = 0; - range_table_work.allocated = 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) FREE_STACK_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 ((syntax & RE_NO_NEWLINE_ANCHOR) ? begbuf : 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 ((syntax & RE_NO_NEWLINE_ANCHOR) ? endbuf : 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) - FREE_STACK_RETURN (REG_BADRPT); - else if (!(syntax & RE_CONTEXT_INDEP_OPS)) - goto normal_char; - } - - { - /* 1 means zero (many) matches is allowed. */ - boolean zero_times_ok = 0, many_times_ok = 0; - boolean greedy = 1; - - /* 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 (;;) - { - if ((syntax & RE_FRUGAL) - && c == '?' && (zero_times_ok || many_times_ok)) - greedy = 0; - else - { - zero_times_ok |= c != '+'; - many_times_ok |= c != '?'; - } - - if (p == pend) - break; - else if (*p == '*' - || (!(syntax & RE_BK_PLUS_QM) - && (*p == '+' || *p == '?'))) - ; - else if (syntax & RE_BK_PLUS_QM && *p == '\\') - { - if (p+1 == pend) - FREE_STACK_RETURN (REG_EESCAPE); - if (p[1] == '+' || p[1] == '?') - PATFETCH (c); /* Gobble up the backslash. */ - else - break; - } - else - break; - /* If we get here, we found another repeat character. */ - PATFETCH (c); - } - - /* Star, etc. applied to an empty pattern is equivalent - to an empty pattern. */ - if (!laststart || laststart == b) - break; - - /* Now we know whether or not zero matches is allowed - and also whether or not two or more matches is allowed. */ - if (greedy) - { - if (many_times_ok) - { - boolean simple = skip_one_char (laststart) == b; - unsigned int startoffset = 0; - re_opcode_t ofj = - /* Check if the loop can match the empty string. */ - (simple || !analyse_first (laststart, b, NULL, 0)) - ? on_failure_jump : on_failure_jump_loop; - assert (skip_one_char (laststart) <= b); - - if (!zero_times_ok && simple) - { /* Since simple * loops can be made faster by using - on_failure_keep_string_jump, we turn simple P+ - into PP* if P is simple. */ - unsigned char *p1, *p2; - startoffset = b - laststart; - GET_BUFFER_SPACE (startoffset); - p1 = b; p2 = laststart; - while (p2 < p1) - *b++ = *p2++; - zero_times_ok = 1; - } - - GET_BUFFER_SPACE (6); - if (!zero_times_ok) - /* A + loop. */ - STORE_JUMP (ofj, b, b + 6); - else - /* Simple * loops can use on_failure_keep_string_jump - depending on what follows. But since we don't know - that yet, we leave the decision up to - on_failure_jump_smart. */ - INSERT_JUMP (simple ? on_failure_jump_smart : ofj, - laststart + startoffset, b + 6); - b += 3; - STORE_JUMP (jump, b, laststart + startoffset); - b += 3; - } - else - { - /* A simple ? pattern. */ - assert (zero_times_ok); - GET_BUFFER_SPACE (3); - INSERT_JUMP (on_failure_jump, laststart, b + 3); - b += 3; - } - } - else /* not greedy */ - { /* I wish the greedy and non-greedy cases could be merged. */ - - GET_BUFFER_SPACE (7); /* We might use less. */ - if (many_times_ok) - { - boolean emptyp = analyse_first (laststart, b, NULL, 0); - - /* The non-greedy multiple match looks like - a repeat..until: we only need a conditional jump - at the end of the loop. */ - if (emptyp) BUF_PUSH (no_op); - STORE_JUMP (emptyp ? on_failure_jump_nastyloop - : on_failure_jump, b, laststart); - b += 3; - if (zero_times_ok) - { - /* The repeat...until naturally matches one or more. - To also match zero times, we need to first jump to - the end of the loop (its conditional jump). */ - INSERT_JUMP (jump, laststart, b); - b += 3; - } - } - else - { - /* non-greedy a?? */ - INSERT_JUMP (jump, laststart, b + 3); - b += 3; - INSERT_JUMP (on_failure_jump, laststart, laststart + 6); - b += 3; - } - } - } - pending_exact = 0; - break; - - - case '.': - laststart = b; - BUF_PUSH (anychar); - break; - - - case '[': - { - CLEAR_RANGE_TABLE_WORK_USED (range_table_work); - - if (p == pend) FREE_STACK_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 (;;) - { - boolean escaped_char = false; - const unsigned char *p2 = p; - - if (p == pend) FREE_STACK_RETURN (REG_EBRACK); - - /* Don't translate yet. The range TRANSLATE(X..Y) cannot - always be determined from TRANSLATE(X) and TRANSLATE(Y) - So the translation is done later in a loop. Example: - (let ((case-fold-search t)) (string-match "[A-_]" "A")) */ - PATFETCH (c); - - /* \ might escape characters inside [...] and [^...]. */ - if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') - { - if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); - - PATFETCH (c); - escaped_char = true; - } - else - { - /* 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 == ']' && p2 != p1) - break; - } - - /* What should we do for the character which is - greater than 0x7F, but not BASE_LEADING_CODE_P? - XXX */ - - /* See if we're at the beginning of a possible character - class. */ - - if (!escaped_char && - syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') - { - /* Leave room for the null. */ - unsigned char str[CHAR_CLASS_MAX_LENGTH + 1]; - const unsigned char *class_beg; - - PATFETCH (c); - c1 = 0; - class_beg = p; - - /* If pattern is `[[:'. */ - if (p == pend) FREE_STACK_RETURN (REG_EBRACK); - - for (;;) - { - PATFETCH (c); - if ((c == ':' && *p == ']') || p == pend) - break; - if (c1 < CHAR_CLASS_MAX_LENGTH) - str[c1++] = c; - else - /* This is in any case an invalid class name. */ - str[0] = '\0'; - } - 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 == ']') - { - re_wchar_t ch; - re_wctype_t cc; - - cc = re_wctype (str); - - if (cc == 0) - FREE_STACK_RETURN (REG_ECTYPE); - - /* Throw away the ] at the end of the character - class. */ - PATFETCH (c); - - if (p == pend) FREE_STACK_RETURN (REG_EBRACK); - - /* Most character classes in a multibyte match - just set a flag. Exceptions are is_blank, - is_digit, is_cntrl, and is_xdigit, since - they can only match ASCII characters. We - don't need to handle them for multibyte. - They are distinguished by a negative wctype. */ - - if (multibyte) - SET_RANGE_TABLE_WORK_AREA_BIT (range_table_work, - re_wctype_to_bit (cc)); - - for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) - { - int translated = TRANSLATE (ch); - if (re_iswctype (btowc (ch), cc)) - SET_LIST_BIT (translated); - } - - /* Repeat the loop. */ - continue; - } - else - { - /* Go back to right after the "[:". */ - p = class_beg; - SET_LIST_BIT ('['); - - /* Because the `:' may starts the range, we - can't simply set bit and repeat the loop. - Instead, just set it to C and handle below. */ - c = ':'; - } - } - - if (p < pend && p[0] == '-' && p[1] != ']') - { - - /* Discard the `-'. */ - PATFETCH (c1); - - /* Fetch the character which ends the range. */ - PATFETCH (c1); - - if (SINGLE_BYTE_CHAR_P (c)) - { - if (! SINGLE_BYTE_CHAR_P (c1)) - { - /* Handle a range starting with a - character of less than 256, and ending - with a character of not less than 256. - Split that into two ranges, the low one - ending at 0377, and the high one - starting at the smallest character in - the charset of C1 and ending at C1. */ - int charset = CHAR_CHARSET (c1); - re_wchar_t c2 = MAKE_CHAR (charset, 0, 0); - - SET_RANGE_TABLE_WORK_AREA (range_table_work, - c2, c1); - c1 = 0377; - } - } - else if (!SAME_CHARSET_P (c, c1)) - FREE_STACK_RETURN (REG_ERANGE); - } - else - /* Range from C to C. */ - c1 = c; - - /* Set the range ... */ - if (SINGLE_BYTE_CHAR_P (c)) - /* ... into bitmap. */ - { - re_wchar_t this_char; - re_wchar_t range_start = c, range_end = c1; - - /* If the start is after the end, the range is empty. */ - if (range_start > range_end) - { - if (syntax & RE_NO_EMPTY_RANGES) - FREE_STACK_RETURN (REG_ERANGE); - /* Else, repeat the loop. */ - } - else - { - for (this_char = range_start; this_char <= range_end; - this_char++) - SET_LIST_BIT (TRANSLATE (this_char)); - } - } - else - /* ... into range table. */ - SET_RANGE_TABLE_WORK_AREA (range_table_work, c, c1); - } - - /* 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]; - - /* Build real range table from work area. */ - if (RANGE_TABLE_WORK_USED (range_table_work) - || RANGE_TABLE_WORK_BITS (range_table_work)) - { - int i; - int used = RANGE_TABLE_WORK_USED (range_table_work); - - /* Allocate space for COUNT + RANGE_TABLE. Needs two - bytes for flags, two for COUNT, and three bytes for - each character. */ - GET_BUFFER_SPACE (4 + used * 3); - - /* Indicate the existence of range table. */ - laststart[1] |= 0x80; - - /* Store the character class flag bits into the range table. - If not in emacs, these flag bits are always 0. */ - *b++ = RANGE_TABLE_WORK_BITS (range_table_work) & 0xff; - *b++ = RANGE_TABLE_WORK_BITS (range_table_work) >> 8; - - STORE_NUMBER_AND_INCR (b, used / 2); - for (i = 0; i < used; i++) - STORE_CHARACTER_AND_INCR - (b, RANGE_TABLE_WORK_ELT (range_table_work, i)); - } - } - 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) FREE_STACK_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 (c); - - switch (c) - { - case '(': - if (syntax & RE_NO_BK_PARENS) - goto normal_backslash; - - handle_open: - { - int shy = 0; - if (p+1 < pend) - { - /* Look for a special (?...) construct */ - if ((syntax & RE_SHY_GROUPS) && *p == '?') - { - PATFETCH (c); /* Gobble up the '?'. */ - PATFETCH (c); - switch (c) - { - case ':': shy = 1; break; - default: - /* Only (?:...) is supported right now. */ - FREE_STACK_RETURN (REG_BADPAT); - } - } - } - - if (!shy) - { - 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 = shy ? -regnum : regnum; - - /* Do not push a - start_memory for groups beyond the last one we can - represent in the compiled pattern. */ - if (regnum <= MAX_REGNUM && !shy) - BUF_PUSH_2 (start_memory, regnum); - - 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 - FREE_STACK_RETURN (REG_ERPAREN); - } - - handle_close: - FIXUP_ALT_JUMP (); - - /* See similar code for backslashed left paren above. */ - if (COMPILE_STACK_EMPTY) - { - if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) - goto normal_char; - else - FREE_STACK_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 && this_group_regnum > 0) - BUF_PUSH_2 (stop_memory, 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'. */ - - FIXUP_ALT_JUMP (); - - /* 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_NO_BK_BRACES)) - 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 = 0, upper_bound = -1; - - beg_interval = p; - - if (p == pend) - FREE_STACK_RETURN (REG_EBRACE); - - GET_UNSIGNED_NUMBER (lower_bound); - - if (c == ',') - GET_UNSIGNED_NUMBER (upper_bound); - else - /* Interval such as `{1}' => match exactly once. */ - upper_bound = lower_bound; - - if (lower_bound < 0 || upper_bound > RE_DUP_MAX - || (upper_bound >= 0 && lower_bound > upper_bound)) - FREE_STACK_RETURN (REG_BADBR); - - if (!(syntax & RE_NO_BK_BRACES)) - { - if (c != '\\') - FREE_STACK_RETURN (REG_BADBR); - - PATFETCH (c); - } - - if (c != '}') - FREE_STACK_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) - FREE_STACK_RETURN (REG_BADRPT); - else if (syntax & RE_CONTEXT_INDEP_OPS) - laststart = b; - else - goto unfetch_interval; - } - - if (upper_bound == 0) - /* If the upper bound is zero, just drop the sub pattern - altogether. */ - b = laststart; - else if (lower_bound == 1 && upper_bound == 1) - /* Just match it once: nothing to do here. */ - ; - - /* 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> <succeed_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 int nbytes = (upper_bound < 0 ? 3 - : upper_bound > 1 ? 5 : 0); - unsigned int startoffset = 0; - - GET_BUFFER_SPACE (20); /* We might use less. */ - - if (lower_bound == 0) - { - /* A succeed_n that starts with 0 is really a - a simple on_failure_jump_loop. */ - INSERT_JUMP (on_failure_jump_loop, laststart, - b + 3 + nbytes); - b += 3; - } - else - { - /* 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 + nbytes, - 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; - startoffset += 5; - } - - if (upper_bound < 0) - { - /* A negative upper bound stands for infinity, - in which case it degenerates to a plain jump. */ - STORE_JUMP (jump, b, laststart + startoffset); - b += 3; - } - else 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 + startoffset, - 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'. */ - c = '{'; - - if (!(syntax & RE_NO_BK_BRACES)) - { - assert (p > pattern && p[-1] == '\\'); - goto normal_backslash; - } - else - 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; - - case 'c': - laststart = b; - PATFETCH (c); - BUF_PUSH_2 (categoryspec, c); - break; - - case 'C': - laststart = b; - PATFETCH (c); - BUF_PUSH_2 (notcategoryspec, c); - break; -#endif /* emacs */ - - - case 'w': - if (syntax & RE_NO_GNU_OPS) - goto normal_char; - laststart = b; - BUF_PUSH_2 (syntaxspec, Sword); - break; - - - case 'W': - if (syntax & RE_NO_GNU_OPS) - goto normal_char; - laststart = b; - BUF_PUSH_2 (notsyntaxspec, Sword); - break; - - - case '<': - if (syntax & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (wordbeg); - break; - - case '>': - if (syntax & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (wordend); - break; - - case 'b': - if (syntax & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (wordbound); - break; - - case 'B': - if (syntax & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (notwordbound); - break; - - case '`': - if (syntax & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (begbuf); - break; - - case '\'': - if (syntax & RE_NO_GNU_OPS) - goto normal_char; - BUF_PUSH (endbuf); - break; - - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - { - regnum_t reg; - - if (syntax & RE_NO_BK_REFS) - goto normal_backslash; - - reg = c - '0'; - - /* Can't back reference to a subexpression before its end. */ - if (reg > regnum || group_in_compile_stack (compile_stack, reg)) - FREE_STACK_RETURN (REG_ESUBREG); - - laststart = b; - BUF_PUSH_2 (duplicate, reg); - } - 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. */ - 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) - MAX_MULTIBYTE_LENGTH - - /* If followed by a repetition operator. */ - || (p != pend && (*p == '*' || *p == '^')) - || ((syntax & RE_BK_PLUS_QM) - ? p + 1 < pend && *p == '\\' && (p[1] == '+' || p[1] == '?') - : p != pend && (*p == '+' || *p == '?')) - || ((syntax & RE_INTERVALS) - && ((syntax & RE_NO_BK_BRACES) - ? p != pend && *p == '{' - : p + 1 < pend && p[0] == '\\' && p[1] == '{'))) - { - /* Start building a new exactn. */ - - laststart = b; - - BUF_PUSH_2 (exactn, 0); - pending_exact = b - 1; - } - - GET_BUFFER_SPACE (MAX_MULTIBYTE_LENGTH); - { - int len; - - c = TRANSLATE (c); - if (multibyte) - len = CHAR_STRING (c, b); - else - *b = c, len = 1; - b += len; - (*pending_exact) += len; - } - - break; - } /* switch (c) */ - } /* while p != pend */ - - - /* Through the pattern now. */ - - FIXUP_ALT_JUMP (); - - if (!COMPILE_STACK_EMPTY) - FREE_STACK_RETURN (REG_EPAREN); - - /* If we don't want backtracking, force success - the first time we reach the end of the compiled pattern. */ - if (syntax & RE_NO_POSIX_BACKTRACKING) - BUF_PUSH (succeed); - - /* We have succeeded; set the length of the buffer. */ - bufp->used = b - bufp->buffer; - -#ifdef DEBUG - if (debug > 0) - { - re_compile_fastmap (bufp); - DEBUG_PRINT1 ("\nCompiled pattern: \n"); - print_compiled_pattern (bufp); - } - debug--; -#endif /* DEBUG */ - -#ifndef MATCH_MAY_ALLOCATE - /* Initialize the failure stack to the largest possible stack. This - isn't necessary unless we're trying to avoid calling alloca in - the search and match routines. */ - { - int num_regs = bufp->re_nsub + 1; - - if (fail_stack.size < re_max_failures * TYPICAL_FAILURE_SIZE) - { - fail_stack.size = re_max_failures * TYPICAL_FAILURE_SIZE; - - if (! fail_stack.stack) - fail_stack.stack - = (fail_stack_elt_t *) malloc (fail_stack.size - * sizeof (fail_stack_elt_t)); - else - fail_stack.stack - = (fail_stack_elt_t *) realloc (fail_stack.stack, - (fail_stack.size - * sizeof (fail_stack_elt_t))); - } - - regex_grow_registers (num_regs); - } -#endif /* not MATCH_MAY_ALLOCATE */ - - FREE_STACK_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) - re_char *pattern, *p; - reg_syntax_t syntax; -{ - re_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)) - /* After a shy subexpression? */ - || ((syntax & RE_SHY_GROUPS) && prev - 2 >= pattern - && prev[-1] == '?' && prev[-2] == '(' - && (syntax & RE_NO_BK_PARENS - || (prev - 3 >= pattern && prev[-3] == '\\'))); -} - - -/* 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) - re_char *p, *pend; - reg_syntax_t syntax; -{ - re_char *next = p; - boolean next_backslash = *next == '\\'; - re_char *next_next = p + 1 < pend ? p + 1 : 0; - - 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; -} - -/* analyse_first. - If fastmap is non-NULL, go through the pattern and fill fastmap - with all the possible leading chars. If fastmap is NULL, don't - bother filling it up (obviously) and only return whether the - pattern could potentially match the empty string. - - Return 1 if p..pend might match the empty string. - Return 0 if p..pend matches at least one char. - Return -1 if fastmap was not updated accurately. */ - -static int -analyse_first (p, pend, fastmap, multibyte) - re_char *p, *pend; - char *fastmap; - const int multibyte; -{ - int j, k; - boolean not; - - /* If all elements for base leading-codes in fastmap is set, this - flag is set true. */ - boolean match_any_multibyte_characters = false; - - assert (p); - - /* The loop below works as follows: - - It has a working-list kept in the PATTERN_STACK and which basically - starts by only containing a pointer to the first operation. - - If the opcode we're looking at is a match against some set of - chars, then we add those chars to the fastmap and go on to the - next work element from the worklist (done via `break'). - - If the opcode is a control operator on the other hand, we either - ignore it (if it's meaningless at this point, such as `start_memory') - or execute it (if it's a jump). If the jump has several destinations - (i.e. `on_failure_jump'), then we push the other destination onto the - worklist. - We guarantee termination by ignoring backward jumps (more or less), - so that `p' is monotonically increasing. More to the point, we - never set `p' (or push) anything `<= p1'. */ - - while (p < pend) - { - /* `p1' is used as a marker of how far back a `on_failure_jump' - can go without being ignored. It is normally equal to `p' - (which prevents any backward `on_failure_jump') except right - after a plain `jump', to allow patterns such as: - 0: jump 10 - 3..9: <body> - 10: on_failure_jump 3 - as used for the *? operator. */ - re_char *p1 = p; - - switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) - { - case succeed: - return 1; - continue; - - case duplicate: - /* If the first character has to match a backreference, that means - that the group was empty (since it already matched). Since this - is the only case that interests us here, we can assume that the - backreference must match the empty string. */ - p++; - continue; - - - /* Following are the cases which match a character. These end - with `break'. */ - - case exactn: - if (fastmap) - { - int c = RE_STRING_CHAR (p + 1, pend - p); - - if (SINGLE_BYTE_CHAR_P (c)) - fastmap[c] = 1; - else - fastmap[p[1]] = 1; - } - break; - - - case anychar: - /* We could put all the chars except for \n (and maybe \0) - but we don't bother since it is generally not worth it. */ - if (!fastmap) break; - return -1; - - - case charset_not: - /* Chars beyond end of bitmap are possible matches. - All the single-byte codes can occur in multibyte buffers. - So any that are not listed in the charset - are possible matches, even in multibyte buffers. */ - if (!fastmap) break; - for (j = CHARSET_BITMAP_SIZE (&p[-1]) * BYTEWIDTH; - j < (1 << BYTEWIDTH); j++) - fastmap[j] = 1; - /* Fallthrough */ - case charset: - if (!fastmap) break; - not = (re_opcode_t) *(p - 1) == charset_not; - for (j = CHARSET_BITMAP_SIZE (&p[-1]) * BYTEWIDTH - 1, p++; - j >= 0; j--) - if (!!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) ^ not) - fastmap[j] = 1; - - if ((not && multibyte) - /* Any character set can possibly contain a character - which doesn't match the specified set of characters. */ - || (CHARSET_RANGE_TABLE_EXISTS_P (&p[-2]) - && CHARSET_RANGE_TABLE_BITS (&p[-2]) != 0)) - /* If we can match a character class, we can match - any character set. */ - { - set_fastmap_for_multibyte_characters: - if (match_any_multibyte_characters == false) - { - for (j = 0x80; j < 0xA0; j++) /* XXX */ - if (BASE_LEADING_CODE_P (j)) - fastmap[j] = 1; - match_any_multibyte_characters = true; - } - } - - else if (!not && CHARSET_RANGE_TABLE_EXISTS_P (&p[-2]) - && match_any_multibyte_characters == false) - { - /* Set fastmap[I] 1 where I is a base leading code of each - multibyte character in the range table. */ - int c, count; - - /* Make P points the range table. `+ 2' is to skip flag - bits for a character class. */ - p += CHARSET_BITMAP_SIZE (&p[-2]) + 2; - - /* Extract the number of ranges in range table into COUNT. */ - EXTRACT_NUMBER_AND_INCR (count, p); - for (; count > 0; count--, p += 2 * 3) /* XXX */ - { - /* Extract the start of each range. */ - EXTRACT_CHARACTER (c, p); - j = CHAR_CHARSET (c); - fastmap[CHARSET_LEADING_CODE_BASE (j)] = 1; - } - } - break; - - case syntaxspec: - case notsyntaxspec: - if (!fastmap) break; -#ifndef emacs - not = (re_opcode_t)p[-1] == notsyntaxspec; - k = *p++; - for (j = 0; j < (1 << BYTEWIDTH); j++) - if ((SYNTAX (j) == (enum syntaxcode) k) ^ not) - fastmap[j] = 1; - break; -#else /* emacs */ - /* This match depends on text properties. These end with - aborting optimizations. */ - return -1; - - case categoryspec: - case notcategoryspec: - if (!fastmap) break; - not = (re_opcode_t)p[-1] == notcategoryspec; - k = *p++; - for (j = 0; j < (1 << BYTEWIDTH); j++) - if ((CHAR_HAS_CATEGORY (j, k)) ^ not) - fastmap[j] = 1; - - if (multibyte) - /* Any character set can possibly contain a character - whose category is K (or not). */ - goto set_fastmap_for_multibyte_characters; - break; - - /* All cases after this match the empty string. These end with - `continue'. */ - - case before_dot: - case at_dot: - case after_dot: -#endif /* !emacs */ - case no_op: - case begline: - case endline: - case begbuf: - case endbuf: - case wordbound: - case notwordbound: - case wordbeg: - case wordend: - continue; - - - case jump: - EXTRACT_NUMBER_AND_INCR (j, p); - if (j < 0) - /* Backward jumps can only go back to code that we've already - visited. `re_compile' should make sure this is true. */ - break; - p += j; - switch (SWITCH_ENUM_CAST ((re_opcode_t) *p)) - { - case on_failure_jump: - case on_failure_keep_string_jump: - case on_failure_jump_loop: - case on_failure_jump_nastyloop: - case on_failure_jump_smart: - p++; - break; - default: - continue; - }; - /* Keep `p1' to allow the `on_failure_jump' we are jumping to - to jump back to "just after here". */ - /* Fallthrough */ - - case on_failure_jump: - case on_failure_keep_string_jump: - case on_failure_jump_nastyloop: - case on_failure_jump_loop: - case on_failure_jump_smart: - EXTRACT_NUMBER_AND_INCR (j, p); - if (p + j <= p1) - ; /* Backward jump to be ignored. */ - else - { /* We have to look down both arms. - We first go down the "straight" path so as to minimize - stack usage when going through alternatives. */ - int r = analyse_first (p, pend, fastmap, multibyte); - if (r) return r; - p += j; - } - continue; - - - case jump_n: - /* This code simply does not properly handle forward jump_n. */ - DEBUG_STATEMENT (EXTRACT_NUMBER (j, p); assert (j < 0)); - p += 4; - /* jump_n can either jump or fall through. The (backward) jump - case has already been handled, so we only need to look at the - fallthrough case. */ - continue; - - case succeed_n: - /* If N == 0, it should be an on_failure_jump_loop instead. */ - DEBUG_STATEMENT (EXTRACT_NUMBER (j, p + 2); assert (j > 0)); - p += 4; - /* We only care about one iteration of the loop, so we don't - need to consider the case where this behaves like an - on_failure_jump. */ - continue; - - - case set_number_at: - p += 4; - continue; - - - case start_memory: - case stop_memory: - p += 1; - 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. */ - return 0; - } /* while p */ - - /* We reached the end without matching anything. */ - return 1; - -} /* analyse_first */ - -/* 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. - - Character codes above (1 << BYTEWIDTH) are not represented in the - fastmap, but the leading codes are represented. Thus, the fastmap - indicates which character sets could start a match. - - 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; -{ - char *fastmap = bufp->fastmap; - int analysis; - - assert (fastmap && bufp->buffer); - - bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ - bufp->fastmap_accurate = 1; /* It will be when we're done. */ - - analysis = analyse_first (bufp->buffer, bufp->buffer + bufp->used, - fastmap, RE_MULTIBYTE_P (bufp)); - bufp->can_be_null = (analysis != 0); - 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; - } -} -WEAK_ALIAS (__re_set_registers, re_set_registers) - -/* 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); -} -WEAK_ALIAS (__re_search, re_search) - -/* Head address of virtual concatenation of string. */ -#define HEAD_ADDR_VSTRING(P) \ - (((P) >= size1 ? string2 : string1)) - -/* End address of virtual concatenation of string. */ -#define STOP_ADDR_VSTRING(P) \ - (((P) >= size1 ? string2 + size2 : string1 + size1)) - -/* Address of POS in the concatenation of virtual string. */ -#define POS_ADDR_VSTRING(POS) \ - (((POS) >= size1 ? string2 - size1 : string1) + (POS)) - -/* 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, str1, size1, str2, size2, startpos, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *str1, *str2; - int size1, size2; - int startpos; - int range; - struct re_registers *regs; - int stop; -{ - int val; - re_char *string1 = (re_char*) str1; - re_char *string2 = (re_char*) str2; - register char *fastmap = bufp->fastmap; - register RE_TRANSLATE_TYPE translate = bufp->translate; - int total_size = size1 + size2; - int endpos = startpos + range; - boolean anchored_start; - - /* Nonzero if we have to concern multibyte character. */ - const boolean multibyte = RE_MULTIBYTE_P (bufp); - - /* 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. - Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ - if (endpos < 0) - range = 0 - 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 anchored at beginning of buffer. */ - if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) - { - if (startpos > 0) - return -1; - else - range = 0; - } - -#ifdef emacs - /* In a forward search for something that starts with \=. - don't keep searching past point. */ - if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) - { - range = PT_BYTE - BEGV_BYTE - startpos; - if (range < 0) - return -1; - } -#endif /* emacs */ - - /* Update the fastmap now if not correct already. */ - if (fastmap && !bufp->fastmap_accurate) - re_compile_fastmap (bufp); - - /* See whether the pattern is anchored. */ - anchored_start = (bufp->buffer[0] == begline); - -#ifdef emacs - gl_state.object = re_match_object; - { - int charpos = SYNTAX_TABLE_BYTE_TO_CHAR (POS_AS_IN_BUFFER (startpos)); - - SETUP_SYNTAX_TABLE_FOR_OBJECT (re_match_object, charpos, 1); - } -#endif - - /* Loop through the string, looking for a place to start matching. */ - for (;;) - { - /* If the pattern is anchored, - skip quickly past places we cannot match. - We don't bother to treat startpos == 0 specially - because that case doesn't repeat. */ - if (anchored_start && startpos > 0) - { - if (! ((startpos <= size1 ? string1[startpos - 1] - : string2[startpos - size1 - 1]) - == '\n')) - goto advance; - } - - /* 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) - { - register re_char *d; - register re_wchar_t buf_ch; - - d = POS_ADDR_VSTRING (startpos); - - if (range > 0) /* Searching forwards. */ - { - register int lim = 0; - int irange = range; - - if (startpos < size1 && startpos + range >= size1) - lim = range - (size1 - startpos); - - /* Written out as an if-else to avoid testing `translate' - inside the loop. */ - if (RE_TRANSLATE_P (translate)) - { - if (multibyte) - while (range > lim) - { - int buf_charlen; - - buf_ch = STRING_CHAR_AND_LENGTH (d, range - lim, - buf_charlen); - - buf_ch = RE_TRANSLATE (translate, buf_ch); - if (buf_ch >= 0400 - || fastmap[buf_ch]) - break; - - range -= buf_charlen; - d += buf_charlen; - } - else - while (range > lim - && !fastmap[RE_TRANSLATE (translate, *d)]) - { - d++; - range--; - } - } - else - while (range > lim && !fastmap[*d]) - { - d++; - range--; - } - - startpos += irange - range; - } - else /* Searching backwards. */ - { - int room = (startpos >= size1 - ? size2 + size1 - startpos - : size1 - startpos); - buf_ch = RE_STRING_CHAR (d, room); - buf_ch = TRANSLATE (buf_ch); - - if (! (buf_ch >= 0400 - || fastmap[buf_ch])) - 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_internal (bufp, string1, size1, string2, size2, - startpos, regs, stop); -#ifndef REGEX_MALLOC -# ifdef C_ALLOCA - alloca (0); -# endif -#endif - - if (val >= 0) - return startpos; - - if (val == -2) - return -2; - - advance: - if (!range) - break; - else if (range > 0) - { - /* Update STARTPOS to the next character boundary. */ - if (multibyte) - { - re_char *p = POS_ADDR_VSTRING (startpos); - re_char *pend = STOP_ADDR_VSTRING (startpos); - int len = MULTIBYTE_FORM_LENGTH (p, pend - p); - - range -= len; - if (range < 0) - break; - startpos += len; - } - else - { - range--; - startpos++; - } - } - else - { - range++; - startpos--; - - /* Update STARTPOS to the previous character boundary. */ - if (multibyte) - { - re_char *p = POS_ADDR_VSTRING (startpos) + 1; - re_char *p0 = p; - re_char *phead = HEAD_ADDR_VSTRING (startpos); - - /* Find the head of multibyte form. */ - PREV_CHAR_BOUNDARY (p, phead); - range += p0 - 1 - p; - if (range > 0) - break; - - startpos -= p0 - 1 - p; - } - } - } - return -1; -} /* re_search_2 */ -WEAK_ALIAS (__re_search_2, re_search_2) - -/* Declarations and macros for re_match_2. */ - -static int bcmp_translate _RE_ARGS((re_char *s1, re_char *s2, - register int len, - RE_TRANSLATE_TYPE translate, - const int multibyte)); - -/* 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) \ - ? ((regoff_t) ((ptr) - string1)) \ - : ((regoff_t) ((ptr) - string2 + size1))) - -/* Call before fetching a character with *d. This switches over to - string2 if necessary. - Check re_match_2_internal for a discussion of why end_match_2 might - not be within string2 (but be equal to end_match_1 instead). */ -#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; \ - } - -/* Call before fetching a char with *d if you already checked other limits. - This is meant for use in lookahead operations like wordend, etc.. - where we might need to look at parts of the string that might be - outside of the LIMITs (i.e past `stop'). */ -#define PREFETCH_NOLIMIT() \ - if (d == end1) \ - { \ - 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) - -/* Disabled due to a compiler bug -- see comment at case wordbound */ - -/* The comment at case wordbound is following one, but we don't use - AT_WORD_BOUNDARY anymore to support multibyte form. - - The DEC Alpha C compiler 3.x generates incorrect code for the - test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of - AT_WORD_BOUNDARY, so this code is disabled. Expanding the - macro and introducing temporary variables works around the bug. */ - -#if 0 -/* 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)) -#endif - -/* Free everything we malloc. */ -#ifdef MATCH_MAY_ALLOCATE -# define FREE_VAR(var) if (var) { REGEX_FREE (var); var = NULL; } else -# define FREE_VARIABLES() \ - do { \ - REGEX_FREE_STACK (fail_stack.stack); \ - FREE_VAR (regstart); \ - FREE_VAR (regend); \ - FREE_VAR (best_regstart); \ - FREE_VAR (best_regend); \ - } while (0) -#else -# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ -#endif /* not MATCH_MAY_ALLOCATE */ - - -/* Optimization routines. */ - -/* If the operation is a match against one or more chars, - return a pointer to the next operation, else return NULL. */ -static re_char * -skip_one_char (p) - re_char *p; -{ - switch (SWITCH_ENUM_CAST (*p++)) - { - case anychar: - break; - - case exactn: - p += *p + 1; - break; - - case charset_not: - case charset: - if (CHARSET_RANGE_TABLE_EXISTS_P (p - 1)) - { - int mcnt; - p = CHARSET_RANGE_TABLE (p - 1); - EXTRACT_NUMBER_AND_INCR (mcnt, p); - p = CHARSET_RANGE_TABLE_END (p, mcnt); - } - else - p += 1 + CHARSET_BITMAP_SIZE (p - 1); - break; - - case syntaxspec: - case notsyntaxspec: -#ifdef emacs - case categoryspec: - case notcategoryspec: -#endif /* emacs */ - p++; - break; - - default: - p = NULL; - } - return p; -} - - -/* Jump over non-matching operations. */ -static re_char * -skip_noops (p, pend) - re_char *p, *pend; -{ - int mcnt; - while (p < pend) - { - switch (SWITCH_ENUM_CAST ((re_opcode_t) *p)) - { - case start_memory: - case stop_memory: - p += 2; break; - case no_op: - p += 1; break; - case jump: - p += 1; - EXTRACT_NUMBER_AND_INCR (mcnt, p); - p += mcnt; - break; - default: - return p; - } - } - assert (p == pend); - return p; -} - -/* Non-zero if "p1 matches something" implies "p2 fails". */ -static int -mutually_exclusive_p (bufp, p1, p2) - struct re_pattern_buffer *bufp; - re_char *p1, *p2; -{ - re_opcode_t op2; - const boolean multibyte = RE_MULTIBYTE_P (bufp); - unsigned char *pend = bufp->buffer + bufp->used; - - assert (p1 >= bufp->buffer && p1 < pend - && p2 >= bufp->buffer && p2 <= pend); - - /* Skip over open/close-group commands. - If what follows this loop is a ...+ construct, - look at what begins its body, since we will have to - match at least one of that. */ - p2 = skip_noops (p2, pend); - /* The same skip can be done for p1, except that this function - is only used in the case where p1 is a simple match operator. */ - /* p1 = skip_noops (p1, pend); */ - - assert (p1 >= bufp->buffer && p1 < pend - && p2 >= bufp->buffer && p2 <= pend); - - op2 = p2 == pend ? succeed : *p2; - - switch (SWITCH_ENUM_CAST (op2)) - { - case succeed: - case endbuf: - /* If we're at the end of the pattern, we can change. */ - if (skip_one_char (p1)) - { - DEBUG_PRINT1 (" End of pattern: fast loop.\n"); - return 1; - } - break; - - case endline: - case exactn: - { - register re_wchar_t c - = (re_opcode_t) *p2 == endline ? '\n' - : RE_STRING_CHAR (p2 + 2, pend - p2 - 2); - - if ((re_opcode_t) *p1 == exactn) - { - if (c != RE_STRING_CHAR (p1 + 2, pend - p1 - 2)) - { - DEBUG_PRINT3 (" '%c' != '%c' => fast loop.\n", c, p1[2]); - return 1; - } - } - - else if ((re_opcode_t) *p1 == charset - || (re_opcode_t) *p1 == charset_not) - { - int not = (re_opcode_t) *p1 == charset_not; - - /* Test if C is listed in charset (or charset_not) - at `p1'. */ - if (SINGLE_BYTE_CHAR_P (c)) - { - if (c < CHARSET_BITMAP_SIZE (p1) * BYTEWIDTH - && p1[2 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; - } - else if (CHARSET_RANGE_TABLE_EXISTS_P (p1)) - CHARSET_LOOKUP_RANGE_TABLE (not, c, p1); - - /* `not' is equal to 1 if c would match, which means - that we can't change to pop_failure_jump. */ - if (!not) - { - DEBUG_PRINT1 (" No match => fast loop.\n"); - return 1; - } - } - else if ((re_opcode_t) *p1 == anychar - && c == '\n') - { - DEBUG_PRINT1 (" . != \\n => fast loop.\n"); - return 1; - } - } - break; - - case charset: - { - if ((re_opcode_t) *p1 == exactn) - /* Reuse the code above. */ - return mutually_exclusive_p (bufp, p2, p1); - - /* It is hard to list up all the character in charset - P2 if it includes multibyte character. Give up in - such case. */ - else if (!multibyte || !CHARSET_RANGE_TABLE_EXISTS_P (p2)) - { - /* Now, we are sure that P2 has no range table. - So, for the size of bitmap in P2, `p2[1]' is - enough. But P1 may have range table, so the - size of bitmap table of P1 is extracted by - using macro `CHARSET_BITMAP_SIZE'. - - Since we know that all the character listed in - P2 is ASCII, it is enough to test only bitmap - table of P1. */ - - if ((re_opcode_t) *p1 == charset) - { - int idx; - /* We win if the charset inside the loop - has no overlap with the one after the loop. */ - for (idx = 0; - (idx < (int) p2[1] - && idx < CHARSET_BITMAP_SIZE (p1)); - idx++) - if ((p2[2 + idx] & p1[2 + idx]) != 0) - break; - - if (idx == p2[1] - || idx == CHARSET_BITMAP_SIZE (p1)) - { - DEBUG_PRINT1 (" No match => fast loop.\n"); - return 1; - } - } - else if ((re_opcode_t) *p1 == charset_not) - { - int idx; - /* We win if the charset_not inside the loop lists - every character listed in the charset after. */ - for (idx = 0; idx < (int) p2[1]; idx++) - if (! (p2[2 + idx] == 0 - || (idx < CHARSET_BITMAP_SIZE (p1) - && ((p2[2 + idx] & ~ p1[2 + idx]) == 0)))) - break; - - if (idx == p2[1]) - { - DEBUG_PRINT1 (" No match => fast loop.\n"); - return 1; - } - } - } - } - break; - - case charset_not: - switch (SWITCH_ENUM_CAST (*p1)) - { - case exactn: - case charset: - /* Reuse the code above. */ - return mutually_exclusive_p (bufp, p2, p1); - case charset_not: - /* When we have two charset_not, it's very unlikely that - they don't overlap. The union of the two sets of excluded - chars should cover all possible chars, which, as a matter of - fact, is virtually impossible in multibyte buffers. */ - break; - } - break; - - case wordend: - case notsyntaxspec: - return ((re_opcode_t) *p1 == syntaxspec - && p1[1] == (op2 == wordend ? Sword : p2[1])); - - case wordbeg: - case syntaxspec: - return ((re_opcode_t) *p1 == notsyntaxspec - && p1[1] == (op2 == wordend ? Sword : p2[1])); - - case wordbound: - return (((re_opcode_t) *p1 == notsyntaxspec - || (re_opcode_t) *p1 == syntaxspec) - && p1[1] == Sword); - -#ifdef emacs - case categoryspec: - return ((re_opcode_t) *p1 == notcategoryspec && p1[1] == p2[1]); - case notcategoryspec: - return ((re_opcode_t) *p1 == categoryspec && p1[1] == p2[1]); -#endif /* emacs */ - - default: - ; - } - - /* Safe default. */ - return 0; -} - - -/* 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; -{ - int result = re_match_2_internal (bufp, NULL, 0, (re_char*) string, size, - pos, regs, size); -# if defined C_ALLOCA && !defined REGEX_MALLOC - alloca (0); -# endif - return result; -} -WEAK_ALIAS (__re_match, re_match) -#endif /* not emacs */ - -#ifdef emacs -/* In Emacs, this is the string or buffer in which we - are matching. It is used for looking up syntax properties. */ -Lisp_Object re_match_object; -#endif - -/* 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; -{ - int result; - -#ifdef emacs - int charpos; - gl_state.object = re_match_object; - charpos = SYNTAX_TABLE_BYTE_TO_CHAR (POS_AS_IN_BUFFER (pos)); - SETUP_SYNTAX_TABLE_FOR_OBJECT (re_match_object, charpos, 1); -#endif - - result = re_match_2_internal (bufp, (re_char*) string1, size1, - (re_char*) string2, size2, - pos, regs, stop); -#if defined C_ALLOCA && !defined REGEX_MALLOC - alloca (0); -#endif - return result; -} -WEAK_ALIAS (__re_match_2, re_match_2) - -/* This is a separate function so that we can force an alloca cleanup - afterwards. */ -static int -re_match_2_internal (bufp, string1, size1, string2, size2, pos, regs, stop) - struct re_pattern_buffer *bufp; - re_char *string1, *string2; - int size1, size2; - int pos; - struct re_registers *regs; - int stop; -{ - /* General temporaries. */ - int mcnt; - size_t reg; - boolean not; - - /* Just past the end of the corresponding string. */ - re_char *end1, *end2; - - /* Pointers into string1 and string2, just past the last characters in - each to consider matching. */ - re_char *end_match_1, *end_match_2; - - /* Where we are in the data, and the end of the current string. */ - re_char *d, *dend; - - /* Used sometimes to remember where we were before starting matching - an operator so that we can go back in case of failure. This "atomic" - behavior of matching opcodes is indispensable to the correctness - of the on_failure_keep_string_jump optimization. */ - re_char *dfail; - - /* Where we are in the pattern, and the end of the pattern. */ - re_char *p = bufp->buffer; - re_char *pend = p + bufp->used; - - /* We use this to map every character in the string. */ - RE_TRANSLATE_TYPE translate = bufp->translate; - - /* Nonzero if we have to concern multibyte character. */ - const boolean multibyte = RE_MULTIBYTE_P (bufp); - - /* Failure point stack. Each place that can handle a failure further - down the line pushes a failure point on this stack. It consists of - regstart, and regend 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. */ -#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ - fail_stack_type fail_stack; -#endif -#ifdef DEBUG - unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; -#endif - -#if defined REL_ALLOC && defined REGEX_MALLOC - /* This holds the pointer to the failure stack, when - it is allocated relocatably. */ - fail_stack_elt_t *failure_stack_ptr; -#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. */ - size_t num_regs = bufp->re_nsub + 1; - - /* 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.) */ -#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - re_char **regstart, **regend; -#endif - - /* 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; -#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ - re_char **best_regstart, **best_regend; -#endif - - /* 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. */ - re_char *match_end = NULL; - -#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 (); - -#ifdef MATCH_MAY_ALLOCATE - /* 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, re_char *); - regend = REGEX_TALLOC (num_regs, re_char *); - best_regstart = REGEX_TALLOC (num_regs, re_char *); - best_regend = REGEX_TALLOC (num_regs, re_char *); - - if (!(regstart && regend && best_regstart && best_regend)) - { - FREE_VARIABLES (); - return -2; - } - } - else - { - /* We must initialize all our variables to NULL, so that - `FREE_VARIABLES' doesn't try to free them. */ - regstart = regend = best_regstart = best_regend = NULL; - } -#endif /* MATCH_MAY_ALLOCATE */ - - /* 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 (reg = 1; reg < num_regs; reg++) - regstart[reg] = regend[reg] = NULL; - - /* 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; - - /* `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 (pos >= size1) - { - /* Only match within string2. */ - d = string2 + pos - size1; - dend = end_match_2 = string2 + stop - size1; - end_match_1 = end1; /* Just to give it a value. */ - } - else - { - if (stop < size1) - { - /* Only match within string1. */ - end_match_1 = string1 + stop; - /* BEWARE! - When we reach end_match_1, PREFETCH normally switches to string2. - But in the present case, this means that just doing a PREFETCH - makes us jump from `stop' to `gap' within the string. - What we really want here is for the search to stop as - soon as we hit end_match_1. That's why we set end_match_2 - to end_match_1 (since PREFETCH fails as soon as we hit - end_match_2). */ - end_match_2 = end_match_1; - } - else - { /* It's important to use this code when stop == size so that - moving `d' from end1 to string2 will not prevent the d == dend - check from catching the end of string. */ - end_match_1 = end1; - end_match_2 = string2 + stop - size1; - } - d = string1 + pos; - dend = end_match_1; - } - - 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 ("\n%p: ", 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) - { - /* 1 if this match ends in the same string (string1 or string2) - as the best previous match. */ - boolean same_str_p = (FIRST_STRING_P (match_end) - == FIRST_STRING_P (d)); - /* 1 if this match is the best seen so far. */ - boolean best_match_p; - - /* AIX compiler got confused when this was combined - with the previous declaration. */ - if (same_str_p) - best_match_p = d > match_end; - else - best_match_p = !FIRST_STRING_P (d); - - DEBUG_PRINT1 ("backtracking.\n"); - - if (!FAIL_STACK_EMPTY ()) - { /* More failure points to try. */ - - /* If exceeds best match so far, save it. */ - if (!best_regs_set || best_match_p) - { - best_regs_set = true; - match_end = d; - - DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); - - for (reg = 1; reg < num_regs; reg++) - { - best_regstart[reg] = regstart[reg]; - best_regend[reg] = regend[reg]; - } - } - goto fail; - } - - /* If no failure points, don't restore garbage. And if - last match is real best match, don't restore second - best one. */ - else if (best_regs_set && !best_match_p) - { - 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 (reg = 1; reg < num_regs; reg++) - { - regstart[reg] = best_regstart[reg]; - regend[reg] = best_regend[reg]; - } - } - } /* d != end_match_2 */ - - succeed_label: - 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) - { - FREE_VARIABLES (); - 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) - { - FREE_VARIABLES (); - return -2; - } - } - } - else - { - /* These braces fend off a "empty body in an else-statement" - warning under GCC when assert expands to nothing. */ - 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] = POINTER_TO_OFFSET (d); - } - - /* Go through the first `min (num_regs, regs->num_regs)' - registers, since that is all we initialized. */ - for (reg = 1; reg < MIN (num_regs, regs->num_regs); reg++) - { - if (REG_UNSET (regstart[reg]) || REG_UNSET (regend[reg])) - regs->start[reg] = regs->end[reg] = -1; - else - { - regs->start[reg] - = (regoff_t) POINTER_TO_OFFSET (regstart[reg]); - regs->end[reg] - = (regoff_t) POINTER_TO_OFFSET (regend[reg]); - } - } - - /* 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 (reg = num_regs; reg < regs->num_regs; reg++) - regs->start[reg] = regs->end[reg] = -1; - } /* regs && !bufp->no_sub */ - - 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 = POINTER_TO_OFFSET (d) - pos; - - DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); - - FREE_VARIABLES (); - return mcnt; - } - - /* Otherwise match next pattern command. */ - switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) - { - /* 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; - - case succeed: - DEBUG_PRINT1 ("EXECUTING succeed.\n"); - goto succeed_label; - - /* 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); - - /* Remember the start point to rollback upon failure. */ - dfail = d; - - /* This is written out as an if-else so we don't waste time - testing `translate' inside the loop. */ - if (RE_TRANSLATE_P (translate)) - { - if (multibyte) - do - { - int pat_charlen, buf_charlen; - unsigned int pat_ch, buf_ch; - - PREFETCH (); - pat_ch = STRING_CHAR_AND_LENGTH (p, pend - p, pat_charlen); - buf_ch = STRING_CHAR_AND_LENGTH (d, dend - d, buf_charlen); - - if (RE_TRANSLATE (translate, buf_ch) - != pat_ch) - { - d = dfail; - goto fail; - } - - p += pat_charlen; - d += buf_charlen; - mcnt -= pat_charlen; - } - while (mcnt > 0); - else - do - { - PREFETCH (); - if (RE_TRANSLATE (translate, *d) != *p++) - { - d = dfail; - goto fail; - } - d++; - } - while (--mcnt); - } - else - { - do - { - PREFETCH (); - if (*d++ != *p++) - { - d = dfail; - goto fail; - } - } - while (--mcnt); - } - break; - - - /* Match any character except possibly a newline or a null. */ - case anychar: - { - int buf_charlen; - re_wchar_t buf_ch; - - DEBUG_PRINT1 ("EXECUTING anychar.\n"); - - PREFETCH (); - buf_ch = RE_STRING_CHAR_AND_LENGTH (d, dend - d, buf_charlen); - buf_ch = TRANSLATE (buf_ch); - - if ((!(bufp->syntax & RE_DOT_NEWLINE) - && buf_ch == '\n') - || ((bufp->syntax & RE_DOT_NOT_NULL) - && buf_ch == '\000')) - goto fail; - - DEBUG_PRINT2 (" Matched `%d'.\n", *d); - d += buf_charlen; - } - break; - - - case charset: - case charset_not: - { - register unsigned int c; - boolean not = (re_opcode_t) *(p - 1) == charset_not; - int len; - - /* Start of actual range_table, or end of bitmap if there is no - range table. */ - re_char *range_table; - - /* Nonzero if there is a range table. */ - int range_table_exists; - - /* Number of ranges of range table. This is not included - in the initial byte-length of the command. */ - int count = 0; - - DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); - - range_table_exists = CHARSET_RANGE_TABLE_EXISTS_P (&p[-1]); - - if (range_table_exists) - { - range_table = CHARSET_RANGE_TABLE (&p[-1]); /* Past the bitmap. */ - EXTRACT_NUMBER_AND_INCR (count, range_table); - } - - PREFETCH (); - c = RE_STRING_CHAR_AND_LENGTH (d, dend - d, len); - c = TRANSLATE (c); /* The character to match. */ - - if (SINGLE_BYTE_CHAR_P (c)) - { /* Lookup bitmap. */ - /* Cast to `unsigned' instead of `unsigned char' in - case the bit list is a full 32 bytes long. */ - if (c < (unsigned) (CHARSET_BITMAP_SIZE (&p[-1]) * BYTEWIDTH) - && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; - } -#ifdef emacs - else if (range_table_exists) - { - int class_bits = CHARSET_RANGE_TABLE_BITS (&p[-1]); - - if ( (class_bits & BIT_LOWER && ISLOWER (c)) - | (class_bits & BIT_MULTIBYTE) - | (class_bits & BIT_PUNCT && ISPUNCT (c)) - | (class_bits & BIT_SPACE && ISSPACE (c)) - | (class_bits & BIT_UPPER && ISUPPER (c)) - | (class_bits & BIT_WORD && ISWORD (c))) - not = !not; - else - CHARSET_LOOKUP_RANGE_TABLE_RAW (not, c, range_table, count); - } -#endif /* emacs */ - - if (range_table_exists) - p = CHARSET_RANGE_TABLE_END (range_table, count); - else - p += CHARSET_BITMAP_SIZE (&p[-1]) + 1; - - if (!not) goto fail; - - d += len; - break; - } - - - /* The beginning of a group is represented by start_memory. - The argument is the register number. The text - matched within the group is recorded (in the internal - registers data structure) under the register number. */ - case start_memory: - DEBUG_PRINT2 ("EXECUTING start_memory %d:\n", *p); - - /* In case we need to undo this operation (via backtracking). */ - PUSH_FAILURE_REG ((unsigned int)*p); - - regstart[*p] = d; - regend[*p] = NULL; /* probably unnecessary. -sm */ - DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); - - /* Move past the register number and inner group count. */ - p += 1; - break; - - - /* The stop_memory opcode represents the end of a group. Its - argument is the same as start_memory's: the register number. */ - case stop_memory: - DEBUG_PRINT2 ("EXECUTING stop_memory %d:\n", *p); - - assert (!REG_UNSET (regstart[*p])); - /* Strictly speaking, there should be code such as: - - assert (REG_UNSET (regend[*p])); - PUSH_FAILURE_REGSTOP ((unsigned int)*p); - - But the only info to be pushed is regend[*p] and it is known to - be UNSET, so there really isn't anything to push. - Not pushing anything, on the other hand deprives us from the - guarantee that regend[*p] is UNSET since undoing this operation - will not reset its value properly. This is not important since - the value will only be read on the next start_memory or at - the very end and both events can only happen if this stop_memory - is *not* undone. */ - - regend[*p] = d; - DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); - - /* Move past the register number and the inner group count. */ - p += 1; - 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 re_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]; - - /* Remember the start point to rollback upon failure. */ - dfail = d; - - /* 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 (RE_TRANSLATE_P (translate) - ? bcmp_translate (d, d2, mcnt, translate, multibyte) - : memcmp (d, d2, mcnt)) - { - d = dfail; - 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 after newlines. */ - case begline: - DEBUG_PRINT1 ("EXECUTING begline.\n"); - - if (AT_STRINGS_BEG (d)) - { - if (!bufp->not_bol) break; - } - else - { - unsigned char c; - GET_CHAR_BEFORE_2 (c, d, string1, end1, string2, end2); - if (c == '\n') - 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; - } - else - { - PREFETCH_NOLIMIT (); - if (*d == '\n') - 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: - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 ("EXECUTING on_failure_keep_string_jump %d (to %p):\n", - mcnt, p + mcnt); - - PUSH_FAILURE_POINT (p - 3, NULL); - break; - - /* A nasty loop is introduced by the non-greedy *? and +?. - With such loops, the stack only ever contains one failure point - at a time, so that a plain on_failure_jump_loop kind of - cycle detection cannot work. Worse yet, such a detection - can not only fail to detect a cycle, but it can also wrongly - detect a cycle (between different instantiations of the same - loop). - So the method used for those nasty loops is a little different: - We use a special cycle-detection-stack-frame which is pushed - when the on_failure_jump_nastyloop failure-point is *popped*. - This special frame thus marks the beginning of one iteration - through the loop and we can hence easily check right here - whether something matched between the beginning and the end of - the loop. */ - case on_failure_jump_nastyloop: - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 ("EXECUTING on_failure_jump_nastyloop %d (to %p):\n", - mcnt, p + mcnt); - - assert ((re_opcode_t)p[-4] == no_op); - { - int cycle = 0; - CHECK_INFINITE_LOOP (p - 4, d); - if (!cycle) - /* If there's a cycle, just continue without pushing - this failure point. The failure point is the "try again" - option, which shouldn't be tried. - We want (x?)*?y\1z to match both xxyz and xxyxz. */ - PUSH_FAILURE_POINT (p - 3, d); - } - break; - - /* Simple loop detecting on_failure_jump: just check on the - failure stack if the same spot was already hit earlier. */ - case on_failure_jump_loop: - on_failure: - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 ("EXECUTING on_failure_jump_loop %d (to %p):\n", - mcnt, p + mcnt); - { - int cycle = 0; - CHECK_INFINITE_LOOP (p - 3, d); - if (cycle) - /* If there's a cycle, get out of the loop, as if the matching - had failed. We used to just `goto fail' here, but that was - aborting the search a bit too early: we want to keep the - empty-loop-match and keep matching after the loop. - We want (x?)*y\1z to match both xxyz and xxyxz. */ - p += mcnt; - else - PUSH_FAILURE_POINT (p - 3, d); - } - 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: - IMMEDIATE_QUIT_CHECK; - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 ("EXECUTING on_failure_jump %d (to %p):\n", - mcnt, p + mcnt); - - PUSH_FAILURE_POINT (p -3, d); - break; - - /* This operation is used for greedy *. - 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 use a non-backtracking loop based on - on_failure_keep_string_jump instead of on_failure_jump. */ - case on_failure_jump_smart: - IMMEDIATE_QUIT_CHECK; - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 ("EXECUTING on_failure_jump_smart %d (to %p).\n", - mcnt, p + mcnt); - { - re_char *p1 = p; /* Next operation. */ - /* Here, we discard `const', making re_match non-reentrant. */ - unsigned char *p2 = (unsigned char*) p + mcnt; /* Jump dest. */ - unsigned char *p3 = (unsigned char*) p - 3; /* opcode location. */ - - p -= 3; /* Reset so that we will re-execute the - instruction once it's been changed. */ - - EXTRACT_NUMBER (mcnt, p2 - 2); - - /* Ensure this is a indeed the trivial kind of loop - we are expecting. */ - assert (skip_one_char (p1) == p2 - 3); - assert ((re_opcode_t) p2[-3] == jump && p2 + mcnt == p); - DEBUG_STATEMENT (debug += 2); - if (mutually_exclusive_p (bufp, p1, p2)) - { - /* Use a fast `on_failure_keep_string_jump' loop. */ - DEBUG_PRINT1 (" smart exclusive => fast loop.\n"); - *p3 = (unsigned char) on_failure_keep_string_jump; - STORE_NUMBER (p2 - 2, mcnt + 3); - } - else - { - /* Default to a safe `on_failure_jump' loop. */ - DEBUG_PRINT1 (" smart default => slow loop.\n"); - *p3 = (unsigned char) on_failure_jump; - } - DEBUG_STATEMENT (debug -= 2); - } - break; - - /* Unconditionally jump (without popping any failure points). */ - case jump: - unconditional_jump: - IMMEDIATE_QUIT_CHECK; - 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 %p).\n", p); - break; - - - /* Have to succeed matching what follows at least n times. - After that, handle like `on_failure_jump'. */ - case succeed_n: - /* Signedness doesn't matter since we only compare MCNT to 0. */ - EXTRACT_NUMBER (mcnt, p + 2); - DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); - - /* Originally, mcnt is how many times we HAVE to succeed. */ - if (mcnt != 0) - { - /* Here, we discard `const', making re_match non-reentrant. */ - unsigned char *p2 = (unsigned char*) p + 2; /* counter loc. */ - mcnt--; - p += 4; - PUSH_NUMBER (p2, mcnt); - } - else - /* The two bytes encoding mcnt == 0 are two no_op opcodes. */ - goto on_failure; - break; - - case jump_n: - /* Signedness doesn't matter since we only compare MCNT to 0. */ - EXTRACT_NUMBER (mcnt, p + 2); - DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); - - /* Originally, this is how many times we CAN jump. */ - if (mcnt != 0) - { - /* Here, we discard `const', making re_match non-reentrant. */ - unsigned char *p2 = (unsigned char*) p + 2; /* counter loc. */ - mcnt--; - PUSH_NUMBER (p2, 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: - { - unsigned char *p2; /* Location of the counter. */ - DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); - - EXTRACT_NUMBER_AND_INCR (mcnt, p); - /* Here, we discard `const', making re_match non-reentrant. */ - p2 = (unsigned char*) p + mcnt; - /* Signedness doesn't matter since we only copy MCNT's bits . */ - EXTRACT_NUMBER_AND_INCR (mcnt, p); - DEBUG_PRINT3 (" Setting %p to %d.\n", p2, mcnt); - PUSH_NUMBER (p2, mcnt); - break; - } - - case wordbound: - case notwordbound: - not = (re_opcode_t) *(p - 1) == notwordbound; - DEBUG_PRINT2 ("EXECUTING %swordbound.\n", not?"not":""); - - /* We SUCCEED (or FAIL) in one of the following cases: */ - - /* Case 1: D is at the beginning or the end of string. */ - if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) - not = !not; - else - { - /* C1 is the character before D, S1 is the syntax of C1, C2 - is the character at D, and S2 is the syntax of C2. */ - re_wchar_t c1, c2; - int s1, s2; -#ifdef emacs - int offset = PTR_TO_OFFSET (d - 1); - int charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset); - UPDATE_SYNTAX_TABLE (charpos); -#endif - GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); - s1 = SYNTAX (c1); -#ifdef emacs - UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1); -#endif - PREFETCH_NOLIMIT (); - c2 = RE_STRING_CHAR (d, dend - d); - s2 = SYNTAX (c2); - - if (/* Case 2: Only one of S1 and S2 is Sword. */ - ((s1 == Sword) != (s2 == Sword)) - /* Case 3: Both of S1 and S2 are Sword, and macro - WORD_BOUNDARY_P (C1, C2) returns nonzero. */ - || ((s1 == Sword) && WORD_BOUNDARY_P (c1, c2))) - not = !not; - } - if (not) - break; - else - goto fail; - - case wordbeg: - DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); - - /* We FAIL in one of the following cases: */ - - /* Case 1: D is at the end of string. */ - if (AT_STRINGS_END (d)) - goto fail; - else - { - /* C1 is the character before D, S1 is the syntax of C1, C2 - is the character at D, and S2 is the syntax of C2. */ - re_wchar_t c1, c2; - int s1, s2; -#ifdef emacs - int offset = PTR_TO_OFFSET (d); - int charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset); - UPDATE_SYNTAX_TABLE (charpos); -#endif - PREFETCH (); - c2 = RE_STRING_CHAR (d, dend - d); - s2 = SYNTAX (c2); - - /* Case 2: S2 is not Sword. */ - if (s2 != Sword) - goto fail; - - /* Case 3: D is not at the beginning of string ... */ - if (!AT_STRINGS_BEG (d)) - { - GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); -#ifdef emacs - UPDATE_SYNTAX_TABLE_BACKWARD (charpos - 1); -#endif - s1 = SYNTAX (c1); - - /* ... and S1 is Sword, and WORD_BOUNDARY_P (C1, C2) - returns 0. */ - if ((s1 == Sword) && !WORD_BOUNDARY_P (c1, c2)) - goto fail; - } - } - break; - - case wordend: - DEBUG_PRINT1 ("EXECUTING wordend.\n"); - - /* We FAIL in one of the following cases: */ - - /* Case 1: D is at the beginning of string. */ - if (AT_STRINGS_BEG (d)) - goto fail; - else - { - /* C1 is the character before D, S1 is the syntax of C1, C2 - is the character at D, and S2 is the syntax of C2. */ - re_wchar_t c1, c2; - int s1, s2; -#ifdef emacs - int offset = PTR_TO_OFFSET (d) - 1; - int charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset); - UPDATE_SYNTAX_TABLE (charpos); -#endif - GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); - s1 = SYNTAX (c1); - - /* Case 2: S1 is not Sword. */ - if (s1 != Sword) - goto fail; - - /* Case 3: D is not at the end of string ... */ - if (!AT_STRINGS_END (d)) - { - PREFETCH_NOLIMIT (); - c2 = RE_STRING_CHAR (d, dend - d); -#ifdef emacs - UPDATE_SYNTAX_TABLE_FORWARD (charpos); -#endif - s2 = SYNTAX (c2); - - /* ... and S2 is Sword, and WORD_BOUNDARY_P (C1, C2) - returns 0. */ - if ((s2 == Sword) && !WORD_BOUNDARY_P (c1, c2)) - goto fail; - } - } - break; - - case syntaxspec: - case notsyntaxspec: - not = (re_opcode_t) *(p - 1) == notsyntaxspec; - mcnt = *p++; - DEBUG_PRINT3 ("EXECUTING %ssyntaxspec %d.\n", not?"not":"", mcnt); - PREFETCH (); -#ifdef emacs - { - int offset = PTR_TO_OFFSET (d); - int pos1 = SYNTAX_TABLE_BYTE_TO_CHAR (offset); - UPDATE_SYNTAX_TABLE (pos1); - } -#endif - { - int len; - re_wchar_t c; - - c = RE_STRING_CHAR_AND_LENGTH (d, dend - d, len); - - if ((SYNTAX (c) != (enum syntaxcode) mcnt) ^ not) - goto fail; - d += len; - } - break; - -#ifdef emacs - case before_dot: - DEBUG_PRINT1 ("EXECUTING before_dot.\n"); - if (PTR_BYTE_POS (d) >= PT_BYTE) - goto fail; - break; - - case at_dot: - DEBUG_PRINT1 ("EXECUTING at_dot.\n"); - if (PTR_BYTE_POS (d) != PT_BYTE) - goto fail; - break; - - case after_dot: - DEBUG_PRINT1 ("EXECUTING after_dot.\n"); - if (PTR_BYTE_POS (d) <= PT_BYTE) - goto fail; - break; - - case categoryspec: - case notcategoryspec: - not = (re_opcode_t) *(p - 1) == notcategoryspec; - mcnt = *p++; - DEBUG_PRINT3 ("EXECUTING %scategoryspec %d.\n", not?"not":"", mcnt); - PREFETCH (); - { - int len; - re_wchar_t c; - - c = RE_STRING_CHAR_AND_LENGTH (d, dend - d, len); - - if ((!CHAR_HAS_CATEGORY (c, mcnt)) ^ not) - goto fail; - d += len; - } - break; - -#endif /* emacs */ - - default: - abort (); - } - continue; /* Successfully executed one pattern command; keep going. */ - - - /* We goto here if a matching operation fails. */ - fail: - IMMEDIATE_QUIT_CHECK; - if (!FAIL_STACK_EMPTY ()) - { - re_char *str, *pat; - /* A restart point is known. Restore to that state. */ - DEBUG_PRINT1 ("\nFAIL:\n"); - POP_FAILURE_POINT (str, pat); - switch (SWITCH_ENUM_CAST ((re_opcode_t) *pat++)) - { - case on_failure_keep_string_jump: - assert (str == NULL); - goto continue_failure_jump; - - case on_failure_jump_nastyloop: - assert ((re_opcode_t)pat[-2] == no_op); - PUSH_FAILURE_POINT (pat - 2, str); - /* Fallthrough */ - - case on_failure_jump_loop: - case on_failure_jump: - case succeed_n: - d = str; - continue_failure_jump: - EXTRACT_NUMBER_AND_INCR (mcnt, pat); - p = pat + mcnt; - break; - - case no_op: - /* A special frame used for nastyloops. */ - goto fail; - - default: - abort(); - } - - assert (p >= bufp->buffer && p <= pend); - - 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. */ - -/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN - bytes; nonzero otherwise. */ - -static int -bcmp_translate (s1, s2, len, translate, multibyte) - re_char *s1, *s2; - register int len; - RE_TRANSLATE_TYPE translate; - const int multibyte; -{ - register re_char *p1 = s1, *p2 = s2; - re_char *p1_end = s1 + len; - re_char *p2_end = s2 + len; - - /* FIXME: Checking both p1 and p2 presumes that the two strings might have - different lengths, but relying on a single `len' would break this. -sm */ - while (p1 < p1_end && p2 < p2_end) - { - int p1_charlen, p2_charlen; - re_wchar_t p1_ch, p2_ch; - - p1_ch = RE_STRING_CHAR_AND_LENGTH (p1, p1_end - p1, p1_charlen); - p2_ch = RE_STRING_CHAR_AND_LENGTH (p2, p2_end - p2, p2_charlen); - - if (RE_TRANSLATE (translate, p1_ch) - != RE_TRANSLATE (translate, p2_ch)) - return 1; - - p1 += p1_charlen, p2 += p2_charlen; - } - - if (p1 != p1_end || p2 != p2_end) - return 1; - - 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; - size_t 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; - - ret = regex_compile ((re_char*) pattern, length, re_syntax_options, bufp); - - if (!ret) - return NULL; - return gettext (re_error_msgid[(int) ret]); -} -WEAK_ALIAS (__re_compile_pattern, re_compile_pattern) - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC - -/* BSD has one and only one pattern buffer. */ -static struct re_pattern_buffer re_comp_buf; - -char * -# ifdef _LIBC -/* Make these definitions weak in libc, so POSIX programs can redefine - these names if they don't use our functions, and still use - regcomp/regexec below without link errors. */ -weak_function -# endif -re_comp (s) - const char *s; -{ - reg_errcode_t ret; - - if (!s) - { - if (!re_comp_buf.buffer) - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext ("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) - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext (re_error_msgid[(int) REG_ESPACE]); - re_comp_buf.allocated = 200; - - re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); - if (re_comp_buf.fastmap == NULL) - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext (re_error_msgid[(int) REG_ESPACE]); - } - - /* Since `re_exec' always passes NULL for the `regs' argument, we - don't need to initialize the pattern buffer fields which affect it. */ - - ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); - - if (!ret) - return NULL; - - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext (re_error_msgid[(int) ret]); -} - - -int -# ifdef _LIBC -weak_function -# endif -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 /* _REGEX_RE_COMP */ - -/* 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; - `fastmap' to an allocated space for the fastmap; - `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 *__restrict preg; - const char *__restrict pattern; - int cflags; -{ - reg_errcode_t ret; - reg_syntax_t 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; - preg->used = 0; - - /* Try to allocate space for the fastmap. */ - preg->fastmap = (char *) malloc (1 << BYTEWIDTH); - - if (cflags & REG_ICASE) - { - unsigned i; - - preg->translate - = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE - * sizeof (*(RE_TRANSLATE_TYPE)0)); - 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; - } - else - syntax |= RE_NO_NEWLINE_ANCHOR; - - 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 ((re_char*) 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; - - if (ret == REG_NOERROR && preg->fastmap) - { /* Compute the fastmap now, since regexec cannot modify the pattern - buffer. */ - re_compile_fastmap (preg); - if (preg->can_be_null) - { /* The fastmap can't be used anyway. */ - free (preg->fastmap); - preg->fastmap = NULL; - } - } - return (int) ret; -} -WEAK_ALIAS (__regcomp, regcomp) - - -/* 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 *__restrict preg; - const char *__restrict string; - size_t nmatch; - regmatch_t pmatch[__restrict_arr]; - 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 && pmatch; - - 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 * 2, regoff_t); - if (regs.start == NULL) - return (int) REG_NOMATCH; - regs.end = regs.start + nmatch; - } - - /* Instead of using not_eol to implement REG_NOTEOL, we could simply - pass (&private_preg, string, len + 1, 0, len, ...) pretending the string - was a little bit longer but still only matching the real part. - This works because the `endline' will check for a '\n' and will find a - '\0', correctly deciding that this is not the end of a line. - But it doesn't work out so nicely for REG_NOTBOL, since we don't have - a convenient '\0' there. For all we know, the string could be preceded - by '\n' which would throw things off. */ - - /* 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); - } - - /* We want zero return to mean success, unlike `re_search'. */ - return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; -} -WEAK_ALIAS (__regexec, regexec) - - -/* 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_msgid) / sizeof (re_error_msgid[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 = gettext (re_error_msgid[errcode]); - - 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; -} -WEAK_ALIAS (__regerror, regerror) - - -/* 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; -} -WEAK_ALIAS (__regfree, regfree) - -#endif /* not emacs */ - -/* arch-tag: 4ffd68ba-2a9e-435b-a21a-018990f9eeb2 - (do not change this comment) */
--- a/src/regex.h Wed Dec 24 23:32:12 2003 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,576 +0,0 @@ -/* Definitions for data structures and routines for the regular - expression library, version 0.12. - - Copyright (C) 1985,89,90,91,92,93,95,2000 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ - -#ifndef _REGEX_H -#define _REGEX_H 1 - -/* Allow the use in C++ code. */ -#ifdef __cplusplus -extern "C" { -#endif - -/* POSIX says that <sys/types.h> must be included (by the caller) before - <regex.h>. */ - -#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS -/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it - should be there. */ -# include <stddef.h> -#endif - -/* The following bits are used to determine the regexp syntax we - recognize. The set/not-set meanings where historically chosen so - that Emacs syntax had the value 0. - The bits are given in alphabetical order, and - the definitions shifted by one from the previous bit; thus, when we - add or remove a bit, only one other definition need change. */ -typedef unsigned long int reg_syntax_t; - -/* If this bit is not set, then \ inside a bracket expression is literal. - If set, then such a \ quotes the following character. */ -#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) - -/* If this bit is not set, then + and ? are operators, and \+ and \? are - literals. - If set, then \+ and \? are operators and + and ? are literals. */ -#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) - -/* If this bit is set, then character classes are supported. They are: - [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], - [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. - If not set, then character classes are not supported. */ -#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) - -/* If this bit is set, then ^ and $ are always anchors (outside bracket - expressions, of course). - If this bit is not set, then it depends: - ^ is an anchor if it is at the beginning of a regular - expression or after an open-group or an alternation operator; - $ is an anchor if it is at the end of a regular expression, or - before a close-group or an alternation operator. - - This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because - POSIX draft 11.2 says that * etc. in leading positions is undefined. - We already implemented a previous draft which made those constructs - invalid, though, so we haven't changed the code back. */ -#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) - -/* If this bit is set, then special characters are always special - regardless of where they are in the pattern. - If this bit is not set, then special characters are special only in - some contexts; otherwise they are ordinary. Specifically, - * + ? and intervals are only special when not after the beginning, - open-group, or alternation operator. */ -#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) - -/* If this bit is set, then *, +, ?, and { cannot be first in an re or - immediately after an alternation or begin-group operator. */ -#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) - -/* If this bit is set, then . matches newline. - If not set, then it doesn't. */ -#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) - -/* If this bit is set, then . doesn't match NUL. - If not set, then it does. */ -#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) - -/* If this bit is set, nonmatching lists [^...] do not match newline. - If not set, they do. */ -#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) - -/* If this bit is set, either \{...\} or {...} defines an - interval, depending on RE_NO_BK_BRACES. - If not set, \{, \}, {, and } are literals. */ -#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) - -/* If this bit is set, +, ? and | aren't recognized as operators. - If not set, they are. */ -#define RE_LIMITED_OPS (RE_INTERVALS << 1) - -/* If this bit is set, newline is an alternation operator. - If not set, newline is literal. */ -#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) - -/* If this bit is set, then `{...}' defines an interval, and \{ and \} - are literals. - If not set, then `\{...\}' defines an interval. */ -#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) - -/* If this bit is set, (...) defines a group, and \( and \) are literals. - If not set, \(...\) defines a group, and ( and ) are literals. */ -#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) - -/* If this bit is set, then \<digit> matches <digit>. - If not set, then \<digit> is a back-reference. */ -#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) - -/* If this bit is set, then | is an alternation operator, and \| is literal. - If not set, then \| is an alternation operator, and | is literal. */ -#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) - -/* If this bit is set, then an ending range point collating higher - than the starting range point, as in [z-a], is invalid. - If not set, then when ending range point collates higher than the - starting range point, the range is ignored. */ -#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) - -/* If this bit is set, then an unmatched ) is ordinary. - If not set, then an unmatched ) is invalid. */ -#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) - -/* If this bit is set, succeed as soon as we match the whole pattern, - without further backtracking. */ -#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) - -/* If this bit is set, do not process the GNU regex operators. - If not set, then the GNU regex operators are recognized. */ -#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) - -/* If this bit is set, then *?, +? and ?? match non greedily. */ -#define RE_FRUGAL (RE_NO_GNU_OPS << 1) - -/* If this bit is set, then (?:...) is treated as a shy group. */ -#define RE_SHY_GROUPS (RE_FRUGAL << 1) - -/* If this bit is set, ^ and $ only match at beg/end of buffer. */ -#define RE_NO_NEWLINE_ANCHOR (RE_SHY_GROUPS << 1) - -/* If this bit is set, turn on internal regex debugging. - If not set, and debugging was on, turn it off. - This only works if regex.c is compiled -DDEBUG. - We define this bit always, so that all that's needed to turn on - debugging is to recompile regex.c; the calling code can always have - this bit set, and it won't affect anything in the normal case. */ -#define RE_DEBUG (RE_NO_NEWLINE_ANCHOR << 1) - -/* This global variable defines the particular regexp syntax to use (for - some interfaces). When a regexp is compiled, the syntax used is - stored in the pattern buffer, so changing this does not affect - already-compiled regexps. */ -extern reg_syntax_t re_syntax_options; - -#ifdef emacs -/* In Emacs, this is the string or buffer in which we - are matching. It is used for looking up syntax properties. */ -extern Lisp_Object re_match_object; -#endif - - -/* Define combinations of the above bits for the standard possibilities. - (The [[[ comments delimit what gets put into the Texinfo file, so - don't delete them!) */ -/* [[[begin syntaxes]]] */ -#define RE_SYNTAX_EMACS \ - (RE_CHAR_CLASSES | RE_INTERVALS | RE_SHY_GROUPS | RE_FRUGAL) - -#define RE_SYNTAX_AWK \ - (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ - | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ - | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) - -#define RE_SYNTAX_GNU_AWK \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ - & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS)) - -#define RE_SYNTAX_POSIX_AWK \ - (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INTERVALS | RE_NO_GNU_OPS) - -#define RE_SYNTAX_GREP \ - (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ - | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ - | RE_NEWLINE_ALT) - -#define RE_SYNTAX_EGREP \ - (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ - | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ - | RE_NO_BK_VBAR) - -#define RE_SYNTAX_POSIX_EGREP \ - (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES) - -/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ -#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC - -#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC - -/* Syntax bits common to both basic and extended POSIX regex syntax. */ -#define _RE_SYNTAX_POSIX_COMMON \ - (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ - | RE_INTERVALS | RE_NO_EMPTY_RANGES) - -#define RE_SYNTAX_POSIX_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) - -/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes - RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this - isn't minimal, since other operators, such as \`, aren't disabled. */ -#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) - -#define RE_SYNTAX_POSIX_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ - | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) - -/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is - removed and RE_NO_BK_REFS is added. */ -#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) -/* [[[end syntaxes]]] */ - -/* Maximum number of duplicates an interval can allow. Some systems - (erroneously) define this in other header files, but we want our - value, so remove any previous define. */ -#ifdef RE_DUP_MAX -# undef RE_DUP_MAX -#endif -/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ -#define RE_DUP_MAX (0x7fff) - - -/* POSIX `cflags' bits (i.e., information for `regcomp'). */ - -/* If this bit is set, then use extended regular expression syntax. - If not set, then use basic regular expression syntax. */ -#define REG_EXTENDED 1 - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -#define REG_ICASE (REG_EXTENDED << 1) - -/* If this bit is set, then anchors do not match at newline - characters in the string. - If not set, then anchors do match at newlines. */ -#define REG_NEWLINE (REG_ICASE << 1) - -/* If this bit is set, then report only success or fail in regexec. - If not set, then returns differ between not matching and errors. */ -#define REG_NOSUB (REG_NEWLINE << 1) - - -/* POSIX `eflags' bits (i.e., information for regexec). */ - -/* If this bit is set, then the beginning-of-line operator doesn't match - the beginning of the string (presumably because it's not the - beginning of a line). - If not set, then the beginning-of-line operator does match the - beginning of the string. */ -#define REG_NOTBOL 1 - -/* Like REG_NOTBOL, except for the end-of-line. */ -#define REG_NOTEOL (1 << 1) - - -/* If any error codes are removed, changed, or added, update the - `re_error_msg' table in regex.c. */ -typedef enum -{ -#ifdef _XOPEN_SOURCE - REG_ENOSYS = -1, /* This will never happen for this implementation. */ -#endif - - REG_NOERROR = 0, /* Success. */ - REG_NOMATCH, /* Didn't find a match (for regexec). */ - - /* POSIX regcomp return error codes. (In the order listed in the - standard.) */ - REG_BADPAT, /* Invalid pattern. */ - REG_ECOLLATE, /* Not implemented. */ - REG_ECTYPE, /* Invalid character class name. */ - REG_EESCAPE, /* Trailing backslash. */ - REG_ESUBREG, /* Invalid back reference. */ - REG_EBRACK, /* Unmatched left bracket. */ - REG_EPAREN, /* Parenthesis imbalance. */ - REG_EBRACE, /* Unmatched \{. */ - REG_BADBR, /* Invalid contents of \{\}. */ - REG_ERANGE, /* Invalid range end. */ - REG_ESPACE, /* Ran out of memory. */ - REG_BADRPT, /* No preceding re for repetition op. */ - - /* Error codes we've added. */ - REG_EEND, /* Premature end. */ - REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ - REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ -} reg_errcode_t; - -/* This data structure represents a compiled pattern. Before calling - the pattern compiler, the fields `buffer', `allocated', `fastmap', - `translate', and `no_sub' can be set. After the pattern has been - compiled, the `re_nsub' field is available. All other fields are - private to the regex routines. */ - -#ifndef RE_TRANSLATE_TYPE -# define RE_TRANSLATE_TYPE char * -#endif - -struct re_pattern_buffer -{ -/* [[[begin pattern_buffer]]] */ - /* Space that holds the compiled pattern. It is declared as - `unsigned char *' because its elements are - sometimes used as array indexes. */ - unsigned char *buffer; - - /* Number of bytes to which `buffer' points. */ - size_t allocated; - - /* Number of bytes actually used in `buffer'. */ - size_t used; - - /* Syntax setting with which the pattern was compiled. */ - reg_syntax_t syntax; - - /* Pointer to a fastmap, if any, otherwise zero. re_search uses - the fastmap, if there is one, to skip over impossible - starting points for matches. */ - char *fastmap; - - /* Either a translate table to apply to all characters before - comparing them, or zero for no translation. The translation - is applied to a pattern when it is compiled and to a string - when it is matched. */ - RE_TRANSLATE_TYPE translate; - - /* Number of subexpressions found by the compiler. */ - size_t re_nsub; - - /* Zero if this pattern cannot match the empty string, one else. - Well, in truth it's used only in `re_search_2', to see - whether or not we should use the fastmap, so we don't set - this absolutely perfectly; see `re_compile_fastmap'. */ - unsigned can_be_null : 1; - - /* If REGS_UNALLOCATED, allocate space in the `regs' structure - for `max (RE_NREGS, re_nsub + 1)' groups. - If REGS_REALLOCATE, reallocate space if necessary. - If REGS_FIXED, use what's there. */ -#define REGS_UNALLOCATED 0 -#define REGS_REALLOCATE 1 -#define REGS_FIXED 2 - unsigned regs_allocated : 2; - - /* Set to zero when `regex_compile' compiles a pattern; set to one - by `re_compile_fastmap' if it updates the fastmap. */ - unsigned fastmap_accurate : 1; - - /* If set, `re_match_2' does not return information about - subexpressions. */ - unsigned no_sub : 1; - - /* If set, a beginning-of-line anchor doesn't match at the - beginning of the string. */ - unsigned not_bol : 1; - - /* Similarly for an end-of-line anchor. */ - unsigned not_eol : 1; - -#ifdef emacs - /* If true, multi-byte form in the `buffer' should be recognized as a - multibyte character. */ - unsigned multibyte : 1; -#endif - -/* [[[end pattern_buffer]]] */ -}; - -typedef struct re_pattern_buffer regex_t; - -/* Type for byte offsets within the string. POSIX mandates this. */ -typedef int regoff_t; - - -/* This is the structure we store register match data in. See - regex.texinfo for a full description of what registers match. */ -struct re_registers -{ - unsigned num_regs; - regoff_t *start; - regoff_t *end; -}; - - -/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, - `re_match_2' returns information about at least this many registers - the first time a `regs' structure is passed. */ -#ifndef RE_NREGS -# define RE_NREGS 30 -#endif - - -/* POSIX specification for registers. Aside from the different names than - `re_registers', POSIX uses an array of structures, instead of a - structure of arrays. */ -typedef struct -{ - regoff_t rm_so; /* Byte offset from string's start to substring's start. */ - regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ -} regmatch_t; - -/* Declarations for routines. */ - -/* To avoid duplicating every routine declaration -- once with a - prototype (if we are ANSI), and once without (if we aren't) -- we - use the following macro to declare argument types. This - unfortunately clutters up the declarations a bit, but I think it's - worth it. */ - -#if defined __STDC__ || defined PROTOTYPES - -# define _RE_ARGS(args) args - -#else /* not __STDC__ || PROTOTYPES */ - -# define _RE_ARGS(args) () - -#endif /* not __STDC__ || PROTOTYPES */ - -/* Sets the current default syntax to SYNTAX, and return the old syntax. - You can also simply assign to the `re_syntax_options' variable. */ -extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); - -/* Compile the regular expression PATTERN, with length LENGTH - and syntax given by the global `re_syntax_options', into the buffer - BUFFER. Return NULL if successful, and an error string if not. */ -extern const char *re_compile_pattern - _RE_ARGS ((const char *pattern, size_t length, - struct re_pattern_buffer *buffer)); - - -/* Compile a fastmap for the compiled pattern in BUFFER; used to - accelerate searches. Return 0 if successful and -2 if was an - internal error. */ -extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); - - -/* Search in the string STRING (with length LENGTH) for the pattern - compiled into BUFFER. Start searching at position START, for RANGE - characters. Return the starting position of the match, -1 for no - match, or -2 for an internal error. Also return register - information in REGS (if REGS and BUFFER->no_sub are nonzero). */ -extern int re_search - _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, - int length, int start, int range, struct re_registers *regs)); - - -/* Like `re_search', but search in the concatenation of STRING1 and - STRING2. Also, stop searching at index START + STOP. */ -extern int re_search_2 - _RE_ARGS ((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)); - - -/* Like `re_search', but return how many characters in STRING the regexp - in BUFFER matched, starting at position START. */ -extern int re_match - _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string, - int length, int start, struct re_registers *regs)); - - -/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ -extern int re_match_2 - _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1, - int length1, const char *string2, int length2, - int start, struct re_registers *regs, int stop)); - - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using BUFFER and REGS will use this memory - for recording register information. STARTS and ENDS must be - allocated with malloc, 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. */ -extern void re_set_registers - _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, - unsigned num_regs, regoff_t *starts, regoff_t *ends)); - -#if defined _REGEX_RE_COMP || defined _LIBC -# ifndef _CRAY -/* 4.2 bsd compatibility. */ -extern char *re_comp _RE_ARGS ((const char *)); -extern int re_exec _RE_ARGS ((const char *)); -# endif -#endif - -/* GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". */ -#ifndef __restrict -# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) -# if defined restrict || 199901L <= __STDC_VERSION__ -# define __restrict restrict -# else -# define __restrict -# endif -# endif -#endif -/* For now conditionally define __restrict_arr to expand to nothing. - Ideally we would have a test for the compiler which allows defining - it to restrict. */ -#ifndef __restrict_arr -# define __restrict_arr -#endif - -/* POSIX compatibility. */ -extern int regcomp _RE_ARGS ((regex_t *__restrict __preg, - const char *__restrict __pattern, - int __cflags)); - -extern int regexec _RE_ARGS ((const regex_t *__restrict __preg, - const char *__restrict __string, size_t __nmatch, - regmatch_t __pmatch[__restrict_arr], - int __eflags)); - -extern size_t regerror _RE_ARGS ((int __errcode, const regex_t *__preg, - char *__errbuf, size_t __errbuf_size)); - -extern void regfree _RE_ARGS ((regex_t *__preg)); - - -#ifdef __cplusplus -} -#endif /* C++ */ - -#endif /* regex.h */ - -/* -Local variables: -make-backup-files: t -version-control: t -trim-versions-without-asking: nil -End: -*/ - -/* arch-tag: bda6e3ec-3c02-4237-a55a-01ad2e120083 - (do not change this comment) */
--- a/src/scroll.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/scroll.c Sun Dec 28 16:03:57 2003 +0000 @@ -22,8 +22,9 @@ #include <config.h> #include <stdio.h> #include <string.h> +#include "lisp.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" -#include "lisp.h" #include "dispextern.h" #include "keyboard.h" #include "frame.h" @@ -100,7 +101,8 @@ register struct matrix_elt *p, *p1; register int cost, cost1; - int lines_moved = window_size + (scroll_region_ok ? 0 : lines_below); + int lines_moved = window_size + + (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)) ? 0 : lines_below); /* first_insert_cost[I] is the cost of doing the first insert-line at the i'th line of the lines we are considering, where I is origin 1 (as it is below). */ @@ -466,7 +468,8 @@ /* Overhead of setting the scroll window, plus the extra cost cost of scrolling by a distance of one. The extra cost is added once for consistency with the cost vectors */ - scroll_overhead = scroll_region_cost + extra_cost; + scroll_overhead + = TTY_SCROLL_REGION_COST (FRAME_TTY (frame)) + extra_cost; /* initialize the top left corner of the matrix */ matrix->writecost = 0; @@ -818,7 +821,7 @@ matrix = ((struct matrix_elt *) alloca ((window_size + 1) * (window_size + 1) * sizeof *matrix)); - if (scroll_region_ok) + if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame))) { calculate_direct_scrolling (frame, matrix, window_size, unchanged_at_bottom, @@ -914,7 +917,7 @@ if (amount == 0) return 0; - if (! scroll_region_ok) + if (! TTY_SCROLL_REGION_OK (FRAME_TTY (frame))) limit = height; else if (amount > 0) limit += amount;
--- a/src/sysdep.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/sysdep.c Sun Dec 28 16:03:57 2003 +0000 @@ -246,16 +246,11 @@ int emacs_ospeed; -/* The file descriptor for Emacs's input terminal. - Under Unix, this is normally zero except when using X; - under VMS, we place the input channel number here. */ -int input_fd; - void croak P_ ((char *)); #ifdef AIXHFT -void hft_init (); -void hft_reset (); +void hft_init P_ ((struct tty_output *)); +void hft_reset P_ ((struct tty_output *)); #endif /* Temporary used by `sigblock' when defined in terms of signprocmask. */ @@ -263,16 +258,7 @@ SIGMASKTYPE sigprocmask_set; -/* Specify a different file descriptor for further input operations. */ - -void -change_input_fd (fd) - int fd; -{ - input_fd = fd; -} - -/* Discard pending input on descriptor input_fd. */ +/* Discard pending input on all input descriptors. */ void discard_tty_input () @@ -290,22 +276,32 @@ #ifdef VMS end_kbd_input (); - SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0, + SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0, &buf.main, 0, 0, terminator_mask, 0, 0); queue_kbd_input (); #else /* not VMS */ #ifdef APOLLO { - int zero = 0; - ioctl (input_fd, TIOCFLUSH, &zero); + struct tty_output *tty; + for (tty = tty_list; tty; tty = tty->next) + { + int zero = 0; + ioctl (fileno (TTY_INPUT (tty)), TIOCFLUSH, &zero); + } } #else /* not Apollo */ #ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */ while (dos_keyread () != -1) ; #else /* not MSDOS */ - EMACS_GET_TTY (input_fd, &buf); - EMACS_SET_TTY (input_fd, &buf, 0); + { + struct tty_output *tty; + for (tty = tty_list; tty; tty = tty->next) + { + EMACS_GET_TTY (fileno (TTY_INPUT (tty)), &buf); + EMACS_SET_TTY (fileno (TTY_INPUT (tty)), &buf, 0); + } + } #endif /* not MSDOS */ #endif /* not Apollo */ #endif /* not VMS */ @@ -318,19 +314,14 @@ the terminal. */ void -#ifdef PROTOTYPES stuff_char (char c) -#else -stuff_char (c) - char c; -#endif { if (read_socket_hook) return; /* Should perhaps error if in batch mode */ #ifdef TIOCSTI - ioctl (input_fd, TIOCSTI, &c); + ioctl (fileno (TTY_INPUT (CURTTY())), TIOCSTI, &c); #else /* no TIOCSTI */ error ("Cannot stuff terminal input characters in this version of Unix"); #endif /* no TIOCSTI */ @@ -354,7 +345,7 @@ #ifdef VMS struct sensemode sg; - SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0, + SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &sg, 0, 0, &sg.class, 12, 0, 0, 0, 0 ); emacs_ospeed = sg.xmit_baud; #else /* not VMS */ @@ -362,7 +353,7 @@ struct termios sg; sg.c_cflag = B9600; - tcgetattr (input_fd, &sg); + tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg); emacs_ospeed = cfgetospeed (&sg); #if defined (USE_GETOBAUD) && defined (getobaud) /* m88k-motorola-sysv3 needs this (ghazi@noc.rutgers.edu) 9/1/94. */ @@ -375,16 +366,16 @@ sg.c_cflag = B9600; #ifdef HAVE_TCATTR - tcgetattr (input_fd, &sg); + tcgetattr (fileno (TTY_INPUT (CURTTY())), &sg); #else - ioctl (input_fd, TCGETA, &sg); + ioctl (fileno (TTY_INPUT (CURTTY())), TCGETA, &sg); #endif emacs_ospeed = sg.c_cflag & CBAUD; #else /* neither VMS nor TERMIOS nor TERMIO */ struct sgttyb sg; sg.sg_ospeed = B9600; - if (ioctl (input_fd, TIOCGETP, &sg) < 0) + if (ioctl (fileno (TTY_INPUT (CURTTY())), TIOCGETP, &sg) < 0) abort (); emacs_ospeed = sg.sg_ospeed; #endif /* not HAVE_TERMIO */ @@ -947,7 +938,7 @@ #ifdef SIGWINCH sigunblock (sigmask (SIGWINCH)); #endif - fcntl (input_fd, F_SETFL, old_fcntl_flags | FASYNC); + fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags | FASYNC); interrupts_deferred = 0; } @@ -961,7 +952,7 @@ #ifdef SIGWINCH sigblock (sigmask (SIGWINCH)); #endif - fcntl (input_fd, F_SETFL, old_fcntl_flags); + fcntl (fileno (TTY_INPUT (CURTTY())), F_SETFL, old_fcntl_flags); interrupts_deferred = 1; } @@ -976,7 +967,7 @@ if (read_socket_hook) return; - ioctl (input_fd, FIOASYNC, &on); + ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &on); interrupts_deferred = 0; } @@ -988,7 +979,7 @@ if (read_socket_hook) return; - ioctl (input_fd, FIOASYNC, &off); + ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &off); interrupts_deferred = 1; } @@ -1009,7 +1000,7 @@ sigemptyset (&st); sigaddset (&st, SIGIO); - ioctl (input_fd, FIOASYNC, &on); + ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &on); interrupts_deferred = 0; sigprocmask (SIG_UNBLOCK, &st, (sigset_t *)0); } @@ -1022,7 +1013,7 @@ if (read_socket_hook) return; - ioctl (input_fd, FIOASYNC, &off); + ioctl (fileno (TTY_INPUT (CURTTY())), FIOASYNC, &off); interrupts_deferred = 1; } @@ -1082,22 +1073,23 @@ group, redirect the TTY to point to our own process group. We need to be in our own process group to receive SIGIO properly. */ void -narrow_foreground_group () +narrow_foreground_group (struct tty_output *tty) { int me = getpid (); setpgrp (0, inherited_pgroup); + /* XXX This only works on the controlling tty. */ if (inherited_pgroup != me) - EMACS_SET_TTY_PGRP (input_fd, &me); + EMACS_SET_TTY_PGRP (fileno (TTY_INPUT (tty)), &me); setpgrp (0, me); } /* Set the tty to our original foreground group. */ void -widen_foreground_group () +widen_foreground_group (struct tty_output *tty) { if (inherited_pgroup != getpid ()) - EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup); + EMACS_SET_TTY_PGRP (fileno (TTY_INPUT (tty)), &inherited_pgroup); setpgrp (0, inherited_pgroup); } @@ -1255,14 +1247,6 @@ } -/* The initial tty mode bits */ -struct emacs_tty old_tty; - -/* 1 if we have been through init_sys_modes. */ -int term_initted; - -/* 1 if outer tty status has been recorded. */ -int old_tty_valid; #ifdef BSD4_1 /* BSD 4.1 needs to keep track of the lmode bits in order to start @@ -1298,7 +1282,18 @@ #endif void -init_sys_modes () +init_all_sys_modes (void) +{ + struct tty_output *tty = tty_list; + while (tty) { + init_sys_modes (tty); + tty = tty->next; + } +} + +void +init_sys_modes (tty_out) + struct tty_output *tty_out; { struct emacs_tty tty; @@ -1354,11 +1349,11 @@ #ifndef VMS4_4 sys_access_reinit (); #endif -#endif /* not VMS */ +#endif /* VMS */ #ifdef BSD_PGRPS if (! read_socket_hook && EQ (Vwindow_system, Qnil)) - narrow_foreground_group (); + narrow_foreground_group (tty_out); #endif #ifdef HAVE_WINDOW_SYSTEM @@ -1367,14 +1362,15 @@ if (!read_socket_hook && EQ (Vwindow_system, Qnil)) #endif { - EMACS_GET_TTY (input_fd, &old_tty); - - old_tty_valid = 1; - - tty = old_tty; + if (! tty_out->old_tty) + tty_out->old_tty = (struct emacs_tty *) xmalloc (sizeof (struct emacs_tty)); + + EMACS_GET_TTY (fileno (TTY_INPUT (tty_out)), tty_out->old_tty); + + tty = *tty_out->old_tty; #if defined (HAVE_TERMIO) || defined (HAVE_TERMIOS) - XSETINT (Vtty_erase_char, old_tty.main.c_cc[VERASE]); + XSETINT (Vtty_erase_char, tty.main.c_cc[VERASE]); #ifdef DGUX /* This allows meta to be sent on 8th bit. */ @@ -1408,7 +1404,7 @@ on output */ tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */ #ifdef CS8 - if (meta_key) + if (tty_out->meta_key) { tty.main.c_cflag |= CS8; /* allow 8th bit on input */ tty.main.c_cflag &= ~PARENB;/* Don't check parity */ @@ -1539,7 +1535,7 @@ tty.tchars.t_stopc = '\023'; } - tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode; + tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | tty_out->old_tty.lmode; #ifdef ultrix /* Under Ultrix 4.2a, leaving this out doesn't seem to hurt anything, and leaving it in breaks the meta key. Go figure. */ @@ -1557,33 +1553,33 @@ tty.ltchars = new_ltchars; #endif /* HAVE_LTCHARS */ #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida, MW Aug 1993 */ - if (!term_initted) + if (!tty_out->term_initted) internal_terminal_init (); dos_ttraw (); #endif - EMACS_SET_TTY (input_fd, &tty, 0); + EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)), &tty, 0); /* This code added to insure that, if flow-control is not to be used, we have an unlocked terminal at the start. */ #ifdef TCXONC - if (!flow_control) ioctl (input_fd, TCXONC, 1); + if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TCXONC, 1); #endif #ifndef APOLLO #ifdef TIOCSTART - if (!flow_control) ioctl (input_fd, TIOCSTART, 0); + if (!flow_control) ioctl (fileno (TTY_INPUT (tty_out)), TIOCSTART, 0); #endif #endif #if defined (HAVE_TERMIOS) || defined (HPUX9) #ifdef TCOON - if (!flow_control) tcflow (input_fd, TCOON); + if (!flow_control) tcflow (fileno (TTY_INPUT (tty_out)), TCOON); #endif #endif #ifdef AIXHFT - hft_init (); + hft_init (tty_out); #ifdef IBMR2AIX { /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it @@ -1598,7 +1594,7 @@ #ifdef VMS /* Appears to do nothing when in PASTHRU mode. - SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0, + SYS$QIOW (0, fileno (TTY_INPUT (tty_out)), IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0, interrupt_signal, oob_chars, 0, 0, 0, 0); */ queue_kbd_input (0); @@ -1611,9 +1607,9 @@ if (interrupt_input && ! read_socket_hook && EQ (Vwindow_system, Qnil)) { - old_fcntl_owner = fcntl (input_fd, F_GETOWN, 0); - fcntl (input_fd, F_SETOWN, getpid ()); - init_sigio (input_fd); + old_fcntl_owner = fcntl (fileno (TTY_INPUT (tty_out)), F_GETOWN, 0); + fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, getpid ()); + init_sigio (fileno (TTY_INPUT (tty_out))); } #endif /* F_GETOWN */ #endif /* F_SETOWN_BUG */ @@ -1621,7 +1617,7 @@ #ifdef BSD4_1 if (interrupt_input) - init_sigio (input_fd); + init_sigio (fileno (TTY_INPUT (tty_out))); #endif #ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */ @@ -1631,9 +1627,9 @@ /* This symbol is defined on recent USG systems. Someone says without this call USG won't really buffer the file even with a call to setbuf. */ - setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf); + setvbuf (TTY_OUTPUT (tty_out), (char *) _sobuf, _IOFBF, sizeof _sobuf); #else - setbuf (stdout, (char *) _sobuf); + setbuf (TTY_OUTPUT (tty_out), (char *) _sobuf); #endif #ifdef HAVE_WINDOW_SYSTEM /* Emacs' window system on MSDOG uses the `internal terminal' and therefore @@ -1646,38 +1642,48 @@ #endif ) #endif - set_terminal_modes (); - - if (!term_initted - && FRAMEP (Vterminal_frame) - && FRAME_TERMCAP_P (XFRAME (Vterminal_frame))) - init_frame_faces (XFRAME (Vterminal_frame)); - - if (term_initted && no_redraw_on_reenter) + + if (!tty_out->term_initted) + { + Lisp_Object tail, frame; + FOR_EACH_FRAME (tail, frame) + { + if (FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (frame)) == tty_out) + init_frame_faces (XFRAME (frame)); + } + } + + if (tty_out->term_initted && no_redraw_on_reenter) { if (display_completed) direct_output_forward_char (0); } else { + Lisp_Object tail, frame; frame_garbaged = 1; - if (FRAMEP (Vterminal_frame)) - FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1; + FOR_EACH_FRAME (tail, frame) + { + if (FRAME_TERMCAP_P (XFRAME (frame)) + && FRAME_TTY (XFRAME (frame)) == tty_out) + FRAME_GARBAGED_P (XFRAME (frame)) = 1; + } } - term_initted = 1; + tty_out->term_initted = 1; } /* Return nonzero if safe to use tabs in output. At the time this is called, init_sys_modes has not been done yet. */ int -tabs_safe_p () +tabs_safe_p (struct tty_output *tty) { - struct emacs_tty tty; - - EMACS_GET_TTY (input_fd, &tty); - return EMACS_TTY_TABS_OK (&tty); + struct emacs_tty etty; + + EMACS_GET_TTY (fileno (TTY_INPUT (tty)), &etty); + return EMACS_TTY_TABS_OK (&etty); } /* Get terminal size from system. @@ -1685,7 +1691,8 @@ We store 0 if there's no valid information. */ void -get_frame_size (widthp, heightp) +get_tty_size (tty_out, widthp, heightp) + struct tty_output *tty_out; int *widthp, *heightp; { @@ -1694,7 +1701,7 @@ /* BSD-style. */ struct winsize size; - if (ioctl (input_fd, TIOCGWINSZ, &size) == -1) + if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGWINSZ, &size) == -1) *widthp = *heightp = 0; else { @@ -1708,7 +1715,7 @@ /* SunOS - style. */ struct ttysize size; - if (ioctl (input_fd, TIOCGSIZE, &size) == -1) + if (ioctl (fileno (TTY_INPUT (tty_out)), TIOCGSIZE, &size) == -1) *widthp = *heightp = 0; else { @@ -1721,7 +1728,7 @@ struct sensemode tty; - SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0, + SYS$QIOW (0, fileno (TTY_INPUT (CURTTY())), IO$_SENSEMODE, &tty, 0, 0, &tty.class, 12, 0, 0, 0, 0); *widthp = tty.scr_wid; *heightp = tty.scr_len; @@ -1778,10 +1785,21 @@ } +void +reset_all_sys_modes (void) +{ + struct tty_output *tty = tty_list; + while (tty) { + reset_sys_modes (tty); + tty = tty->next; + } +} + /* Prepare the terminal for exiting Emacs; move the cursor to the bottom of the frame, turn off interrupt-driven I/O, etc. */ void -reset_sys_modes () +reset_sys_modes (tty_out) + struct tty_output *tty_out; { struct frame *sf; @@ -1790,7 +1808,7 @@ fflush (stdout); return; } - if (!term_initted) + if (!tty_out->term_initted) return; #ifdef HAVE_WINDOW_SYSTEM /* Emacs' window system on MSDOG uses the `internal terminal' and therefore @@ -1820,12 +1838,12 @@ } #endif - reset_terminal_modes (); - fflush (stdout); + tty_reset_terminal_modes (tty_out); + fflush (TTY_OUTPUT (tty_out)); #ifdef BSD_SYSTEM #ifndef BSD4_1 /* Avoid possible loss of output when changing terminal modes. */ - fsync (fileno (stdout)); + fsync (TTY_OUTPUT (tty_out)); #endif #endif @@ -1835,12 +1853,13 @@ if (interrupt_input) { reset_sigio (); - fcntl (input_fd, F_SETOWN, old_fcntl_owner); + fcntl (fileno (TTY_INPUT (tty_out)), F_SETOWN, old_fcntl_owner); } #endif /* F_SETOWN */ #endif /* F_SETOWN_BUG */ #ifdef O_NDELAY - fcntl (input_fd, F_SETFL, fcntl (input_fd, F_GETFL, 0) & ~O_NDELAY); + fcntl (fileno (TTY_INPUT (tty_out)), F_SETFL, + fcntl (fileno (TTY_INPUT (tty_out)), F_GETFL, 0) & ~O_NDELAY); #endif #endif /* F_SETFL */ #ifdef BSD4_1 @@ -1848,8 +1867,9 @@ reset_sigio (); #endif /* BSD4_1 */ - if (old_tty_valid) - while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR) + if (tty_out->old_tty) + while (EMACS_SET_TTY (fileno (TTY_INPUT (tty_out)), + tty_out->old_tty, 0) < 0 && errno == EINTR) ; #ifdef MSDOS /* Demacs 1.1.2 91/10/20 Manabu Higashida */ @@ -1860,7 +1880,7 @@ /* Ultrix's termios *ignores* any line discipline except TERMIODISC. A different old line discipline is therefore not restored, yet. Restore the old line discipline by hand. */ - ioctl (0, TIOCSETD, &old_tty.main.c_line); + ioctl (0, TIOCSETD, &tty_out->old_tty.main.c_line); #endif #ifdef AIXHFT @@ -1868,7 +1888,7 @@ #endif #ifdef BSD_PGRPS - widen_foreground_group (); + widen_foreground_group (tty_out); #endif } @@ -1933,9 +1953,9 @@ { int status; - if (input_fd == 0) + if (fileno (TTY_INPUT (CURTTY())) == 0) { - status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0); + status = SYS$ASSIGN (&input_dsc, &fileno (TTY_INPUT (CURTTY())), 0, 0); if (! (status & 1)) LIB$STOP (status); } @@ -1946,7 +1966,7 @@ void stop_vms_input () { - return SYS$DASSGN (input_fd); + return SYS$DASSGN (fileno (TTY_INPUT (CURTTY()))); } short input_buffer; @@ -1962,7 +1982,7 @@ waiting_for_ast = 0; stop_input = 0; - status = SYS$QIO (0, input_fd, IO$_READVBLK, + status = SYS$QIO (0, fileno (TTY_INPUT (CURTTY())), IO$_READVBLK, &input_iosb, kbd_input_ast, 1, &input_buffer, 1, 0, terminator_mask, 0, 0); } @@ -2079,7 +2099,7 @@ #endif if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */ { - SYS$CANCEL (input_fd); + SYS$CANCEL (fileno (TTY_INPUT (CURTTY()))); return; } @@ -2088,7 +2108,7 @@ SYS$CLREF (input_ef); waiting_for_ast = 1; stop_input = 1; - SYS$CANCEL (input_fd); + SYS$CANCEL (fileno (TTY_INPUT (CURTTY()))); SYS$SETAST (1); SYS$WAITFR (input_ef); waiting_for_ast = 0; @@ -3470,7 +3490,7 @@ char *badfunc; { printf ("%s not yet implemented\r\n", badfunc); - reset_sys_modes (); + reset_all_sys_modes (); exit (1); } @@ -5056,7 +5076,7 @@ char *badfunc; { printf ("%s not yet implemented\r\n", badfunc); - reset_sys_modes (); + reset_all_sys_modes (); exit (1); } @@ -5078,7 +5098,7 @@ /* Called from init_sys_modes. */ void -hft_init () +hft_init (struct tty_output *tty_out) { int junk; @@ -5126,13 +5146,14 @@ } /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly at times. */ - line_ins_del_ok = char_ins_del_ok = 0; + TTY_LINE_INS_DEL_OK (tty_out) = 0; + TTY_CHAR_INS_DEL_OK (tty_out) = 0; } /* Reset the rubout key to backspace. */ void -hft_reset () +hft_reset (struct tty_output *tty_out) { struct hfbuf buf; struct hfkeymap keymap;
--- a/src/term.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/term.c Sun Dec 28 16:03:57 2003 +0000 @@ -26,9 +26,12 @@ #include <ctype.h> #include <string.h> +#include <sys/file.h> + +#include "lisp.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "termopts.h" -#include "lisp.h" #include "charset.h" #include "coding.h" #include "keyboard.h" @@ -60,53 +63,53 @@ #include "macterm.h" #endif +#ifndef O_RDWR +#define O_RDWR 2 +#endif + static void turn_on_face P_ ((struct frame *, int face_id)); static void turn_off_face P_ ((struct frame *, int face_id)); -static void tty_show_cursor P_ ((void)); -static void tty_hide_cursor P_ ((void)); - -#define OUTPUT(a) \ - tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) - curY), cmputc) -#define OUTPUT1(a) tputs (a, 1, cmputc) -#define OUTPUTL(a, lines) tputs (a, lines, cmputc) - -#define OUTPUT_IF(a) \ - do { \ - if (a) \ - tputs (a, (int) (FRAME_LINES (XFRAME (selected_frame)) \ - - curY), cmputc); \ - } while (0) - -#define OUTPUT1_IF(a) do { if (a) tputs (a, 1, cmputc); } while (0) +static void tty_show_cursor P_ ((struct tty_output *)); +static void tty_hide_cursor P_ ((struct tty_output *)); + +void delete_tty P_ ((struct tty_output *)); +static void delete_tty_1 P_ ((struct tty_output *)); + + +#define OUTPUT(tty, a) \ + emacs_tputs ((tty), a, \ + (int) (FRAME_LINES (XFRAME (selected_frame)) \ + - curY (tty)), \ + cmputc) + +#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc) +#define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc) + +#define OUTPUT_IF(tty, a) \ + do { \ + if (a) \ + emacs_tputs ((tty), a, \ + (int) (FRAME_LINES (XFRAME (selected_frame)) \ + - curY (tty) ), \ + cmputc); \ + } while (0) + +#define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0) /* Function to use to ring the bell. */ Lisp_Object Vring_bell_function; -/* Terminal characteristics that higher levels want to look at. - These are all extern'd in termchar.h */ - -int must_write_spaces; /* Nonzero means spaces in the text - must actually be output; can't just skip - over some columns to leave them blank. */ -int min_padding_speed; /* Speed below which no padding necessary */ - -int line_ins_del_ok; /* Terminal can insert and delete lines */ -int char_ins_del_ok; /* Terminal can insert and delete chars */ -int scroll_region_ok; /* Terminal supports setting the - scroll window */ -int scroll_region_cost; /* Cost of setting a scroll window, - measured in characters */ -int memory_below_frame; /* Terminal remembers lines - scrolled off bottom */ -int fast_clear_end_of_line; /* Terminal has a `ce' string */ - -/* Nonzero means no need to redraw the entire frame on resuming - a suspended Emacs. This is useful on terminals with multiple pages, - where one page is used for Emacs and another for all else. */ - +/* Terminal characteristics that higher levels want to look at. */ + +struct tty_output *tty_list; + +/* Nonzero means no need to redraw the entire frame on resuming a + suspended Emacs. This is useful on terminals with multiple + pages, where one page is used for Emacs and another for all + else. */ int no_redraw_on_reenter; - + /* Hook functions that you can set to snap out the functions in this file. These are all extern'd in termhooks.h */ @@ -131,7 +134,7 @@ void (*write_glyphs_hook) P_ ((struct glyph *, int)); void (*delete_glyphs_hook) P_ ((int)); -int (*read_socket_hook) P_ ((int, struct input_event *, int, int)); +int (*read_socket_hook) P_ ((struct input_event *, int, int)); void (*frame_up_to_date_hook) P_ ((struct frame *)); @@ -235,51 +238,6 @@ void (*judge_scroll_bars_hook) P_ ((FRAME_PTR FRAME)); -/* Strings, numbers and flags taken from the termcap entry. */ - -char *TS_ins_line; /* "al" */ -char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */ -char *TS_bell; /* "bl" */ -char *TS_clr_to_bottom; /* "cd" */ -char *TS_clr_line; /* "ce", clear to end of line */ -char *TS_clr_frame; /* "cl" */ -char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */ -char *TS_set_scroll_region_1; /* "cS" (4 params: total lines, - lines above scroll region, lines below it, - total lines again) */ -char *TS_del_char; /* "dc" */ -char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */ -char *TS_del_line; /* "dl" */ -char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */ -char *TS_delete_mode; /* "dm", enter character-delete mode */ -char *TS_end_delete_mode; /* "ed", leave character-delete mode */ -char *TS_end_insert_mode; /* "ei", leave character-insert mode */ -char *TS_ins_char; /* "ic" */ -char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */ -char *TS_insert_mode; /* "im", enter character-insert mode */ -char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */ -char *TS_end_keypad_mode; /* "ke" */ -char *TS_keypad_mode; /* "ks" */ -char *TS_pad_char; /* "pc", char to use as padding */ -char *TS_repeat; /* "rp" (2 params, # times to repeat - and character to be repeated) */ -char *TS_end_standout_mode; /* "se" */ -char *TS_fwd_scroll; /* "sf" */ -char *TS_standout_mode; /* "so" */ -char *TS_rev_scroll; /* "sr" */ -char *TS_end_termcap_modes; /* "te" */ -char *TS_termcap_modes; /* "ti" */ -char *TS_visible_bell; /* "vb" */ -char *TS_cursor_normal; /* "ve" */ -char *TS_cursor_visible; /* "vs" */ -char *TS_cursor_invisible; /* "vi" */ -char *TS_set_window; /* "wi" (4 params, start and end of window, - each as vpos and hpos) */ - -/* Value of the "NC" (no_color_video) capability, or 0 if not - present. */ - -static int TN_no_color_video; /* Meaning of bits in no_color_video. Each bit set means that the corresponding attribute cannot be combined with colors. */ @@ -297,68 +255,6 @@ NC_ALT_CHARSET = 1 << 8 }; -/* "md" -- turn on bold (extra bright mode). */ - -char *TS_enter_bold_mode; - -/* "mh" -- turn on half-bright mode. */ - -char *TS_enter_dim_mode; - -/* "mb" -- enter blinking mode. */ - -char *TS_enter_blink_mode; - -/* "mr" -- enter reverse video mode. */ - -char *TS_enter_reverse_mode; - -/* "us"/"ue" -- start/end underlining. */ - -char *TS_exit_underline_mode, *TS_enter_underline_mode; - -/* "as"/"ae" -- start/end alternate character set. Not really - supported, yet. */ - -char *TS_enter_alt_charset_mode, *TS_exit_alt_charset_mode; - -/* "me" -- switch appearances off. */ - -char *TS_exit_attribute_mode; - -/* "Co" -- number of colors. */ - -int TN_max_colors; - -/* "pa" -- max. number of color pairs on screen. Not handled yet. - Could be a problem if not equal to TN_max_colors * TN_max_colors. */ - -int TN_max_pairs; - -/* "op" -- SVr4 set default pair to its original value. */ - -char *TS_orig_pair; - -/* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color. - 1 param, the color index. */ - -char *TS_set_foreground, *TS_set_background; - -int TF_hazeltine; /* termcap hz flag. */ -int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */ -int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */ -int TF_underscore; /* termcap ul flag: _ underlines if over-struck on - non-blank position. Must clear before writing _. */ -int TF_teleray; /* termcap xt flag: many weird consequences. - For t1061. */ - -static int RPov; /* # chars to start a TS_repeat */ - -static int delete_in_insert_mode; /* delete mode == insert mode */ - -static int se_is_so; /* 1 if same string both enters and leaves - standout mode */ - /* internal state */ /* The largest frame width in any call to calculate_costs. */ @@ -369,20 +265,6 @@ int max_frame_lines; -static int costs_set; /* Nonzero if costs have been calculated. */ - -int insert_mode; /* Nonzero when in insert mode. */ -int standout_mode; /* Nonzero when in standout mode. */ - -/* Size of window specified by higher levels. - This is the number of lines, from the top of frame downwards, - which can participate in insert-line/delete-line operations. - - Effectively it excludes the bottom frame_lines - specified_window_size - lines from those operations. */ - -int specified_window; - /* Frame currently being redisplayed; 0 if not currently redisplaying. (Direct output does not count). */ @@ -392,10 +274,6 @@ static int system_uses_terminfo; -/* Flag used in tty_show/hide_cursor. */ - -static int tty_cursor_hidden; - char *tparam (); extern char *tgetstr (); @@ -415,6 +293,8 @@ void ring_bell () { + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + if (!NILP (Vring_bell_function)) { Lisp_Object function; @@ -434,40 +314,51 @@ Vring_bell_function = function; } - else if (!FRAME_TERMCAP_P (XFRAME (selected_frame))) + else if (!FRAME_TERMCAP_P (f)) (*ring_bell_hook) (); - else - OUTPUT (TS_visible_bell && visible_bell ? TS_visible_bell : TS_bell); + else { + struct tty_output *tty = FRAME_TTY (f); + OUTPUT (tty, tty->TS_visible_bell && visible_bell ? tty->TS_visible_bell : tty->TS_bell); + } +} + +void tty_set_terminal_modes (struct tty_output *tty) +{ + OUTPUT_IF (tty, tty->TS_termcap_modes); + OUTPUT_IF (tty, tty->TS_cursor_visible); + OUTPUT_IF (tty, tty->TS_keypad_mode); + losecursor (tty); } void set_terminal_modes () { - if (FRAME_TERMCAP_P (XFRAME (selected_frame))) - { - OUTPUT_IF (TS_termcap_modes); - OUTPUT_IF (TS_cursor_visible); - OUTPUT_IF (TS_keypad_mode); - losecursor (); - } + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + if (FRAME_TERMCAP_P (f)) + tty_set_terminal_modes (FRAME_TTY (f)); else (*set_terminal_modes_hook) (); } +void tty_reset_terminal_modes (struct tty_output *tty) +{ + turn_off_highlight (tty); + turn_off_insert (tty); + OUTPUT_IF (tty, tty->TS_end_keypad_mode); + OUTPUT_IF (tty, tty->TS_cursor_normal); + OUTPUT_IF (tty, tty->TS_end_termcap_modes); + OUTPUT_IF (tty, tty->TS_orig_pair); + /* Output raw CR so kernel can track the cursor hpos. */ + current_tty = tty; + cmputc ('\r'); +} + void reset_terminal_modes () { - if (FRAME_TERMCAP_P (XFRAME (selected_frame))) - { - turn_off_highlight (); - turn_off_insert (); - OUTPUT_IF (TS_end_keypad_mode); - OUTPUT_IF (TS_cursor_normal); - OUTPUT_IF (TS_end_termcap_modes); - OUTPUT_IF (TS_orig_pair); - /* Output raw CR so kernel can track the cursor hpos. */ - cmputc ('\r'); - } + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + if (FRAME_TERMCAP_P (f)) + tty_reset_terminal_modes (FRAME_TTY (f)); else if (reset_terminal_modes_hook) (*reset_terminal_modes_hook) (); } @@ -487,10 +378,11 @@ { if (FRAME_TERMCAP_P (f)) { + struct tty_output *tty = FRAME_TTY (f); if (!XWINDOW (selected_window)->cursor_off_p) - tty_show_cursor (); - turn_off_insert (); - background_highlight (); + tty_show_cursor (tty); + turn_off_insert (tty); + background_highlight (tty); } else update_end_hook (f); @@ -502,11 +394,13 @@ set_terminal_window (size) int size; { - if (FRAME_TERMCAP_P (updating_frame)) + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + if (FRAME_TERMCAP_P (f)) { - specified_window = size ? size : FRAME_LINES (updating_frame); - if (scroll_region_ok) - set_scroll_region (0, specified_window); + struct tty_output *tty = FRAME_TTY (f); + tty->specified_window = size ? size : FRAME_LINES (f); + if (TTY_SCROLL_REGION_OK (tty)) + set_scroll_region (0, tty->specified_window); } else set_terminal_window_hook (size); @@ -517,77 +411,78 @@ int start, stop; { char *buf; - struct frame *sf = XFRAME (selected_frame); - - if (TS_set_scroll_region) - buf = tparam (TS_set_scroll_region, 0, 0, start, stop - 1); - else if (TS_set_scroll_region_1) - buf = tparam (TS_set_scroll_region_1, 0, 0, - FRAME_LINES (sf), start, - FRAME_LINES (sf) - stop, - FRAME_LINES (sf)); + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + struct tty_output *tty = FRAME_TTY (f); + + if (tty->TS_set_scroll_region) + buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1); + else if (tty->TS_set_scroll_region_1) + buf = tparam (tty->TS_set_scroll_region_1, 0, 0, + FRAME_LINES (f), start, + FRAME_LINES (f) - stop, + FRAME_LINES (f)); else - buf = tparam (TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (sf)); - - OUTPUT (buf); + buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f)); + + OUTPUT (tty, buf); xfree (buf); - losecursor (); + losecursor (tty); } static void -turn_on_insert () +turn_on_insert (struct tty_output *tty) { - if (!insert_mode) - OUTPUT (TS_insert_mode); - insert_mode = 1; + if (!tty->insert_mode) + OUTPUT (tty, tty->TS_insert_mode); + tty->insert_mode = 1; } void -turn_off_insert () +turn_off_insert (struct tty_output *tty) { - if (insert_mode) - OUTPUT (TS_end_insert_mode); - insert_mode = 0; + if (tty->insert_mode) + OUTPUT (tty, tty->TS_end_insert_mode); + tty->insert_mode = 0; } /* Handle highlighting. */ void -turn_off_highlight () +turn_off_highlight (struct tty_output *tty) { - if (standout_mode) - OUTPUT_IF (TS_end_standout_mode); - standout_mode = 0; + if (tty->standout_mode) + OUTPUT_IF (tty, tty->TS_end_standout_mode); + tty->standout_mode = 0; } static void -turn_on_highlight () +turn_on_highlight (struct tty_output *tty) { - if (!standout_mode) - OUTPUT_IF (TS_standout_mode); - standout_mode = 1; + if (!tty->standout_mode) + OUTPUT_IF (tty, tty->TS_standout_mode); + tty->standout_mode = 1; } static void -toggle_highlight () +toggle_highlight (struct tty_output *tty) { - if (standout_mode) - turn_off_highlight (); + if (tty->standout_mode) + turn_off_highlight (tty); else - turn_on_highlight (); + turn_on_highlight (tty); } /* Make cursor invisible. */ static void -tty_hide_cursor () +tty_hide_cursor (struct tty_output *tty) { - if (tty_cursor_hidden == 0) + if (tty->cursor_hidden == 0) { - tty_cursor_hidden = 1; - OUTPUT_IF (TS_cursor_invisible); + tty->cursor_hidden = 1; + OUTPUT_IF (tty, tty->TS_cursor_invisible); } } @@ -595,13 +490,13 @@ /* Ensure that cursor is visible. */ static void -tty_show_cursor () +tty_show_cursor (struct tty_output *tty) { - if (tty_cursor_hidden) + if (tty->cursor_hidden) { - tty_cursor_hidden = 0; - OUTPUT_IF (TS_cursor_normal); - OUTPUT_IF (TS_cursor_visible); + tty->cursor_hidden = 0; + OUTPUT_IF (tty, tty->TS_cursor_normal); + OUTPUT_IF (tty, tty->TS_cursor_visible); } } @@ -611,23 +506,23 @@ depends on the user option inverse-video. */ void -background_highlight () +background_highlight (struct tty_output *tty) { if (inverse_video) - turn_on_highlight (); + turn_on_highlight (tty); else - turn_off_highlight (); + turn_off_highlight (tty); } /* Set standout mode to the mode specified for the text to be output. */ static void -highlight_if_desired () +highlight_if_desired (struct tty_output *tty) { if (inverse_video) - turn_on_highlight (); + turn_on_highlight (tty); else - turn_off_highlight (); + turn_off_highlight (tty); } @@ -638,26 +533,30 @@ cursor_to (vpos, hpos) int vpos, hpos; { - struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame); - + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + struct tty_output *tty; + if (! FRAME_TERMCAP_P (f) && cursor_to_hook) { (*cursor_to_hook) (vpos, hpos); return; } + tty = FRAME_TTY (f); + /* Detect the case where we are called from reset_sys_modes and the costs have never been calculated. Do nothing. */ - if (! costs_set) + if (! tty->costs_set) return; - if (curY == vpos && curX == hpos) + if (curY (tty) == vpos + && curX (tty) == hpos) return; - if (!TF_standout_motion) - background_highlight (); - if (!TF_insmode_motion) - turn_off_insert (); - cmgoto (vpos, hpos); + if (!tty->TF_standout_motion) + background_highlight (tty); + if (!tty->TF_insmode_motion) + turn_off_insert (tty); + cmgoto (tty, vpos, hpos); } /* Similar but don't take any account of the wasted characters. */ @@ -667,18 +566,21 @@ int row, col; { struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame); + struct tty_output *tty; if (! FRAME_TERMCAP_P (f)) { (*raw_cursor_to_hook) (row, col); return; } - if (curY == row && curX == col) + tty = FRAME_TTY (f); + if (curY (tty) == row + && curX (tty) == col) return; - if (!TF_standout_motion) - background_highlight (); - if (!TF_insmode_motion) - turn_off_insert (); - cmgoto (row, col); + if (!tty->TF_standout_motion) + background_highlight (tty); + if (!tty->TF_insmode_motion) + turn_off_insert (tty); + cmgoto (tty, row, col); } /* Erase operations */ @@ -689,22 +591,26 @@ { register int i; - if (clear_to_end_hook && ! FRAME_TERMCAP_P (updating_frame)) + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + struct tty_output *tty; + + if (clear_to_end_hook && ! FRAME_TERMCAP_P (f)) { (*clear_to_end_hook) (); return; } - if (TS_clr_to_bottom) + tty = FRAME_TTY (f); + if (tty->TS_clr_to_bottom) { - background_highlight (); - OUTPUT (TS_clr_to_bottom); + background_highlight (tty); + OUTPUT (tty, tty->TS_clr_to_bottom); } else { - for (i = curY; i < FRAME_LINES (XFRAME (selected_frame)); i++) + for (i = curY (tty); i < FRAME_LINES (f); i++) { cursor_to (i, 0); - clear_end_of_line (FRAME_COLS (XFRAME (selected_frame))); + clear_end_of_line (FRAME_COLS (f)); } } } @@ -714,19 +620,20 @@ void clear_frame () { - struct frame *sf = XFRAME (selected_frame); - - if (clear_frame_hook - && ! FRAME_TERMCAP_P ((updating_frame ? updating_frame : sf))) + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + struct tty_output *tty; + + if (clear_frame_hook && ! FRAME_TERMCAP_P (f)) { (*clear_frame_hook) (); return; } - if (TS_clr_frame) + tty = FRAME_TTY (f); + if (tty->TS_clr_frame) { - background_highlight (); - OUTPUT (TS_clr_frame); - cmat (0, 0); + background_highlight (tty); + OUTPUT (tty, tty->TS_clr_frame); + cmat (tty, 0, 0); } else { @@ -746,44 +653,47 @@ { register int i; + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + struct tty_output *tty; + if (clear_end_of_line_hook - && ! FRAME_TERMCAP_P ((updating_frame - ? updating_frame - : XFRAME (selected_frame)))) + && ! FRAME_TERMCAP_P (f)) { (*clear_end_of_line_hook) (first_unused_hpos); return; } + tty = FRAME_TTY (f); + /* Detect the case where we are called from reset_sys_modes and the costs have never been calculated. Do nothing. */ - if (! costs_set) + if (! tty->costs_set) return; - if (curX >= first_unused_hpos) + if (curX (tty) >= first_unused_hpos) return; - background_highlight (); - if (TS_clr_line) + background_highlight (tty); + if (tty->TS_clr_line) { - OUTPUT1 (TS_clr_line); + OUTPUT1 (tty, tty->TS_clr_line); } else { /* have to do it the hard way */ - struct frame *sf = XFRAME (selected_frame); - turn_off_insert (); + turn_off_insert (tty); /* Do not write in last row last col with Auto-wrap on. */ - if (AutoWrap && curY == FRAME_LINES (sf) - 1 - && first_unused_hpos == FRAME_COLS (sf)) + if (AutoWrap (tty) + && curY (tty) == FRAME_LINES (f) - 1 + && first_unused_hpos == FRAME_COLS (f)) first_unused_hpos--; - for (i = curX; i < first_unused_hpos; i++) + for (i = curX (tty); i < first_unused_hpos; i++) { - if (termscript) - fputc (' ', termscript); - putchar (' '); + if (TTY_TERMSCRIPT (tty)) + fputc (' ', TTY_TERMSCRIPT (tty)); + fputc (' ', TTY_OUTPUT (tty)); } - cmplus (first_unused_hpos - curX); + cmplus (tty, first_unused_hpos - curX (tty)); } } @@ -902,8 +812,8 @@ register int len; { int produced, consumed; - struct frame *sf = XFRAME (selected_frame); - struct frame *f = updating_frame ? updating_frame : sf; + struct frame *f = updating_frame ? updating_frame : XFRAME (selected_frame); + struct tty_output *tty; unsigned char conversion_buffer[1024]; int conversion_buffer_size = sizeof conversion_buffer; @@ -914,20 +824,22 @@ return; } - turn_off_insert (); - tty_hide_cursor (); + tty = FRAME_TTY (f); + + turn_off_insert (tty); + tty_hide_cursor (tty); /* Don't dare write in last column of bottom line, if Auto-Wrap, since that would scroll the whole frame on some terminals. */ - if (AutoWrap - && curY + 1 == FRAME_LINES (sf) - && (curX + len) == FRAME_COLS (sf)) + if (AutoWrap (tty) + && curY (tty) + 1 == FRAME_LINES (f) + && (curX (tty) + len) == FRAME_COLS (f)) len --; if (len <= 0) return; - cmplus (len); + cmplus (tty, len); /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ @@ -944,7 +856,7 @@ break; /* Turn appearance modes of the face of the run on. */ - highlight_if_desired (); + highlight_if_desired (tty); turn_on_face (f, face_id); while (n > 0) @@ -957,11 +869,13 @@ &consumed); if (produced > 0) { - fwrite (conversion_buffer, 1, produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, produced, termscript); + fwrite (conversion_buffer, 1, produced, + TTY_OUTPUT (tty)); + if (ferror (TTY_OUTPUT (tty))) + clearerr (TTY_OUTPUT (tty)); + if (TTY_TERMSCRIPT (tty)) + fwrite (conversion_buffer, 1, produced, + TTY_TERMSCRIPT (tty)); } len -= consumed; n -= consumed; @@ -970,7 +884,7 @@ /* Turn appearance modes off. */ turn_off_face (f, face_id); - turn_off_highlight (); + turn_off_highlight (tty); } /* We may have to output some codes to terminate the writing. */ @@ -981,16 +895,17 @@ 0, conversion_buffer_size); if (terminal_coding.produced > 0) { - fwrite (conversion_buffer, 1, terminal_coding.produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) + fwrite (conversion_buffer, 1, terminal_coding.produced, + TTY_OUTPUT (tty)); + if (ferror (TTY_OUTPUT (tty))) + clearerr (TTY_OUTPUT (tty)); + if (TTY_TERMSCRIPT (tty)) fwrite (conversion_buffer, 1, terminal_coding.produced, - termscript); + TTY_TERMSCRIPT (tty)); } } - cmcheckmagic (); + cmcheckmagic (tty); } /* If start is zero, insert blanks instead of a string at start */ @@ -1002,32 +917,32 @@ { char *buf; struct glyph *glyph = NULL; - struct frame *f, *sf; - + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + struct tty_output *tty; + if (len <= 0) return; - if (insert_glyphs_hook) + if (insert_glyphs_hook && ! FRAME_TERMCAP_P (f)) { (*insert_glyphs_hook) (start, len); return; } - sf = XFRAME (selected_frame); - f = updating_frame ? updating_frame : sf; - - if (TS_ins_multi_chars) + tty = FRAME_TTY (f); + + if (tty->TS_ins_multi_chars) { - buf = tparam (TS_ins_multi_chars, 0, 0, len); - OUTPUT1 (buf); + buf = tparam (tty->TS_ins_multi_chars, 0, 0, len); + OUTPUT1 (tty, buf); xfree (buf); if (start) write_glyphs (start, len); return; } - turn_on_insert (); - cmplus (len); + turn_on_insert (tty); + cmplus (tty, len); /* The bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; while (len-- > 0) @@ -1036,7 +951,7 @@ unsigned char conversion_buffer[1024]; int conversion_buffer_size = sizeof conversion_buffer; - OUTPUT1_IF (TS_ins_char); + OUTPUT1_IF (tty, tty->TS_ins_char); if (!start) { conversion_buffer[0] = SPACEGLYPH; @@ -1044,7 +959,7 @@ } else { - highlight_if_desired (); + highlight_if_desired (tty); turn_on_face (f, start->face_id); glyph = start; ++start; @@ -1052,7 +967,7 @@ occupies more than one column. */ while (len && CHAR_GLYPH_PADDING_P (*start)) { - OUTPUT1_IF (TS_ins_char); + OUTPUT1_IF (tty, tty->TS_ins_char); start++, len--; } @@ -1068,22 +983,24 @@ if (produced > 0) { - fwrite (conversion_buffer, 1, produced, stdout); - if (ferror (stdout)) - clearerr (stdout); - if (termscript) - fwrite (conversion_buffer, 1, produced, termscript); + fwrite (conversion_buffer, 1, produced, + TTY_OUTPUT (tty)); + if (ferror (TTY_OUTPUT (tty))) + clearerr (TTY_OUTPUT (tty)); + if (TTY_TERMSCRIPT (tty)) + fwrite (conversion_buffer, 1, produced, + TTY_TERMSCRIPT (tty)); } - OUTPUT1_IF (TS_pad_inserted_char); + OUTPUT1_IF (tty, tty->TS_pad_inserted_char); if (start) { turn_off_face (f, glyph->face_id); - turn_off_highlight (); + turn_off_highlight (tty); } } - cmcheckmagic (); + cmcheckmagic (tty); } void @@ -1092,34 +1009,37 @@ { char *buf; register int i; - - if (delete_glyphs_hook && ! FRAME_TERMCAP_P (updating_frame)) + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + struct tty_output *tty = FRAME_TTY (f); + + if (delete_glyphs_hook && ! FRAME_TERMCAP_P (f)) { (*delete_glyphs_hook) (n); return; } - if (delete_in_insert_mode) + + if (tty->delete_in_insert_mode) { - turn_on_insert (); + turn_on_insert (tty); } else { - turn_off_insert (); - OUTPUT_IF (TS_delete_mode); + turn_off_insert (tty); + OUTPUT_IF (tty, tty->TS_delete_mode); } - - if (TS_del_multi_chars) + + if (tty->TS_del_multi_chars) { - buf = tparam (TS_del_multi_chars, 0, 0, n); - OUTPUT1 (buf); + buf = tparam (tty->TS_del_multi_chars, 0, 0, n); + OUTPUT1 (tty, buf); xfree (buf); } else for (i = 0; i < n; i++) - OUTPUT1 (TS_del_char); - if (!delete_in_insert_mode) - OUTPUT_IF (TS_end_delete_mode); + OUTPUT1 (tty, tty->TS_del_char); + if (!tty->delete_in_insert_mode) + OUTPUT_IF (tty, tty->TS_end_delete_mode); } /* Insert N lines at vpos VPOS. If N is negative, delete -N lines. */ @@ -1128,68 +1048,73 @@ ins_del_lines (vpos, n) int vpos, n; { - char *multi = n > 0 ? TS_ins_multi_lines : TS_del_multi_lines; - char *single = n > 0 ? TS_ins_line : TS_del_line; - char *scroll = n > 0 ? TS_rev_scroll : TS_fwd_scroll; - struct frame *sf; - - register int i = n > 0 ? n : -n; - register char *buf; - - if (ins_del_lines_hook && ! FRAME_TERMCAP_P (updating_frame)) + struct frame *f = (updating_frame ? updating_frame : XFRAME (selected_frame)); + if (ins_del_lines_hook && ! FRAME_TERMCAP_P (f)) { (*ins_del_lines_hook) (vpos, n); return; } - - sf = XFRAME (selected_frame); - - /* If the lines below the insertion are being pushed - into the end of the window, this is the same as clearing; - and we know the lines are already clear, since the matching - deletion has already been done. So can ignore this. */ - /* If the lines below the deletion are blank lines coming - out of the end of the window, don't bother, - as there will be a matching inslines later that will flush them. */ - if (scroll_region_ok && vpos + i >= specified_window) - return; - if (!memory_below_frame && vpos + i >= FRAME_LINES (sf)) - return; - - if (multi) - { - raw_cursor_to (vpos, 0); - background_highlight (); - buf = tparam (multi, 0, 0, i); - OUTPUT (buf); - xfree (buf); - } - else if (single) - { - raw_cursor_to (vpos, 0); - background_highlight (); - while (--i >= 0) - OUTPUT (single); - if (TF_teleray) - curX = 0; - } else { - set_scroll_region (vpos, specified_window); - if (n < 0) - raw_cursor_to (specified_window - 1, 0); + struct tty_output *tty = FRAME_TTY (f); + char *multi = n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines; + char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line; + char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll; + + register int i = n > 0 ? n : -n; + register char *buf; + + /* If the lines below the insertion are being pushed + into the end of the window, this is the same as clearing; + and we know the lines are already clear, since the matching + deletion has already been done. So can ignore this. */ + /* If the lines below the deletion are blank lines coming + out of the end of the window, don't bother, + as there will be a matching inslines later that will flush them. */ + if (TTY_SCROLL_REGION_OK (tty) + && vpos + i >= tty->specified_window) + return; + if (!TTY_MEMORY_BELOW_FRAME (tty) + && vpos + i >= FRAME_LINES (f)) + return; + + if (multi) + { + raw_cursor_to (vpos, 0); + background_highlight (tty); + buf = tparam (multi, 0, 0, i); + OUTPUT (tty, buf); + xfree (buf); + } + else if (single) + { + raw_cursor_to (vpos, 0); + background_highlight (tty); + while (--i >= 0) + OUTPUT (tty, single); + if (tty->TF_teleray) + curX (tty) = 0; + } else - raw_cursor_to (vpos, 0); - background_highlight (); - while (--i >= 0) - OUTPUTL (scroll, specified_window - vpos); - set_scroll_region (0, specified_window); - } - - if (!scroll_region_ok && memory_below_frame && n < 0) - { - cursor_to (FRAME_LINES (sf) + n, 0); - clear_to_end (); + { + set_scroll_region (vpos, tty->specified_window); + if (n < 0) + raw_cursor_to (tty->specified_window - 1, 0); + else + raw_cursor_to (vpos, 0); + background_highlight (tty); + while (--i >= 0) + OUTPUTL (tty, scroll, tty->specified_window - vpos); + set_scroll_region (0, tty->specified_window); + } + + if (!TTY_SCROLL_REGION_OK (tty) + && TTY_MEMORY_BELOW_FRAME (tty) + && n < 0) + { + cursor_to (FRAME_LINES (f) + n, 0); + clear_to_end (); + } } } @@ -1247,26 +1172,27 @@ /* ARGSUSED */ static void -calculate_ins_del_char_costs (frame) - FRAME_PTR frame; +calculate_ins_del_char_costs (f) + FRAME_PTR f; { + struct tty_output *tty = FRAME_TTY (f); int ins_startup_cost, del_startup_cost; int ins_cost_per_char, del_cost_per_char; register int i; register int *p; - if (TS_ins_multi_chars) + if (tty->TS_ins_multi_chars) { ins_cost_per_char = 0; - ins_startup_cost = string_cost_one_line (TS_ins_multi_chars); + ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars); } - else if (TS_ins_char || TS_pad_inserted_char - || (TS_insert_mode && TS_end_insert_mode)) + else if (tty->TS_ins_char || tty->TS_pad_inserted_char + || (tty->TS_insert_mode && tty->TS_end_insert_mode)) { - ins_startup_cost = (30 * (string_cost (TS_insert_mode) - + string_cost (TS_end_insert_mode))) / 100; - ins_cost_per_char = (string_cost_one_line (TS_ins_char) - + string_cost_one_line (TS_pad_inserted_char)); + ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode) + + string_cost (tty->TS_end_insert_mode))) / 100; + ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char) + + string_cost_one_line (tty->TS_pad_inserted_char)); } else { @@ -1274,18 +1200,18 @@ ins_cost_per_char = 0; } - if (TS_del_multi_chars) + if (tty->TS_del_multi_chars) { del_cost_per_char = 0; - del_startup_cost = string_cost_one_line (TS_del_multi_chars); + del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars); } - else if (TS_del_char) + else if (tty->TS_del_char) { - del_startup_cost = (string_cost (TS_delete_mode) - + string_cost (TS_end_delete_mode)); - if (delete_in_insert_mode) + del_startup_cost = (string_cost (tty->TS_delete_mode) + + string_cost (tty->TS_end_delete_mode)); + if (tty->delete_in_insert_mode) del_startup_cost /= 2; - del_cost_per_char = string_cost_one_line (TS_del_char); + del_cost_per_char = string_cost_one_line (tty->TS_del_char); } else { @@ -1294,16 +1220,16 @@ } /* Delete costs are at negative offsets */ - p = &char_ins_del_cost (frame)[0]; - for (i = FRAME_COLS (frame); --i >= 0;) + p = &char_ins_del_cost (f)[0]; + for (i = FRAME_COLS (f); --i >= 0;) *--p = (del_startup_cost += del_cost_per_char); /* Doing nothing is free */ - p = &char_ins_del_cost (frame)[0]; + p = &char_ins_del_cost (f)[0]; *p++ = 0; /* Insert costs are at positive offsets */ - for (i = FRAME_COLS (frame); --i >= 0;) + for (i = FRAME_COLS (f); --i >= 0;) *p++ = (ins_startup_cost += ins_cost_per_char); } @@ -1311,13 +1237,15 @@ calculate_costs (frame) FRAME_PTR frame; { - register char *f = (TS_set_scroll_region - ? TS_set_scroll_region - : TS_set_scroll_region_1); + struct tty_output *tty = FRAME_TTY (frame); + register char *f = (tty->TS_set_scroll_region + ? tty->TS_set_scroll_region + : tty->TS_set_scroll_region_1); FRAME_COST_BAUD_RATE (frame) = baud_rate; - scroll_region_cost = string_cost (f); + if (FRAME_TERMCAP_P (frame)) + TTY_SCROLL_REGION_COST (frame->output_data.tty) = string_cost (f); /* These variables are only used for terminal stuff. They are allocated once for the terminal frame of X-windows emacs, but not used afterwards. @@ -1328,7 +1256,7 @@ max_frame_lines = max (max_frame_lines, FRAME_LINES (frame)); max_frame_cols = max (max_frame_cols, FRAME_COLS (frame)); - costs_set = 1; + tty->costs_set = 1; if (char_ins_del_vector != 0) char_ins_del_vector @@ -1343,26 +1271,26 @@ bzero (char_ins_del_vector, (sizeof (int) + 2 * max_frame_cols * sizeof (int))); - if (f && (!TS_ins_line && !TS_del_line)) + if (f && (!tty->TS_ins_line && !tty->TS_del_line)) do_line_insertion_deletion_costs (frame, - TS_rev_scroll, TS_ins_multi_lines, - TS_fwd_scroll, TS_del_multi_lines, + tty->TS_rev_scroll, tty->TS_ins_multi_lines, + tty->TS_fwd_scroll, tty->TS_del_multi_lines, f, f, 1); else do_line_insertion_deletion_costs (frame, - TS_ins_line, TS_ins_multi_lines, - TS_del_line, TS_del_multi_lines, + tty->TS_ins_line, tty->TS_ins_multi_lines, + tty->TS_del_line, tty->TS_del_multi_lines, 0, 0, 1); calculate_ins_del_char_costs (frame); /* Don't use TS_repeat if its padding is worse than sending the chars */ - if (TS_repeat && per_line_cost (TS_repeat) * baud_rate < 9000) - RPov = string_cost (TS_repeat); + if (tty->TS_repeat && per_line_cost (tty->TS_repeat) * baud_rate < 9000) + tty->RPov = string_cost (tty->TS_repeat); else - RPov = FRAME_COLS (frame) * 2; - - cmcostinit (); /* set up cursor motion costs */ + tty->RPov = FRAME_COLS (frame) * 2; + + cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */ } struct fkey_table { @@ -1812,10 +1740,10 @@ from them. Some display attributes may not be used together with color; the termcap capability `NC' specifies which ones. */ -#define MAY_USE_WITH_COLORS_P(ATTR) \ - (TN_max_colors > 0 \ - ? (TN_no_color_video & (ATTR)) == 0 \ - : 1) +#define MAY_USE_WITH_COLORS_P(tty, ATTR) \ + (tty->TN_max_colors > 0 \ + ? (tty->TN_no_color_video & (ATTR)) == 0 \ + : 1) /* Turn appearances of face FACE_ID on tty frame F on. */ @@ -1827,12 +1755,13 @@ struct face *face = FACE_FROM_ID (f, face_id); long fg = face->foreground; long bg = face->background; + struct tty_output *tty = FRAME_TTY (f); /* Do this first because TS_end_standout_mode may be the same as TS_exit_attribute_mode, which turns all appearances off. */ - if (MAY_USE_WITH_COLORS_P (NC_REVERSE)) + if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE)) { - if (TN_max_colors > 0) + if (tty->TN_max_colors > 0) { if (fg >= 0 && bg >= 0) { @@ -1846,13 +1775,13 @@ { if (fg == FACE_TTY_DEFAULT_FG_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR) - toggle_highlight (); + toggle_highlight (tty); } else { if (fg == FACE_TTY_DEFAULT_BG_COLOR || bg == FACE_TTY_DEFAULT_FG_COLOR) - toggle_highlight (); + toggle_highlight (tty); } } else @@ -1863,53 +1792,53 @@ { if (fg == FACE_TTY_DEFAULT_FG_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR) - toggle_highlight (); + toggle_highlight (tty); } else { if (fg == FACE_TTY_DEFAULT_BG_COLOR || bg == FACE_TTY_DEFAULT_FG_COLOR) - toggle_highlight (); + toggle_highlight (tty); } } } if (face->tty_bold_p) { - if (MAY_USE_WITH_COLORS_P (NC_BOLD)) - OUTPUT1_IF (TS_enter_bold_mode); + if (MAY_USE_WITH_COLORS_P (tty, NC_BOLD)) + OUTPUT1_IF (tty, tty->TS_enter_bold_mode); } else if (face->tty_dim_p) - if (MAY_USE_WITH_COLORS_P (NC_DIM)) - OUTPUT1_IF (TS_enter_dim_mode); + if (MAY_USE_WITH_COLORS_P (tty, NC_DIM)) + OUTPUT1_IF (tty, tty->TS_enter_dim_mode); /* Alternate charset and blinking not yet used. */ if (face->tty_alt_charset_p - && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET)) - OUTPUT1_IF (TS_enter_alt_charset_mode); + && MAY_USE_WITH_COLORS_P (tty, NC_ALT_CHARSET)) + OUTPUT1_IF (tty, tty->TS_enter_alt_charset_mode); if (face->tty_blinking_p - && MAY_USE_WITH_COLORS_P (NC_BLINK)) - OUTPUT1_IF (TS_enter_blink_mode); - - if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE)) - OUTPUT1_IF (TS_enter_underline_mode); - - if (TN_max_colors > 0) + && MAY_USE_WITH_COLORS_P (tty, NC_BLINK)) + OUTPUT1_IF (tty, tty->TS_enter_blink_mode); + + if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE)) + OUTPUT1_IF (tty, tty->TS_enter_underline_mode); + + if (tty->TN_max_colors > 0) { char *p; - if (fg >= 0 && TS_set_foreground) + if (fg >= 0 && tty->TS_set_foreground) { - p = tparam (TS_set_foreground, NULL, 0, (int) fg); - OUTPUT (p); + p = tparam (tty->TS_set_foreground, NULL, 0, (int) fg); + OUTPUT (tty, p); xfree (p); } - if (bg >= 0 && TS_set_background) + if (bg >= 0 && tty->TS_set_background) { - p = tparam (TS_set_background, NULL, 0, (int) bg); - OUTPUT (p); + p = tparam (tty->TS_set_background, NULL, 0, (int) bg); + OUTPUT (tty, p); xfree (p); } } @@ -1924,10 +1853,11 @@ int face_id; { struct face *face = FACE_FROM_ID (f, face_id); + struct tty_output *tty = FRAME_TTY (f); xassert (face != NULL); - if (TS_exit_attribute_mode) + if (tty->TS_exit_attribute_mode) { /* Capability "me" will turn off appearance modes double-bright, half-bright, reverse-video, standout, underline. It may or @@ -1939,32 +1869,32 @@ || face->tty_blinking_p || face->tty_underline_p) { - OUTPUT1_IF (TS_exit_attribute_mode); - if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0) - standout_mode = 0; + OUTPUT1_IF (tty, tty->TS_exit_attribute_mode); + if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0) + tty->standout_mode = 0; } if (face->tty_alt_charset_p) - OUTPUT_IF (TS_exit_alt_charset_mode); + OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode); } else { /* If we don't have "me" we can only have those appearances that have exit sequences defined. */ if (face->tty_alt_charset_p) - OUTPUT_IF (TS_exit_alt_charset_mode); + OUTPUT_IF (tty, tty->TS_exit_alt_charset_mode); if (face->tty_underline_p) - OUTPUT_IF (TS_exit_underline_mode); + OUTPUT_IF (tty, tty->TS_exit_underline_mode); } /* Switch back to default colors. */ - if (TN_max_colors > 0 + if (tty->TN_max_colors > 0 && ((face->foreground != FACE_TTY_DEFAULT_COLOR && face->foreground != FACE_TTY_DEFAULT_FG_COLOR) || (face->background != FACE_TTY_DEFAULT_COLOR && face->background != FACE_TTY_DEFAULT_BG_COLOR))) - OUTPUT1_IF (TS_orig_pair); + OUTPUT1_IF (tty, tty->TS_orig_pair); } @@ -1973,21 +1903,21 @@ colors FG and BG. */ int -tty_capable_p (f, caps, fg, bg) - struct frame *f; +tty_capable_p (tty, caps, fg, bg) + struct tty_output *tty; unsigned caps; unsigned long fg, bg; { -#define TTY_CAPABLE_P_TRY(cap, TS, NC_bit) \ - if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit))) \ +#define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \ + if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \ return 0; - TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE, TS_standout_mode, NC_REVERSE); - TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE); - TTY_CAPABLE_P_TRY (TTY_CAP_BOLD, TS_enter_bold_mode, NC_BOLD); - TTY_CAPABLE_P_TRY (TTY_CAP_DIM, TS_enter_dim_mode, NC_DIM); - TTY_CAPABLE_P_TRY (TTY_CAP_BLINK, TS_enter_blink_mode, NC_BLINK); - TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_INVERSE, tty->TS_standout_mode, NC_REVERSE); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_UNDERLINE, tty->TS_enter_underline_mode, NC_UNDERLINE); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_BOLD, tty->TS_enter_bold_mode, NC_BOLD); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_DIM, tty->TS_enter_dim_mode, NC_DIM); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_BLINK, tty->TS_enter_blink_mode, NC_BLINK); + TTY_CAPABLE_P_TRY (tty, TTY_CAP_ALT_CHARSET, tty->TS_enter_alt_charset_mode, NC_ALT_CHARSET); /* We can do it! */ return 1; @@ -2002,7 +1932,8 @@ (display) Lisp_Object display; { - return TN_max_colors > 0 ? Qt : Qnil; + struct tty_output *tty = FRAME_TTY (SELECTED_FRAME ()); + return tty->TN_max_colors > 0 ? Qt : Qnil; } /* Return the number of supported colors. */ @@ -2012,7 +1943,8 @@ (display) Lisp_Object display; { - return make_number (TN_max_colors); + struct tty_output *tty = FRAME_TTY (SELECTED_FRAME ()); + return make_number (tty->TN_max_colors); } #ifndef WINDOWSNT @@ -2020,8 +1952,7 @@ /* Save or restore the default color-related capabilities of this terminal. */ static void -tty_default_color_capabilities (save) - int save; +tty_default_color_capabilities (struct tty_output *tty, int save) { static char *default_orig_pair, *default_set_foreground, *default_set_background; @@ -2031,30 +1962,30 @@ { if (default_orig_pair) xfree (default_orig_pair); - default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL; + default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL; if (default_set_foreground) xfree (default_set_foreground); - default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground) + default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground) : NULL; if (default_set_background) xfree (default_set_background); - default_set_background = TS_set_background ? xstrdup (TS_set_background) + default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background) : NULL; - default_max_colors = TN_max_colors; - default_max_pairs = TN_max_pairs; - default_no_color_video = TN_no_color_video; + default_max_colors = tty->TN_max_colors; + default_max_pairs = tty->TN_max_pairs; + default_no_color_video = tty->TN_no_color_video; } else { - TS_orig_pair = default_orig_pair; - TS_set_foreground = default_set_foreground; - TS_set_background = default_set_background; - TN_max_colors = default_max_colors; - TN_max_pairs = default_max_pairs; - TN_no_color_video = default_no_color_video; + tty->TS_orig_pair = default_orig_pair; + tty->TS_set_foreground = default_set_foreground; + tty->TS_set_background = default_set_background; + tty->TN_max_colors = default_max_colors; + tty->TN_max_pairs = default_max_pairs; + tty->TN_no_color_video = default_no_color_video; } } @@ -2063,8 +1994,7 @@ support; zero means set up for the default capabilities, the ones we saw at term_init time; -1 means turn off color support. */ void -tty_setup_colors (mode) - int mode; +tty_setup_colors (struct tty_output *tty, int mode) { /* Canonicalize all negative values of MODE. */ if (mode < -1) @@ -2073,27 +2003,27 @@ switch (mode) { case -1: /* no colors at all */ - TN_max_colors = 0; - TN_max_pairs = 0; - TN_no_color_video = 0; - TS_set_foreground = TS_set_background = TS_orig_pair = NULL; + tty->TN_max_colors = 0; + tty->TN_max_pairs = 0; + tty->TN_no_color_video = 0; + tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL; break; case 0: /* default colors, if any */ default: - tty_default_color_capabilities (0); + tty_default_color_capabilities (tty, 0); break; case 8: /* 8 standard ANSI colors */ - TS_orig_pair = "\033[0m"; + tty->TS_orig_pair = "\033[0m"; #ifdef TERMINFO - TS_set_foreground = "\033[3%p1%dm"; - TS_set_background = "\033[4%p1%dm"; + tty->TS_set_foreground = "\033[3%p1%dm"; + tty->TS_set_background = "\033[4%p1%dm"; #else - TS_set_foreground = "\033[3%dm"; - TS_set_background = "\033[4%dm"; + tty->TS_set_foreground = "\033[3%dm"; + tty->TS_set_background = "\033[4%dm"; #endif - TN_max_colors = 8; - TN_max_pairs = 64; - TN_no_color_video = 0; + tty->TN_max_colors = 8; + tty->TN_max_pairs = 64; + tty->TN_no_color_video = 0; break; } } @@ -2144,7 +2074,7 @@ if (mode != old_mode) { - tty_setup_colors (mode); + tty_setup_colors (FRAME_TTY (f), mode); /* This recomputes all the faces given the new color definitions. */ call0 (intern ("tty-set-up-initial-frame-faces")); @@ -2155,12 +2085,46 @@ #endif /* !WINDOWSNT */ + +struct tty_output * +get_named_tty (name) + char *name; +{ + struct tty_output *tty = tty_list; + + while (tty) { + if ((tty->name == 0 && name == 0) + || (name && tty->name && !strcmp (tty->name, name))) + return tty; + tty = tty->next; + }; + + return 0; +} + + /*********************************************************************** Initialization ***********************************************************************/ -void -term_init (terminal_type) +struct tty_output * +term_dummy_init (void) +{ + if (initialized || tty_list) + error ("tty already initialized"); + + tty_list = xmalloc (sizeof (struct tty_output)); + bzero (tty_list, sizeof (struct tty_output)); + TTY_NAME (tty_list) = 0; + TTY_INPUT (tty_list) = stdin; + TTY_OUTPUT (tty_list) = stdout; + return tty_list; +} + + +struct tty_output * +term_init (name, terminal_type) + char *name; char *terminal_type; { char *area; @@ -2171,10 +2135,63 @@ int status; struct frame *sf = XFRAME (selected_frame); + struct tty_output *tty; + + tty = get_named_tty (name); + if (tty) + { + /* Return the previously initialized terminal, except if it is the dummy + terminal created for the initial frame. */ + if (tty->type) + return tty; + + /* In the latter case, initialize top_frame to the current terminal. */ + tty->top_frame = selected_frame; + } + else + { + tty = (struct tty_output *) xmalloc (sizeof (struct tty_output)); + bzero (tty, sizeof (struct tty_output)); + tty->next = tty_list; + tty_list = tty; + } + + if (tty->Wcm) + Wcm_clear (tty); + else + tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm)); + + if (name) + { + int fd; + FILE *f; + fd = emacs_open (name, O_RDWR, 0); + if (fd < 0) + { + tty_list = tty->next; + xfree (tty); + error ("Could not open file: %s", name); + } + f = fdopen (fd, "w+"); + TTY_NAME (tty) = xstrdup (name); + TTY_INPUT (tty) = f; + TTY_OUTPUT (tty) = f; + } + else + { + TTY_NAME (tty) = 0; + TTY_INPUT (tty) = stdin; + TTY_OUTPUT (tty) = stdout; + } + + TTY_TYPE (tty) = xstrdup (terminal_type); + + init_sys_modes (tty); + #ifdef WINDOWSNT initialize_w32_display (); - Wcm_clear (); + Wcm_clear (tty); area = (char *) xmalloc (2044); @@ -2185,15 +2202,15 @@ delete_in_insert_mode = 1; UseTabs = 0; - scroll_region_ok = 0; + TTY_SCROLL_REGION_OK (tty) = 0; /* Seems to insert lines when it's not supposed to, messing up the display. In doing a trace, it didn't seem to be called much, so I don't think we're losing anything by turning it off. */ - - line_ins_del_ok = 0; - char_ins_del_ok = 1; + TTY_LINE_INS_DEL_OK (tty) = 0; + + TTY_CHAR_INS_DEL_OK (tty) = 1; baud_rate = 19200; @@ -2201,37 +2218,61 @@ FRAME_VERTICAL_SCROLL_BAR_TYPE (sf) = vertical_scroll_bar_none; TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */ - return; + return tty; #else /* not WINDOWSNT */ - Wcm_clear (); + Wcm_clear (tty); buffer = (char *) xmalloc (buffer_size); status = tgetent (buffer, terminal_type); if (status < 0) { #ifdef TERMINFO - fatal ("Cannot open terminfo database file"); + if (name) + { + delete_tty (tty); + error ("Cannot open terminfo database file"); + } + else + fatal ("Cannot open terminfo database file"); #else - fatal ("Cannot open termcap database file"); + if (name) + { + delete_tty (tty); + error ("Cannot open termcap database file"); + } + else + fatal ("Cannot open termcap database file"); #endif } if (status == 0) { #ifdef TERMINFO - fatal ("Terminal type %s is not defined.\n\ -If that is not the actual type of terminal you have,\n\ + if (name) + { + delete_tty (tty); + error ("Terminal type %s is not defined", terminal_type); + } + else + fatal ("Terminal type %s is not defined.\n\ +If that is not the actual type of terminal you have,\n \ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", - terminal_type); + terminal_type); #else - fatal ("Terminal type %s is not defined.\n\ -If that is not the actual type of terminal you have,\n\ + if (name) + { + delete_tty (tty); + error ("Terminal type %s is not defined", terminal_type); + } + else + fatal ("Terminal type %s is not defined.\n\ +If that is not the actual type of terminal you have,\n \ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", - terminal_type); + terminal_type); #endif } @@ -2242,125 +2283,125 @@ #endif area = (char *) xmalloc (buffer_size); - TS_ins_line = tgetstr ("al", address); - TS_ins_multi_lines = tgetstr ("AL", address); - TS_bell = tgetstr ("bl", address); - BackTab = tgetstr ("bt", address); - TS_clr_to_bottom = tgetstr ("cd", address); - TS_clr_line = tgetstr ("ce", address); - TS_clr_frame = tgetstr ("cl", address); - ColPosition = NULL; /* tgetstr ("ch", address); */ - AbsPosition = tgetstr ("cm", address); - CR = tgetstr ("cr", address); - TS_set_scroll_region = tgetstr ("cs", address); - TS_set_scroll_region_1 = tgetstr ("cS", address); - RowPosition = tgetstr ("cv", address); - TS_del_char = tgetstr ("dc", address); - TS_del_multi_chars = tgetstr ("DC", address); - TS_del_line = tgetstr ("dl", address); - TS_del_multi_lines = tgetstr ("DL", address); - TS_delete_mode = tgetstr ("dm", address); - TS_end_delete_mode = tgetstr ("ed", address); - TS_end_insert_mode = tgetstr ("ei", address); - Home = tgetstr ("ho", address); - TS_ins_char = tgetstr ("ic", address); - TS_ins_multi_chars = tgetstr ("IC", address); - TS_insert_mode = tgetstr ("im", address); - TS_pad_inserted_char = tgetstr ("ip", address); - TS_end_keypad_mode = tgetstr ("ke", address); - TS_keypad_mode = tgetstr ("ks", address); - LastLine = tgetstr ("ll", address); - Right = tgetstr ("nd", address); - Down = tgetstr ("do", address); - if (!Down) - Down = tgetstr ("nl", address); /* Obsolete name for "do" */ + tty->TS_ins_line = tgetstr ("al", address); + tty->TS_ins_multi_lines = tgetstr ("AL", address); + tty->TS_bell = tgetstr ("bl", address); + BackTab (tty) = tgetstr ("bt", address); + tty->TS_clr_to_bottom = tgetstr ("cd", address); + tty->TS_clr_line = tgetstr ("ce", address); + tty->TS_clr_frame = tgetstr ("cl", address); + ColPosition (tty) = NULL; /* tgetstr ("ch", address); */ + AbsPosition (tty) = tgetstr ("cm", address); + CR (tty) = tgetstr ("cr", address); + tty->TS_set_scroll_region = tgetstr ("cs", address); + tty->TS_set_scroll_region_1 = tgetstr ("cS", address); + RowPosition (tty) = tgetstr ("cv", address); + tty->TS_del_char = tgetstr ("dc", address); + tty->TS_del_multi_chars = tgetstr ("DC", address); + tty->TS_del_line = tgetstr ("dl", address); + tty->TS_del_multi_lines = tgetstr ("DL", address); + tty->TS_delete_mode = tgetstr ("dm", address); + tty->TS_end_delete_mode = tgetstr ("ed", address); + tty->TS_end_insert_mode = tgetstr ("ei", address); + Home (tty) = tgetstr ("ho", address); + tty->TS_ins_char = tgetstr ("ic", address); + tty->TS_ins_multi_chars = tgetstr ("IC", address); + tty->TS_insert_mode = tgetstr ("im", address); + tty->TS_pad_inserted_char = tgetstr ("ip", address); + tty->TS_end_keypad_mode = tgetstr ("ke", address); + tty->TS_keypad_mode = tgetstr ("ks", address); + LastLine (tty) = tgetstr ("ll", address); + Right (tty) = tgetstr ("nd", address); + Down (tty) = tgetstr ("do", address); + if (!Down (tty)) + Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */ #ifdef VMS /* VMS puts a carriage return before each linefeed, so it is not safe to use linefeeds. */ - if (Down && Down[0] == '\n' && Down[1] == '\0') - Down = 0; + if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0') + Down (tty) = 0; #endif /* VMS */ if (tgetflag ("bs")) - Left = "\b"; /* can't possibly be longer! */ + Left (tty) = "\b"; /* can't possibly be longer! */ else /* (Actually, "bs" is obsolete...) */ - Left = tgetstr ("le", address); - if (!Left) - Left = tgetstr ("bc", address); /* Obsolete name for "le" */ - TS_pad_char = tgetstr ("pc", address); - TS_repeat = tgetstr ("rp", address); - TS_end_standout_mode = tgetstr ("se", address); - TS_fwd_scroll = tgetstr ("sf", address); - TS_standout_mode = tgetstr ("so", address); - TS_rev_scroll = tgetstr ("sr", address); - Wcm.cm_tab = tgetstr ("ta", address); - TS_end_termcap_modes = tgetstr ("te", address); - TS_termcap_modes = tgetstr ("ti", address); - Up = tgetstr ("up", address); - TS_visible_bell = tgetstr ("vb", address); - TS_cursor_normal = tgetstr ("ve", address); - TS_cursor_visible = tgetstr ("vs", address); - TS_cursor_invisible = tgetstr ("vi", address); - TS_set_window = tgetstr ("wi", address); - - TS_enter_underline_mode = tgetstr ("us", address); - TS_exit_underline_mode = tgetstr ("ue", address); - TS_enter_bold_mode = tgetstr ("md", address); - TS_enter_dim_mode = tgetstr ("mh", address); - TS_enter_blink_mode = tgetstr ("mb", address); - TS_enter_reverse_mode = tgetstr ("mr", address); - TS_enter_alt_charset_mode = tgetstr ("as", address); - TS_exit_alt_charset_mode = tgetstr ("ae", address); - TS_exit_attribute_mode = tgetstr ("me", address); - - MultiUp = tgetstr ("UP", address); - MultiDown = tgetstr ("DO", address); - MultiLeft = tgetstr ("LE", address); - MultiRight = tgetstr ("RI", address); + Left (tty) = tgetstr ("le", address); + if (!Left (tty)) + Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */ + tty->TS_pad_char = tgetstr ("pc", address); + tty->TS_repeat = tgetstr ("rp", address); + tty->TS_end_standout_mode = tgetstr ("se", address); + tty->TS_fwd_scroll = tgetstr ("sf", address); + tty->TS_standout_mode = tgetstr ("so", address); + tty->TS_rev_scroll = tgetstr ("sr", address); + tty->Wcm->cm_tab = tgetstr ("ta", address); + tty->TS_end_termcap_modes = tgetstr ("te", address); + tty->TS_termcap_modes = tgetstr ("ti", address); + Up (tty) = tgetstr ("up", address); + tty->TS_visible_bell = tgetstr ("vb", address); + tty->TS_cursor_normal = tgetstr ("ve", address); + tty->TS_cursor_visible = tgetstr ("vs", address); + tty->TS_cursor_invisible = tgetstr ("vi", address); + tty->TS_set_window = tgetstr ("wi", address); + + tty->TS_enter_underline_mode = tgetstr ("us", address); + tty->TS_exit_underline_mode = tgetstr ("ue", address); + tty->TS_enter_bold_mode = tgetstr ("md", address); + tty->TS_enter_dim_mode = tgetstr ("mh", address); + tty->TS_enter_blink_mode = tgetstr ("mb", address); + tty->TS_enter_reverse_mode = tgetstr ("mr", address); + tty->TS_enter_alt_charset_mode = tgetstr ("as", address); + tty->TS_exit_alt_charset_mode = tgetstr ("ae", address); + tty->TS_exit_attribute_mode = tgetstr ("me", address); + + MultiUp (tty) = tgetstr ("UP", address); + MultiDown (tty) = tgetstr ("DO", address); + MultiLeft (tty) = tgetstr ("LE", address); + MultiRight (tty) = tgetstr ("RI", address); /* SVr4/ANSI color suppert. If "op" isn't available, don't support color because we can't switch back to the default foreground and background. */ - TS_orig_pair = tgetstr ("op", address); - if (TS_orig_pair) + tty->TS_orig_pair = tgetstr ("op", address); + if (tty->TS_orig_pair) { - TS_set_foreground = tgetstr ("AF", address); - TS_set_background = tgetstr ("AB", address); - if (!TS_set_foreground) + tty->TS_set_foreground = tgetstr ("AF", address); + tty->TS_set_background = tgetstr ("AB", address); + if (!tty->TS_set_foreground) { /* SVr4. */ - TS_set_foreground = tgetstr ("Sf", address); - TS_set_background = tgetstr ("Sb", address); + tty->TS_set_foreground = tgetstr ("Sf", address); + tty->TS_set_background = tgetstr ("Sb", address); } - TN_max_colors = tgetnum ("Co"); - TN_max_pairs = tgetnum ("pa"); - - TN_no_color_video = tgetnum ("NC"); - if (TN_no_color_video == -1) - TN_no_color_video = 0; + tty->TN_max_colors = tgetnum ("Co"); + tty->TN_max_pairs = tgetnum ("pa"); + + tty->TN_no_color_video = tgetnum ("NC"); + if (tty->TN_no_color_video == -1) + tty->TN_no_color_video = 0; } - tty_default_color_capabilities (1); - - MagicWrap = tgetflag ("xn"); + tty_default_color_capabilities (tty, 1); + + MagicWrap (tty) = tgetflag ("xn"); /* Since we make MagicWrap terminals look like AutoWrap, we need to have the former flag imply the latter. */ - AutoWrap = MagicWrap || tgetflag ("am"); - memory_below_frame = tgetflag ("db"); - TF_hazeltine = tgetflag ("hz"); - must_write_spaces = tgetflag ("in"); - meta_key = tgetflag ("km") || tgetflag ("MT"); - TF_insmode_motion = tgetflag ("mi"); - TF_standout_motion = tgetflag ("ms"); - TF_underscore = tgetflag ("ul"); - TF_teleray = tgetflag ("xt"); + AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am"); + TTY_MEMORY_BELOW_FRAME (tty) = tgetflag ("db"); + tty->TF_hazeltine = tgetflag ("hz"); + TTY_MUST_WRITE_SPACES (tty) = tgetflag ("in"); + tty->meta_key = tgetflag ("km") || tgetflag ("MT"); + tty->TF_insmode_motion = tgetflag ("mi"); + tty->TF_standout_motion = tgetflag ("ms"); + tty->TF_underscore = tgetflag ("ul"); + tty->TF_teleray = tgetflag ("xt"); term_get_fkeys (address); /* Get frame size from system, or else from termcap. */ { int height, width; - get_frame_size (&width, &height); + get_tty_size (tty, &width, &height); FRAME_COLS (sf) = width; FRAME_LINES (sf) = height; } @@ -2375,86 +2416,89 @@ if (FRAME_LINES (sf) < 3 || FRAME_COLS (sf) < 3) fatal ("Screen size %dx%d is too small", - FRAME_LINES (sf), FRAME_COLS (sf)); - - min_padding_speed = tgetnum ("pb"); - TabWidth = tgetnum ("tw"); + FRAME_LINES (sf), FRAME_COLS (sf)); + +#if 0 /* This is not used anywhere. */ + TTY_MIN_PADDING_SPEED (tty) = tgetnum ("pb"); +#endif + + TabWidth (tty) = tgetnum ("tw"); #ifdef VMS /* These capabilities commonly use ^J. I don't know why, but sending them on VMS does not work; it causes following spaces to be lost, sometimes. For now, the simplest fix is to avoid using these capabilities ever. */ - if (Down && Down[0] == '\n') - Down = 0; + if (Down (tty) && Down (tty)[0] == '\n') + Down (tty) = 0; #endif /* VMS */ - if (!TS_bell) - TS_bell = "\07"; - - if (!TS_fwd_scroll) - TS_fwd_scroll = Down; - - PC = TS_pad_char ? *TS_pad_char : 0; - - if (TabWidth < 0) - TabWidth = 8; + if (!tty->TS_bell) + tty->TS_bell = "\07"; + + if (!tty->TS_fwd_scroll) + tty->TS_fwd_scroll = Down (tty); + + PC = tty->TS_pad_char ? *tty->TS_pad_char : 0; + + if (TabWidth (tty) < 0) + TabWidth (tty) = 8; /* Turned off since /etc/termcap seems to have :ta= for most terminals and newer termcap doc does not seem to say there is a default. - if (!Wcm.cm_tab) - Wcm.cm_tab = "\t"; + if (!tty->Wcm->cm_tab) + tty->Wcm->cm_tab = "\t"; */ /* We don't support standout modes that use `magic cookies', so turn off any that do. */ - if (TS_standout_mode && tgetnum ("sg") >= 0) + if (tty->TS_standout_mode && tgetnum ("sg") >= 0) { - TS_standout_mode = 0; - TS_end_standout_mode = 0; + tty->TS_standout_mode = 0; + tty->TS_end_standout_mode = 0; } - if (TS_enter_underline_mode && tgetnum ("ug") >= 0) + if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0) { - TS_enter_underline_mode = 0; - TS_exit_underline_mode = 0; + tty->TS_enter_underline_mode = 0; + tty->TS_exit_underline_mode = 0; } /* If there's no standout mode, try to use underlining instead. */ - if (TS_standout_mode == 0) + if (tty->TS_standout_mode == 0) { - TS_standout_mode = TS_enter_underline_mode; - TS_end_standout_mode = TS_exit_underline_mode; + tty->TS_standout_mode = tty->TS_enter_underline_mode; + tty->TS_end_standout_mode = tty->TS_exit_underline_mode; } /* If no `se' string, try using a `me' string instead. If that fails, we can't use standout mode at all. */ - if (TS_end_standout_mode == 0) + if (tty->TS_end_standout_mode == 0) { char *s = tgetstr ("me", address); if (s != 0) - TS_end_standout_mode = s; + tty->TS_end_standout_mode = s; else - TS_standout_mode = 0; + tty->TS_standout_mode = 0; } - if (TF_teleray) + if (tty->TF_teleray) { - Wcm.cm_tab = 0; + tty->Wcm->cm_tab = 0; /* We can't support standout mode, because it uses magic cookies. */ - TS_standout_mode = 0; + tty->TS_standout_mode = 0; /* But that means we cannot rely on ^M to go to column zero! */ - CR = 0; + CR (tty) = 0; /* LF can't be trusted either -- can alter hpos */ /* if move at column 0 thru a line with TS_standout_mode */ - Down = 0; + Down (tty) = 0; } /* Special handling for certain terminal types known to need it */ if (!strcmp (terminal_type, "supdup")) { - memory_below_frame = 1; - Wcm.cm_losewrap = 1; + TTY_MEMORY_BELOW_FRAME (tty) = 1; + tty->Wcm->cm_losewrap = 1; } if (!strncmp (terminal_type, "c10", 3) || !strcmp (terminal_type, "perq")) @@ -2463,7 +2507,7 @@ This string is not valid in general since it works only for windows starting at the upper left corner; but that is all Emacs uses. - + This string works only if the frame is using the top of the video memory, because addressing is memory-relative. So first check the :ti string to see if that is true. @@ -2471,95 +2515,114 @@ It would be simpler if the :wi string could go in the termcap entry, but it can't because it is not fully valid. If it were in the termcap entry, it would confuse other programs. */ - if (!TS_set_window) + if (!tty->TS_set_window) { - p = TS_termcap_modes; + p = tty->TS_termcap_modes; while (*p && strcmp (p, "\033v ")) p++; if (*p) - TS_set_window = "\033v%C %C %C %C "; + tty->TS_set_window = "\033v%C %C %C %C "; } /* Termcap entry often fails to have :in: flag */ - must_write_spaces = 1; + TTY_MUST_WRITE_SPACES (tty) = 1; /* :ti string typically fails to have \E^G! in it */ /* This limits scope of insert-char to one line. */ - strcpy (area, TS_termcap_modes); + strcpy (area, tty->TS_termcap_modes); strcat (area, "\033\007!"); - TS_termcap_modes = area; + tty->TS_termcap_modes = area; area += strlen (area) + 1; - p = AbsPosition; + p = AbsPosition (tty); /* Change all %+ parameters to %C, to handle - values above 96 correctly for the C100. */ + values above 96 correctly for the C100. */ while (*p) - { - if (p[0] == '%' && p[1] == '+') - p[1] = 'C'; - p++; - } + { + if (p[0] == '%' && p[1] == '+') + p[1] = 'C'; + p++; + } } - FrameRows = FRAME_LINES (sf); - FrameCols = FRAME_COLS (sf); - specified_window = FRAME_LINES (sf); - - if (Wcm_init () == -1) /* can't do cursor motion */ + FrameRows (tty) = FRAME_LINES (sf); + FrameCols (tty) = FRAME_COLS (sf); + tty->specified_window = FRAME_LINES (sf); + + if (Wcm_init (tty) == -1) /* can't do cursor motion */ + if (name) + { + delete_tty (tty); + error ("Terminal type \"%s\" is not powerful enough to run Emacs"); + } + else { #ifdef VMS - fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ + fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ It lacks the ability to position the cursor.\n\ If that is not the actual type of terminal you have, use either the\n\ DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\ or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.", - terminal_type); + terminal_type); #else /* not VMS */ # ifdef TERMINFO - fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ -It lacks the ability to position the cursor.\n\ -If that is not the actual type of terminal you have,\n\ + fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ +It lacks the ability to position the cursor.\n \ +If that is not the actual type of terminal you have,\n \ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.", - terminal_type); + terminal_type); # else /* TERMCAP */ - fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ -It lacks the ability to position the cursor.\n\ + fatal ("Terminal type \"%s\" is not powerful enough to run Emacs.\n\ +It lacks the ability to position the cursor.\n \ If that is not the actual type of terminal you have,\n\ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\ `setenv TERM ...') to specify the correct type. It may be necessary\n\ to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.", - terminal_type); + terminal_type); # endif /* TERMINFO */ #endif /*VMS */ + } + if (FRAME_LINES (sf) <= 0 || FRAME_COLS (sf) <= 0) - fatal ("The frame size has not been specified"); - - delete_in_insert_mode - = TS_delete_mode && TS_insert_mode - && !strcmp (TS_delete_mode, TS_insert_mode); - - se_is_so = (TS_standout_mode - && TS_end_standout_mode - && !strcmp (TS_standout_mode, TS_end_standout_mode)); - - UseTabs = tabs_safe_p () && TabWidth == 8; - - scroll_region_ok - = (Wcm.cm_abs - && (TS_set_window || TS_set_scroll_region || TS_set_scroll_region_1)); - - line_ins_del_ok = (((TS_ins_line || TS_ins_multi_lines) - && (TS_del_line || TS_del_multi_lines)) - || (scroll_region_ok && TS_fwd_scroll && TS_rev_scroll)); - - char_ins_del_ok = ((TS_ins_char || TS_insert_mode - || TS_pad_inserted_char || TS_ins_multi_chars) - && (TS_del_char || TS_del_multi_chars)); - - fast_clear_end_of_line = TS_clr_line != 0; + { + if (name) + { + delete_tty (tty); + error ("The frame size has not been specified"); + } + else + fatal ("The frame size has not been specified"); + } + + tty->delete_in_insert_mode + = tty->TS_delete_mode && tty->TS_insert_mode + && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode); + + tty->se_is_so = (tty->TS_standout_mode + && tty->TS_end_standout_mode + && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode)); + + UseTabs (tty) = tabs_safe_p (tty) && TabWidth (tty) == 8; + + TTY_SCROLL_REGION_OK (tty) + = (tty->Wcm->cm_abs + && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1)); + + TTY_LINE_INS_DEL_OK (tty) + = (((tty->TS_ins_line || tty->TS_ins_multi_lines) + && (tty->TS_del_line || tty->TS_del_multi_lines)) + || (TTY_SCROLL_REGION_OK (tty) + && tty->TS_fwd_scroll && tty->TS_rev_scroll)); + + TTY_CHAR_INS_DEL_OK (tty) + = ((tty->TS_ins_char || tty->TS_insert_mode + || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars) + && (tty->TS_del_char || tty->TS_del_multi_chars)); + + TTY_FAST_CLEAR_END_OF_LINE (tty) = tty->TS_clr_line != 0; init_baud_rate (); - if (read_socket_hook) /* Baudrate is somewhat */ - /* meaningless in this case */ + if (read_socket_hook) /* Baudrate is somewhat + meaningless in this case */ baud_rate = 9600; FRAME_CAN_HAVE_SCROLL_BARS (sf) = 0; @@ -2567,6 +2630,10 @@ #endif /* WINDOWSNT */ xfree (buffer); + + tty_set_terminal_modes (tty); + + return tty; } /* VARARGS 1 */ @@ -2600,7 +2667,97 @@ defsubr (&Stty_display_color_p); defsubr (&Stty_display_color_cells); + + Fprovide (intern ("multi-tty"), Qnil); } +void +delete_tty (struct tty_output *tty) +{ + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_LIVE_P (f) && FRAME_TTY (f) == tty) + { + Fdelete_frame (frame, Qt); + f->output_data.tty = 0; + } + } + + /* Close the terminal and free memory. */ + delete_tty_1 (tty); +} + +static void +delete_tty_1 (struct tty_output *tty) +{ + + if (tty == tty_list) + tty_list = tty->next; + else + { + struct tty_output *p; + for (p = tty_list; p && p->next != tty; p = p->next) + ; + + if (! p) + /* This should not happen. */ + abort (); + + p->next = p->next->next; + } + + /* This hangs. */ + /* reset_sys_modes (tty); */ + + if (tty->name) + xfree (tty->name); + if (tty->type) + xfree (tty->type); + if (tty->input) + fclose (tty->input); + if (tty->output) + fclose (tty->output); + if (tty->termscript) + fclose (tty->termscript); + + /* + if (tty->old_tty) + xfree (tty->old_tty); + + if (tty->Wcm) + { + bzero (tty->Wcm, sizeof (struct cm)); + } + xfree (tty->Wcm); + + bzero (tty, sizeof (struct tty_output)); + + xfree (tty); + */ +} + + +struct tty_output * +get_current_tty () +{ + return CURTTY(); +} + +void +print_all_frames () +{ + /* XXX Debug function. */ + Lisp_Object frame, tail; + FOR_EACH_FRAME (tail, frame) + { + fprintf (stderr, "Frame: %x\n", XFRAME (frame)); + fflush (stderr); + } +} + + /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193 (do not change this comment) */
--- a/src/termchar.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/termchar.h Sun Dec 28 16:03:57 2003 +0000 @@ -1,5 +1,5 @@ /* Flags and parameters describing terminal's characteristics. - Copyright (C) 1985, 1986 Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 2003 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -18,32 +18,214 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* Each termcap frame points to its own struct tty_output object in the + output_data.tty field. The tty_output structure contains the information + that is specific to terminals. */ +struct tty_output +{ + char *name; /* The name of the device file or 0 if + stdin/stdout. */ + char *type; /* The type of the tty. */ + + /* Input/output */ + + FILE *input; /* The stream to be used for terminal input. */ + FILE *output; /* The stream to be used for terminal output. */ + + FILE *termscript; /* If nonzero, send all terminal output + characters to this stream also. */ -/* extern EMACS_INT baud_rate; */ /* Output speed in baud */ -extern int must_write_spaces; /* Nonzero means spaces in the text - must actually be output; can't just skip - over some columns to leave them blank. */ -extern int min_padding_speed; /* Speed below which no padding necessary */ -extern int fast_clear_end_of_line; /* Nonzero means terminal has - command for this */ + struct emacs_tty *old_tty; /* The initial tty mode bits */ + + int term_initted; /* 1 if we have been through init_sys_modes. */ + + + /* Structure for info on cursor positioning. */ + + struct cm *Wcm; + + /* Redisplay. */ + + /* XXX GC does not know about this; is this a problem? */ + Lisp_Object top_frame; /* The topmost frame on this tty. */ + + /* The previous terminal frame we displayed on this tty. */ + struct frame *previous_terminal_frame; + + /* Pixel values. + XXX What are these used for? */ + + unsigned long background_pixel; + unsigned long foreground_pixel; + + /* Terminal characteristics. */ + + int must_write_spaces; /* Nonzero means spaces in the text must + actually be output; can't just skip over + some columns to leave them blank. */ + int fast_clear_end_of_line; /* Nonzero means terminal has a `ce' string */ + + int line_ins_del_ok; /* Terminal can insert and delete lines */ + int char_ins_del_ok; /* Terminal can insert and delete chars */ + int scroll_region_ok; /* Terminal supports setting the scroll + window */ + int scroll_region_cost; /* Cost of setting the scroll window, + measured in characters. */ + int memory_below_frame; /* Terminal remembers lines scrolled + off bottom */ + +#if 0 /* These are not used anywhere. */ + /* EMACS_INT baud_rate; */ /* Output speed in baud */ + int min_padding_speed; /* Speed below which no padding necessary. */ + int dont_calculate_costs; /* Nonzero means don't bother computing + various cost tables; we won't use them. */ +#endif + + /* Strings, numbers and flags taken from the termcap entry. */ + + char *TS_ins_line; /* "al" */ + char *TS_ins_multi_lines; /* "AL" (one parameter, # lines to insert) */ + char *TS_bell; /* "bl" */ + char *TS_clr_to_bottom; /* "cd" */ + char *TS_clr_line; /* "ce", clear to end of line */ + char *TS_clr_frame; /* "cl" */ + char *TS_set_scroll_region; /* "cs" (2 params, first line and last line) */ + char *TS_set_scroll_region_1; /* "cS" (4 params: total lines, + lines above scroll region, lines below it, + total lines again) */ + char *TS_del_char; /* "dc" */ + char *TS_del_multi_chars; /* "DC" (one parameter, # chars to delete) */ + char *TS_del_line; /* "dl" */ + char *TS_del_multi_lines; /* "DL" (one parameter, # lines to delete) */ + char *TS_delete_mode; /* "dm", enter character-delete mode */ + char *TS_end_delete_mode; /* "ed", leave character-delete mode */ + char *TS_end_insert_mode; /* "ei", leave character-insert mode */ + char *TS_ins_char; /* "ic" */ + char *TS_ins_multi_chars; /* "IC" (one parameter, # chars to insert) */ + char *TS_insert_mode; /* "im", enter character-insert mode */ + char *TS_pad_inserted_char; /* "ip". Just padding, no commands. */ + char *TS_end_keypad_mode; /* "ke" */ + char *TS_keypad_mode; /* "ks" */ + char *TS_pad_char; /* "pc", char to use as padding */ + char *TS_repeat; /* "rp" (2 params, # times to repeat + and character to be repeated) */ + char *TS_end_standout_mode; /* "se" */ + char *TS_fwd_scroll; /* "sf" */ + char *TS_standout_mode; /* "so" */ + char *TS_rev_scroll; /* "sr" */ + char *TS_end_termcap_modes; /* "te" */ + char *TS_termcap_modes; /* "ti" */ + char *TS_visible_bell; /* "vb" */ + char *TS_cursor_normal; /* "ve" */ + char *TS_cursor_visible; /* "vs" */ + char *TS_cursor_invisible; /* "vi" */ + char *TS_set_window; /* "wi" (4 params, start and end of window, + each as vpos and hpos) */ -extern int line_ins_del_ok; /* Terminal can insert and delete lines */ -extern int char_ins_del_ok; /* Terminal can insert and delete chars */ -extern int scroll_region_ok; /* Terminal supports setting the scroll - window */ -extern int scroll_region_cost; /* Cost of setting the scroll window, - measured in characters */ -extern int memory_below_frame; /* Terminal remembers lines scrolled - off bottom */ -extern int fast_clear_end_of_line; /* Terminal has a `ce' string */ + char *TS_enter_bold_mode; /* "md" -- turn on bold (extra bright mode). */ + char *TS_enter_dim_mode; /* "mh" -- turn on half-bright mode. */ + char *TS_enter_blink_mode; /* "mb" -- enter blinking mode. */ + char *TS_enter_reverse_mode; /* "mr" -- enter reverse video mode. */ + char *TS_exit_underline_mode; /* "us" -- start underlining. */ + char *TS_enter_underline_mode; /* "ue" -- end underlining. */ + + /* "as"/"ae" -- start/end alternate character set. Not really + supported, yet. */ + char *TS_enter_alt_charset_mode; + char *TS_exit_alt_charset_mode; + + char *TS_exit_attribute_mode; /* "me" -- switch appearances off. */ + + /* Value of the "NC" (no_color_video) capability, or 0 if not present. */ + int TN_no_color_video; + + int TN_max_colors; /* "Co" -- number of colors. */ + + /* "pa" -- max. number of color pairs on screen. Not handled yet. + Could be a problem if not equal to TN_max_colors * TN_max_colors. */ + int TN_max_pairs; + + /* "op" -- SVr4 set default pair to its original value. */ + char *TS_orig_pair; + + /* "AF"/"AB" or "Sf"/"Sb"-- set ANSI or SVr4 foreground/background color. + 1 param, the color index. */ + char *TS_set_foreground; + char *TS_set_background; + + int TF_hazeltine; /* termcap hz flag. */ + int TF_insmode_motion; /* termcap mi flag: can move while in insert mode. */ + int TF_standout_motion; /* termcap mi flag: can move while in standout mode. */ + int TF_underscore; /* termcap ul flag: _ underlines if over-struck on + non-blank position. Must clear before writing _. */ + int TF_teleray; /* termcap xt flag: many weird consequences. + For t1061. */ + + int RPov; /* # chars to start a TS_repeat */ + + int delete_in_insert_mode; /* delete mode == insert mode */ + + int se_is_so; /* 1 if same string both enters and leaves + standout mode */ + + int costs_set; /* Nonzero if costs have been calculated. */ + + int insert_mode; /* Nonzero when in insert mode. */ + int standout_mode; /* Nonzero when in standout mode. */ + -extern int dont_calculate_costs; /* Nonzero means don't bother computing - various cost tables; we won't use them. */ + + /* 1 if should obey 0200 bit in input chars as "Meta", 2 if should + keep 0200 bit in input chars. 0 to ignore the 0200 bit. */ + + int meta_key; + + /* Size of window specified by higher levels. + This is the number of lines, from the top of frame downwards, + which can participate in insert-line/delete-line operations. + + Effectively it excludes the bottom frame_lines - specified_window_size + lines from those operations. */ + + int specified_window; + + /* Flag used in tty_show/hide_cursor. */ + + int cursor_hidden; + + + struct tty_output *next; +}; + +extern struct tty_output *tty_list; + -/* Nonzero means no need to redraw the entire frame on resuming - a suspended Emacs. This is useful on terminals with multiple pages, - where one page is used for Emacs and another for all else. */ -extern int no_redraw_on_reenter; +#define FRAME_TTY(f) \ + ((f)->output_method == output_termcap \ + ? (f)->output_data.tty : (abort(), (struct tty_output *) 0)) + +#define CURTTY() FRAME_TTY (SELECTED_FRAME()) + +#define TTY_NAME(t) ((t)->name) +#define TTY_TYPE(t) ((t)->type) + +#define TTY_INPUT(t) ((t)->input) +#define TTY_OUTPUT(t) ((t)->output) +#define TTY_TERMSCRIPT(t) ((t)->termscript) + +#define TTY_MUST_WRITE_SPACES(t) ((t)->must_write_spaces) +#define TTY_FAST_CLEAR_END_OF_LINE(t) ((t)->fast_clear_end_of_line) +#define TTY_LINE_INS_DEL_OK(t) ((t)->line_ins_del_ok) +#define TTY_CHAR_INS_DEL_OK(t) ((t)->char_ins_del_ok) +#define TTY_SCROLL_REGION_OK(t) ((t)->scroll_region_ok) +#define TTY_SCROLL_REGION_COST(t) ((t)->scroll_region_cost) +#define TTY_MEMORY_BELOW_FRAME(t) ((t)->memory_below_frame) + +#if 0 +/* These are not used anywhere. */ +#define TTY_MIN_PADDING_SPEED(t) ((t)->min_padding_speed) +#define TTY_DONT_CALCULATE_COSTS(t) ((t)->dont_calculate_costs) +#endif /* arch-tag: bf9f0d49-842b-42fb-9348-ec8759b27193 (do not change this comment) */
--- a/src/termhooks.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/termhooks.h Sun Dec 28 16:03:57 2003 +0000 @@ -25,9 +25,6 @@ struct glyph; struct frame; -/* If nonzero, send all terminal output characters to this stream also. */ -extern FILE *termscript; - /* Only use prototypes when lisp.h has been included. */ #ifndef P_ #define P_(X) () @@ -374,7 +371,7 @@ #define EVENT_INIT(event) bzero (&(event), sizeof (struct input_event)) /* Called to read input events. */ -extern int (*read_socket_hook) P_ ((int, struct input_event *, int, int)); +extern int (*read_socket_hook) P_ ((struct input_event *, int, int)); /* Called when a frame's display becomes entirely up to date. */ extern void (*frame_up_to_date_hook) P_ ((struct frame *));
--- a/src/termopts.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/termopts.h Sun Dec 28 16:03:57 2003 +0000 @@ -40,5 +40,10 @@ /* Nonzero means truncate lines in all windows less wide than the frame */ extern int truncate_partial_width_windows; +/* Nonzero means no need to redraw the entire frame on resuming a suspended + Emacs. This is useful on terminals with multiple pages, where one page is + used for Emacs and another for all else. */ +extern int no_redraw_on_reenter; + /* arch-tag: 35d4d284-dc1a-4fff-97fa-0154a21aebdb (do not change this comment) */
--- a/src/w32inevt.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/w32inevt.c Sun Dec 28 16:03:57 2003 +0000 @@ -642,7 +642,7 @@ } int -w32_console_read_socket (int sd, struct input_event *bufp, int numchars, +w32_console_read_socket (struct input_event *bufp, int numchars, int expected) { BOOL no_events = TRUE;
--- a/src/w32term.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/w32term.c Sun Dec 28 16:03:57 2003 +0000 @@ -4078,8 +4078,7 @@ */ int -w32_read_socket (sd, bufp, numchars, expected) - register int sd; +w32_read_socket (bufp, numchars, expected) /* register */ struct input_event *bufp; /* register */ int numchars; int expected; @@ -6366,12 +6365,13 @@ redeem_scroll_bar_hook = w32_redeem_scroll_bar; judge_scroll_bars_hook = w32_judge_scroll_bars; - scroll_region_ok = 1; /* we'll scroll partial frames */ - char_ins_del_ok = 1; - line_ins_del_ok = 1; /* we'll just blt 'em */ - fast_clear_end_of_line = 1; /* X does this well */ - memory_below_frame = 0; /* we don't remember what scrolls - off the bottom */ + TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */ + TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1; + TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */ + TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */ + TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what + scrolls off the + bottom */ baud_rate = 19200; w32_system_caret_hwnd = NULL;
--- a/src/w32term.h Wed Dec 24 23:32:12 2003 +0000 +++ b/src/w32term.h Sun Dec 28 16:03:57 2003 +0000 @@ -389,8 +389,6 @@ #define FRAME_W32_WINDOW(f) ((f)->output_data.w32->window_desc) #define FRAME_X_WINDOW(f) ((f)->output_data.w32->window_desc) -#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel) -#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel) #define FRAME_FONT(f) ((f)->output_data.w32->font) #define FRAME_FONTSET(f) ((f)->output_data.w32->fontset) #define FRAME_BASELINE_OFFSET(f) ((f)->output_data.w32->baseline_offset)
--- a/src/window.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/window.c Sun Dec 28 16:03:57 2003 +0000 @@ -29,6 +29,7 @@ #include "window.h" #include "commands.h" #include "indent.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "disptab.h" #include "dispextern.h" @@ -6381,9 +6382,8 @@ void init_window_once () { - struct frame *f = make_terminal_frame (); + struct frame *f = make_terminal_frame (0, 0); XSETFRAME (selected_frame, f); - Vterminal_frame = selected_frame; minibuf_window = f->minibuffer_window; selected_window = f->selected_window; last_nonminibuf_frame = f;
--- a/src/xdisp.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/xdisp.c Sun Dec 28 16:03:57 2003 +0000 @@ -173,6 +173,7 @@ #include "keyboard.h" #include "frame.h" #include "window.h" +#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #include "dispextern.h" #include "buffer.h" @@ -735,10 +736,6 @@ #define CLEAR_FACE_CACHE_COUNT 500 static int clear_face_cache_count; -/* Record the previous terminal frame we displayed. */ - -static struct frame *previous_terminal_frame; - /* Non-zero while redisplay_internal is in progress. */ int redisplaying_p; @@ -2011,7 +2008,7 @@ /* If realized faces have been removed, e.g. because of face attribute changes of named faces, recompute them. When running - in batch mode, the face cache of Vterminal_frame is null. If + in batch mode, the face cache of the initial frame is null. If we happen to get called, make a dummy face cache. */ if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL) init_frame_faces (it->f); @@ -7558,11 +7555,11 @@ { Lisp_Object tail, frame; int changed_count = 0; - + FOR_EACH_FRAME (tail, frame) { struct frame *f = XFRAME (frame); - + if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f)) { if (f->resized_p) @@ -7573,7 +7570,7 @@ f->resized_p = 0; } } - + frame_garbaged = 0; if (changed_count) ++windows_or_buffers_changed; @@ -7609,7 +7606,7 @@ /* When Emacs starts, selected_frame may be a visible terminal frame, even if we run under a window system. If we let this through, a message would be displayed on the terminal. */ - if (EQ (selected_frame, Vterminal_frame) + if (!FRAME_WINDOW_P (XFRAME (selected_frame)) && !NILP (Vwindow_system)) return 0; #endif /* HAVE_WINDOW_SYSTEM */ @@ -9570,7 +9567,7 @@ { Lisp_Object tail, sym, val; Lisp_Object old = selected_frame; - + selected_frame = frame; for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail)) @@ -9686,17 +9683,16 @@ if (face_change_count) ++windows_or_buffers_changed; - if (! FRAME_WINDOW_P (sf) - && previous_terminal_frame != sf) - { - /* Since frames on an ASCII terminal share the same display - area, displaying a different frame means redisplay the whole - thing. */ + if (FRAME_TERMCAP_P (sf) + && FRAME_TTY (sf)->previous_terminal_frame != sf) + { + /* Since frames on a single ASCII terminal share the same + display area, displaying a different frame means redisplay + the whole thing. */ windows_or_buffers_changed++; SET_FRAME_GARBAGED (sf); - XSETFRAME (Vterminal_frame, sf); - } - previous_terminal_frame = sf; + FRAME_TTY (sf)->previous_terminal_frame = sf; + } /* Set the visible flags for all frames. Do this before checking for resized or garbaged frames; they want to know if their frames @@ -9718,6 +9714,7 @@ } } + /* Notice any pending interrupt request to change frame size. */ do_pending_window_change (1); @@ -10075,7 +10072,7 @@ { struct frame *f = XFRAME (frame); - if (FRAME_WINDOW_P (f) || f == sf) + if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf) { if (! EQ (frame, selected_frame)) /* Select the frame, for the sake of frame-local @@ -12889,7 +12886,7 @@ /* Window must either use window-based redisplay or be full width. */ if (!FRAME_WINDOW_P (f) - && (!line_ins_del_ok + && (!TTY_LINE_INS_DEL_OK (CURTTY ()) || !WINDOW_FULL_WIDTH_P (w))) GIVE_UP (4); @@ -13322,7 +13319,7 @@ /* On dumb terminals delete dvpos lines at the end before inserting dvpos empty lines. */ - if (!scroll_region_ok) + if (!TTY_SCROLL_REGION_OK (FRAME_TTY (f))) ins_del_lines (end - dvpos, -dvpos); /* Insert dvpos empty lines in front of @@ -13343,7 +13340,7 @@ /* On a dumb terminal insert dvpos empty lines at the end. */ - if (!scroll_region_ok) + if (!TTY_SCROLL_REGION_OK (FRAME_TTY (f))) ins_del_lines (end + dvpos, -dvpos); }
--- a/src/xfaces.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/xfaces.c Sun Dec 28 16:03:57 2003 +0000 @@ -241,6 +241,8 @@ #include "blockinput.h" #include "window.h" #include "intervals.h" +#include "systty.h" /* For emacs_tty in termchar.h */ +#include "termchar.h" #ifdef HAVE_X_WINDOWS @@ -5343,7 +5345,7 @@ /* See if the capabilities we selected above are supported, with the given colors. */ if (test_caps != 0 && - ! tty_capable_p (f, test_caps, fg_tty_color.pixel, bg_tty_color.pixel)) + ! tty_capable_p (FRAME_TTY (SELECTED_FRAME ()), test_caps, fg_tty_color.pixel, bg_tty_color.pixel)) return Qnil;
--- a/src/xfns.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/xfns.c Sun Dec 28 16:03:57 2003 +0000 @@ -48,6 +48,8 @@ #include "systime.h" #include "termhooks.h" #include "atimer.h" +#include "systty.h" +#include "termchar.h" #ifdef HAVE_X_WINDOWS
--- a/src/xterm.c Wed Dec 24 23:32:12 2003 +0000 +++ b/src/xterm.c Sun Dec 28 16:03:57 2003 +0000 @@ -7057,8 +7057,7 @@ EXPECTED is nonzero if the caller knows input is available. */ static int -XTread_socket (sd, bufp, numchars, expected) - register int sd; +XTread_socket (bufp, numchars, expected) /* register */ struct input_event *bufp; /* register */ int numchars; int expected; @@ -10852,12 +10851,13 @@ redeem_scroll_bar_hook = XTredeem_scroll_bar; judge_scroll_bars_hook = XTjudge_scroll_bars; - scroll_region_ok = 1; /* we'll scroll partial frames */ - char_ins_del_ok = 1; - line_ins_del_ok = 1; /* we'll just blt 'em */ - fast_clear_end_of_line = 1; /* X does this well */ - memory_below_frame = 0; /* we don't remember what scrolls - off the bottom */ + TERMINAL_SCROLL_REGION_OK (CURRENT_TERMINAL ()) = 1; /* we'll scroll partial frames */ + TERMINAL_CHAR_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; + TERMINAL_LINE_INS_DEL_OK (CURRENT_TERMINAL ()) = 1; /* we'll just blt 'em */ + TERMINAL_FAST_CLEAR_END_OF_LINE (CURRENT_TERMINAL ()) = 1; /* X does this well */ + TERMINAL_MEMORY_BELOW_FRAME (CURRENT_TERMINAL ()) = 0; /* we don't remember what + scrolls off the + bottom */ baud_rate = 19200; x_noop_count = 0;