pax_global_header00006660000000000000000000000064130627255520014521gustar00rootroot0000000000000052 comment=4ca282b327bd929587a8f5e3b76bfdfbf8083a55 boxes-1.2/000077500000000000000000000000001306272555200125035ustar00rootroot00000000000000boxes-1.2/.gitignore000066400000000000000000000002761306272555200145000ustar00rootroot00000000000000.cproject .project .idea/ .jekyll-metadata *.o *.a _support/ doc/boxes.1 doc/*.tar.gz *.tar.gz src/boxes src/boxes.exe src/boxes.h src/lex.yy.c src/parser.h src/parser.c bin/ _site/ _cache/ boxes-1.2/.travis.yml000066400000000000000000000002671306272555200146210ustar00rootroot00000000000000# Travis CI Build Configuration file for boxes language: c script: make && make test sudo: false addons: apt: packages: - flex - bison branches: only: - master boxes-1.2/LICENSE000066400000000000000000000431521306272555200135150ustar00rootroot00000000000000GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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. {description} Copyright (C) {year} {fullname} This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 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 Lesser General Public License instead of this License. boxes-1.2/Makefile000066400000000000000000000056421306272555200141520ustar00rootroot00000000000000# # File: Makefile # Creation: August 14, 1999 (Saturday, 01:08h) # Author: Copyright (C) 1999 Thomas Jensen # Format: GNU make # Purpose: Makefile for boxes, the box drawing program # # License: o 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. # o 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. # o 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 #____________________________________________________________________________ #============================================================================ # The following line (GLOBALCONF) is the only line you should need to edit! GLOBALCONF = /usr/share/boxes BVERSION = 1.2 ALL_FILES = LICENSE README.md README.Win32.txt boxes-config DOC_FILES = doc/boxes.1 doc/boxes.el PKG_NAME = boxes-$(BVERSION) .PHONY: clean build win32 debug win32.debug infomsg replaceinfos test package win32.package package_common build debug: infomsg replaceinfos $(MAKE) -C src BOXES_PLATFORM=unix $@ win32: infomsg replaceinfos $(MAKE) -C src BOXES_PLATFORM=win32 build win32.debug: infomsg replaceinfos $(MAKE) -C src BOXES_PLATFORM=win32 debug infomsg: @echo "| For compilation info please refer to the boxes compilation FAQ" @echo "| at http://boxes.thomasjensen.com/docs/faq.html#q5" replaceinfos: src/boxes.h doc/boxes.1 src/boxes.h: src/boxes.h.in src/regexp/regexp.h Makefile sed -e 's/--BVERSION--/$(BVERSION)/; s/--GLOBALCONF--/$(subst /,\/,$(GLOBALCONF))/' src/boxes.h.in > src/boxes.h doc/boxes.1: doc/boxes.1.in Makefile sed -e 's/--BVERSION--/$(BVERSION)/; s/--GLOBALCONF--/$(subst /,\/,$(GLOBALCONF))/' doc/boxes.1.in > doc/boxes.1 $(PKG_NAME).tar.gz: mkdir -p $(PKG_NAME)/doc cp $(ALL_FILES) $(PKG_NAME) cp $(DOC_FILES) $(PKG_NAME)/doc $(MAKE) -C src PKG_NAME=$(PKG_NAME) BOXES_PLATFORM=$(BOXES_PLATFORM) flags_$(BOXES_PLATFORM) package if which gtar >/dev/null 2>&1 ; then gtar cfvz $(PKG_NAME).tar.gz $(PKG_NAME)/* ; \ else tar cfvz $(PKG_NAME).tar.gz $(PKG_NAME)/* ; fi rm -rf $(PKG_NAME)/ package: build $(MAKE) BOXES_PLATFORM=unix $(PKG_NAME).tar.gz win32.package: win32 $(MAKE) BOXES_PLATFORM=win32 $(PKG_NAME).tar.gz clean: rm -f doc/boxes.1 src/boxes.h $(MAKE) -C src clean test: cd test; ./testrunner.sh -suite #EOF boxes-1.2/README.Win32.txt000066400000000000000000000024601306272555200151040ustar00rootroot00000000000000boxes 1.2 Win32 port Information Date: 16-Mar-2017 This is the Win32 Version of boxes 1.2, built from the official source tarball. Many thanks to Ron Aaron for making this Windows build possible! General information may be found in the generic README file provided with this archive and at http://boxes.thomasjensen.com/, the boxes home page. Note that the generic README file is intended for UNIX users, so some things don't translate literally (e.g., you would have to type Ctrl-Z instead of Ctrl-D to signal end of file, etc.). The system-wide config file is assumed to reside in the same directory as the boxes executable. (This is the case when you unpack the archive.) The name of the config file is assumed to be the same as the name of the executable, only with a .cfg extension instead of .exe. As with the UNIX version, boxes still looks for a file boxes.cfg in the directory pointed to by the environment variable HOME, and for a file pointed to by the environment variable BOXES. The standard troff format manual page is part of the package (boxes.1), but knowing that in the Windows world there may be some people who don't have troff installed on their systems, an HTML version of the page is provided. Enjoy! Thomas Jensen EOT boxes-1.2/README.md000066400000000000000000000050721306272555200137660ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/ascii-boxes/boxes.svg?branch=master)](https://travis-ci.org/ascii-boxes/boxes) # boxes **Command line ASCII boxes unlimited!** [Boxes](http://boxes.thomasjensen.com/) is a command line [filter program](http://boxes.thomasjensen.com/docs/filters.html) that draws ASCII art boxes around your input text ([examples](http://boxes.thomasjensen.com/examples.html)). For more information, please visit [the website](http://boxes.thomasjensen.com/). ## Status *Boxes* is **stable**. It has been around since 1999, and has since been included in several Linux distributions and, lately, even [Windows 10](http://boxes.thomasjensen.com/2016/08/boxes-part-of-windows10), via its Ubuntu subsystem. Its source code is quite portable, and so, *boxes* has been made to run on a wide range of platforms, from Windows PCs to Netgear routers. *Boxes* has matured, and is thusly no longer being actively developed. But contributors can be sure that their pull requests are promptly reviewed and merged into the main code base. ## License Boxes is free software under the GNU General Public License, version 2 ([GPLv2](http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)). ## Development The website has information on [building from source](http://boxes.thomasjensen.com/build.html), [testing](http://boxes.thomasjensen.com/testing.html), and [contributing](http://boxes.thomasjensen.com/contributing.html) to the source code.
*Boxes* has received support from many [contributors](http://boxes.thomasjensen.com/contributing.html#contributors) over the years, and continues to benefit greatly from contributions. Many thanks for that! ## Running it Try if boxes works by typing `echo foo | boxes` on the command line. It should give you something like that: /*******/ /* foo */ /*******/ Type `boxes -l` to get a long list of box designs to use. Detailed usage information is in the manual page and on the website. Consider tying *boxes* to your editor, so that it can be invoked by a simple keypress. ## Custom box designs You can define [your own box designs](http://boxes.thomasjensen.com/docs/)! We appreciate the creative new box designs that you craft for *boxes*. Please feel free to submit them in the form of pull requests on [boxes-config](https://github.com/ascii-boxes/boxes/blob/master/boxes-config), and they may make it into the next release! ``` _________________________ /\ \ \_| Thank you for | | using Boxes! | | _____________________|_ \_/______________________/ ``` boxes-1.2/boxes-1.2.lsm000066400000000000000000000020221306272555200146320ustar00rootroot00000000000000Begin4 Title: boxes Version: 1.2 Entered-date: 2017-03-16 Description: Boxes is a text filter which can draw any kind of box around its input text. Box design choices range from simple boxes to complex ASCII art. Removes and repairs boxes, even even if they have been badly damaged by editing of the text inside. Since boxes may be open on any side, the program can also be used to create regional comments in any programming language. Add and share new box designs by appending to a flexible config file. Keywords: text utility, boxes, ASCII art, filter program, text editing Author: boxes@thomasjensen.com (Thomas Jensen) Maintained-by: boxes@thomasjensen.com (Thomas Jensen) Primary-site: metalab.unc.edu /pub/Linux/utils/text 135k boxes-1.2.src.tar.gz 51k boxes-1.2.bin.ELF.tar.gz Original-site: http://boxes.thomasjensen.com/ Copying-policy: GPL 2.0 End boxes-1.2/boxes-config000066400000000000000000001651651306272555200150270ustar00rootroot00000000000000# # File: boxes-config # Date created: March 17, 1999 (Wednesday, 17:02h) # Author: listed separately for each box design # Format: ASCII Text # Purpose: boxes configuration file # # License: o 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. # o 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. # o 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 # # Remarks: Extensive documentation may be found on the Web at # http://boxes.thomasjensen.com/docs/ # The config file syntax in particular is described in # http://boxes.thomasjensen.com/docs/config-syntax.html #____________________________________________________________________________ #============================================================================ BOX c author "Thomas Jensen " designer "(public domain)" revision "1.0" revdate "March 18, 1999 (Thursday, 15:25h)" created "March 18, 1999 (Thursday, 15:25h)" sample /*************/ /* */ /* */ /*************/ ends shapes { nw ("/*") n ("*") ne ("*/") w ("/*") e ("*/") sw ("/*") s ("*") se ("*/") } delim ?" replace "\*/" with "*\/" # quote closing comment tags reverse "\*\\/" to "*/" padding { horiz 1 # alternatives: all, vert, lef, rig, bottom, top } # can be combined, e.g. all 3 top 1 elastic (n,e,s,w) END c # ============================================================================ BOX parchment author "Thomas Jensen " created "March 12, 1999 (Friday, 17:05h)" revision "1.0" revdate "March 12, 1999 (Friday, 17:05h)" escaped "aaa\"bbb\\\"ccc#" # the string aaa"bbb\"ccc# #escaped2 "aaa\\"bbb" # unterminated sample ________________________ /\ \ \_| | | | | | | ____________________|_ \_/_____________________/ ends shapes { nw (" __") nnw () wnw ("/\\ ", "\\_|") w (" |") n ("_") ne (" ") ene ("\\ ") e ("| ") se ("|_ ","__/") s ("_","_") ssw (" ", "\\_/") sw (" |"," ") ese () } padding { top 1 h 1 } elastic (n,e,s,w) END parchment # ============================================================================ BOX columns author "Thomas Jensen " revision "1.1" revdate "July 20, 1999 (Tuesday, 21:06h)" created "March 17, 1999 (Wednesday, 15:27h)" sample __^__ __^__ ( ___ )---------------( ___ ) | / | | \ | | / | | \ | | / | | \ | |___| |___| (_____)---------------(_____) ends shapes { nw (" __^__", "( ___ ") nnw (" ",")") n (" ","-") nne (" ","(") ne ("__^__ ", " ___ )") w (" | / |") wsw (" |___|") e ("| \\ | ") ese ("|___| ") sw ("(_____") ssw (")") s ("-") sse ("(") se ("_____)") } elastic (n, e, w, s) padding { horiz 1 } END columns # ============================================================================ BOX whirly author "Thomas Jensen " created "March 17, 1999 (Wednesday, 15:40h)" revdate "March 17, 1999 (Wednesday, 15:40h)" revision "1.0" sample .+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+. ( ) ) ( ( ) "+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+"+.+" ends shapes { nw (" .") wnw ("( ") w (" )", "( ") sw (" \"") n ("+\"+.") ne (". ") ene (" )") e ("( ", " )") s ("+.+\"") nne ("+\"+") sse ("+.+") se ("\" ") } elastic (n, w, s, e) END whirly # ============================================================================ BOX scroll author "Thomas Jensen " revision "1.2" revdate "August 18, 1999 (Wednesday, 17:00h)" created "March 17, 1999 (Wednesday, 17:04h)" SAMPLE / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \ | /~~\ /~~\ | |\ \ | | / /| | \ /| |\ / | | ~~ | | ~~ | | | | | | | | | | | | | | | | | | | | | \ |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| / \ / \ / ~~~ ~~~ ENDS delimiter ?" shapes { ne ("~~~~~ \ ") ene (" /~~\ |", "| / /|", "|\ / |", "| ~~ |") e ("| |") se ("| / ", " \ / ", " ~~~ ") nw (" / ~~~~~") wnw ("| /~~\ ", "|\ \ |", "| \ /|", "| ~~ |") w ("| |") sw (" \ |", " \ / ", " ~~~ ") n ("~") s ("~"," "," ") } eLAStic (n, s, e, w) padding { h 2 v 1 } END scroll # ============================================================================ BOX simple author "Thomas Jensen " designer "(public domain)" revision "1.1" revdate "August 22, 1999 (Sunday, 12:44h)" created "March 18, 1999 (Thursday, 15:24h)" sample ************* * * * * ************* ends shapes { nw ("*") ne ("*") sw ("*") se ("*") n ("*") e ("*") s ("*") w ("*") } padding { horiz 1 } elastic (n,e,s,W) END simple # ============================================================================ BOX c-cmt author "Thomas Jensen " designer "(public domain)" revision "1.0" revdate "June 17, 1999 (Thursday, 19:59h)" created "June 17, 1999 (Thursday, 19:59h)" sample /* */ /* regular C language */ /* comments */ /* */ ends shapes { w ("/*") e ("*/") } replace "\\*/" with "*\\/" # quote closing comment tags reverse "\\*\\\\/" to "*/" Padding { h 1 } elastic (e, w) END c-cmt # ============================================================================ BOX c-cmt2 author "Thomas Jensen " designer "(public domain)" revision "1.1" revdate "August 18, 1999 (Wednesday, 17:01h)" created "June 17, 1999 (Thursday, 19:59h)" sample /* * regular C language * comments */ ends shapes { nw ("/*") w (" *") sw (" *") ssw ("/") s (" ") # note that S must be defined! } padding { left 2 } delimiter ?" replace "\*/" with "*\/" # quote closing comment tags reverse "\*\\/" to "*/" elastic (s, w) END c-cmt2 # ============================================================================ BOX c-cmt3 author "AlpT (@freaknet.org)" designer "AlpT (@freaknet.org)" revision "1.0" revdate "Fri Jun 9 11:04:42 CEST 2006" created "Fri Jun 9 11:04:42 CEST 2006" sample /** * */ code(here); a++; /**/ ends shapes { nnw ("/** ", " * ", " */ ") n (" ", " ", " ") ssw ("/**/") s (" ") } delimiter ?" replace "\*/" with "*\/" # quote closing comment tags reverse "\*\\/" to "*/" elastic (n,s) END c-cmt3 # ============================================================================ BOX javadoc author "Ted Berg " designer "(public domain)" revision "1.0" revdate "October 25, 1999 (Monday 10:16h)" created "October 25, 1999 (Monday 10:16h)" sample /** * Javadoc Comments * */ ends shapes { nw ("/*") nnw ("*") n (" ") w (" *") sw (" *") ssw ("/") s (" ") } padding { left 2 } delimiter ?" replace "\*/" with "*\/" # quote closing comment tags reverse "\*\\/" to "*/" elastic (s, w, n) END javadoc # ============================================================================ BOX html author "Thomas Jensen " designer "(public domain)" revision "1.2" revdate "October 19, 2012 (Friday, 17:32h)" created "March 18, 1999 (Thursday, 15:26h)" sample ends shapes { nw ("") w ("") sw ("") } padding { h 1 } delim ?" replace "-->" with "-\-\>" reverse "-\\-\\>" to "-->" elastic (n,e,s,w) END html # ============================================================================ BOX shell author "Thomas Jensen " designer "(public domain)" revision "1.0" revdate "March 18, 1999 (Thursday, 15:27h)" created "March 18, 1999 (Thursday, 15:27h)" sample ############# # # # # ############# ends shapes { nw ("#") n ("#") se ("#") e ("#") sw ("#") s ("#") ne ("#") w ("#") } padding { h 1 } elastic (n,s,e, w) END shell # ============================================================================ BOX nuke author "Thomas Jensen " designer "Joan G. Stark " revision "1.1" revdate "August 22, 1999 (Sunday, 12:51h)" created "March 30, 1999 (Tuesday, 15:55h)" sample _ ._ _ , _ ._ (_ ' ( ` )_ .__) ( ( ( ) `) ) _) (__ (_ (_ . _) _) ,__) `~~`\ ' . /`~~` ,::: ; ; :::, ':::::::::::::::' _________________jgs______/_ __ \________________________ | | | BAD, BAD, BUG HERE :-) | |_________________________________________________________| ends shapes { nw (" "," "," "," "," "," "," "," ") ne (" "," "," "," "," "," "," "," ") nnw (" "," "," "," "," "," "," ","_") nne (" "," "," "," "," "," "," ","_") n (" _ ._ _ , _ ._ ", " (_ ' ( ` )_ .__) ", " ( ( ( ) `) ) _) ", " (__ (_ (_ . _) _) ,__)", " `~~`\\ ' . /`~~` ", " ,::: ; ; :::, ", " ':::::::::::::::' ", "jgs______/_ __ \\_________") w ("|") e ("|") sw ("|") s ("_") se ("|") } padding { all 1 bottom 0 } elastic (nne,nnw, s, e, w) END nuke # ============================================================================ BOX diamonds author "Thomas Jensen " designer "Joan G. Stark " revision "1.1" revdate "August 18, 1999 (Wednesday, 17:02h)" created "March 30, 1999 (Tuesday, 15:59h)" Sample /\ /\ /\ /\ /\//\\/\ /\//\\/\ /\//\\/\ /\//\\/\ /\//\\\///\\/\//\\\///\\/\//\\\///\\/\//\\\///\\/\ //\\\//\/\\///\\\//\/\\///\\\//\/\\///\\\//\/\\///\\ \\//\/ \/\\// \/ \/ /\ /\ //\\ joan stark spunk1111@juno.com //\\ \\// http://www.geocities.com/SoHo/7373/ \\// \/ \/ /\ /\ //\\/\ /\//\\ \\///\\/\//\\\///\\/\//\\\///\\/\//\\\///\\/\//\\\// \/\\///\\\//\/\\///\\\//\/\\///\\\//\/\\///\\\//\/ \/\\//\/ \/\\//\/ \/\\//\/ \/\\//\/ \/ \/ \/ \/ Ends delimiter ?" shapes { nw (" ", " /\", " /\//\", "//\\\/") nnw (" /\ ", "//\\/\ ", "\\///\\/", "/\/\\///") n (" /\ ", " /\//\\/\ ", "\//\\\///\\/", "\\\//\/\\///") nne (" /\ ", " /\//\\", "\//\\\//", "\\\//\/\") ne (" ", "/\ ", "/\\/\ ", "\///\\") ene ("\/\\//", " \/ ") e (" /\ ", " //\\", " \\//", " \/ ") ese (" /\ ", "/\//\\") wnw ("\\//\/", " \/ ") w (" /\ ", "//\\ ", "\\// ", " \/ ") wsw (" /\ ", "//\\/\") sw ("\\///\", " \/\\/", " \/", " ") ssw ("\/\//\\\", "//\\\//\", "\\//\/ ", " \/ ") s ("///\\/\//\\\", "/\\///\\\//\", " \/\\//\/ ", " \/ ") sse ("///\\/\/", "/\\///\\", " \/\\//", " \/ ") se ("/\\\//", "\//\/ ", "\/ ", " ") } elastic (n,s,e, w) END diamonds # ============================================================================ BOX mouse author "Thomas Jensen " designer "Joan G. Stark " revision "1.1" revdate "August 22, 1999 (Sunday, 12:57h)" created "March 18, 1999 (Thursday, 15:27h)" sample .--, .--, ( ( \.---./ ) ) '.__/o o\__.' {= ^ =} > - < ___________.""`-------`"".____________ / \ \ o joan stark O / / spunk1111@juno.com \ \ ascii art gallery / / http://www.geocities.com/SoHo/7373/ \ \______________________________________/ ___)( )(___ (((__) (__))) ends shapes { nnw (" ", " ", " ", " ", " ", "_") nne (" ", " ", " ", " ", " ", "_") ne (" ", " ", " ", " ", " ", " ") nw (" ", " ", " ", " ", " ", " ") sw ("\\", " ", " ") se ("/", " ", " ") ene ("\\") wnw ("/") e ("/","\\") w ("\\","/") n (" .--, .--, ", "( ( \\.---./ ) )", " '.__/o o\\__.' ", " {= ^ =} ", " > - < ", "_.\"\"`-------`\"\"._") s ("_____________", " ___)( )(___ ", "(((__) (__)))") ssw ("_"," "," ") sse ("_"," "," ") } elastic (nne,nnw, sse,ssw, e, w) padding { top 1 horiz 1 } END mouse # ============================================================================ BOX sunset author "Thomas Jensen " designer "Joan G. Stark " revision "1.0" revdate "March 30, 1999 (Tuesday, 17:10h)" created "March 30, 1999 (Tuesday, 17:10h)" sample . . | . \ | / '. \ ' / .' '. .'```'. .' <>.............:::::::`.......`:::::::................<> <>: ., .., . . . . . . . . . . joan stark :<> <>: :, :.' : : :`.: :.' `: `: `: `: spunk1111 :<> <>: ,.; : `.' : `: : `. : : : : @juno.com :<> <>:..................................................:<> <><><><><><><><><><><><><><><><><><><><><><><><><><><><> ~you can't hurt your eyesight by looking on the bright side~ ~but you can hurt them by looking at bad ascii art!~ ends shapes { e (":<>") w ("<>:") sw ("<>:", "<><") se (":<>", "><>") s ("..", "><") nw (" ", " ", " ", " ", " ", "<>.") ne (" ", " ", " ", " ", " ", ".<>") nnw (" ", " ", " ", " ", " ", ".") nne (" ", " ", " ", " ", " ", ".") n (" . ", " . | . ", " \\ | / ", " '. \\ ' / .' ", " '. .'```'. .' ", ":::::::`.......`:::::::") } elastic (nne,nnw, s, e, w) END sunset # ============================================================================ BOX boy author "Thomas Jensen " designer "Joan G. Stark " revision "1.1" revdate "August 22, 1999 (Sunday, 13:02h)" created "April 02, 1999 (Friday, 15:02h)" sample .-"""-. / .===. \ \/ 6 6 \/ ( \___/ ) _________ooo__\_____/______________ / \ | joan stark spunk1111@juno.com | | VISIT MY ASCII ART GALLERY: | | http://www.geocities.com/SoHo/7373/ | \_______________________ooo_________/ jgs | | | |_ | _| | | | |__|__| /-'Y'-\ (__/ \__) ends shapes { e (" |") w ("| ") sw (" \\", " ", " ", " ", " ", " ", " ") se ("/ ", " ", " ", " ", " ", " ", " ") ssw ("_", " ", " ", " ", " ", " ", " ") sse ("_", " ", " ", " ", " ", " ", " ") nw (" ", " ", " ", " ", " ") nnw (" ", " ", " ", " ", "_") nne (" ", " ", " ", " ", "_") ne (" ", " ", " ", " ", " ") ene ("\\ ") wnw (" /") n (" .-\"\"\"-. ", " / .===. \\ ", " \\/ 6 6 \\/ ", " ( \\___/ ) ", "ooo__\\_____/_____") s ("______________ooo", " | | | ", " |_ | _| ", " | | | ", " |__|__| ", " /-'Y'-\\ ", " (__/ \\__) ") } padding { top 1 } #elastic (n,s,e, w) # then I'd have to call this "boys" elastic (nne,nnw, sse,ssw, e, w) END boy # ============================================================================ BOX girl author "Thomas Jensen " designer "Joan G. Stark " revision "1.0" revdate "April 02, 1999 (Friday, 19:13h)" created "April 02, 1999 (Friday, 19:13h)" sample .-"""-. / .===. \ / / a a \ \ / ( \___/ ) \ ________ooo\__\_____/__/___________ / \ | joan stark spunk1111@juno.com | | VISIT MY ASCII ART GALLERY: | | http://www.geocities.com/SoHo/7373/ | \________________________ooo________/ jgs / \ /:.:.:.:.:.:.:\ | | | \==|==/ /-'Y'-\ (__/ \__) ends shapes { n (" .-\"\"\"-. ", " / .===. \\ ", " / / a a \\ \\ ", " / ( \\___/ ) \\ ", "ooo\\__\\_____/__/___", " ") s ("________________ooo", " / \\ ", " /:.:.:.:.:.:.:\\ ", " | | | ", " \\==|==/ ", " /-'Y'-\\ ", " (__/ \\__) ") e (" |") w ("| ") sw (" \\", " ", " ", " ", " ", " ", " ") se ("/ ", " ", " ", " ", " ", " ", " ") ssw ("_", " ", " ", " ", " ", " ", " ") sse ("_", " ", " ", " ", " ", " ", " ") nw (" ", " ", " ", " ", " ", " /") nnw (" ", " ", " ", " ", "_", " ") nne (" ", " ", " ", " ", "_", " ") ne (" ", " ", " ", " ", " ", "\\ ") } elastic (nne,nnw, sse,ssw, e, w) END girl # ============================================================================ BOX tjc author "Thomas Jensen " designer "Thomas Jensen " revision "1.1" revdate "July 16, 1999 (Friday, 18:55h)" created "April 02, 1999 (Friday, 19:26h)" SAmple static char *foo (const int a, const int b) /* * Do the foo on the bar and around again. * * a number of doodlefrobs * b barfoo mode (0 == off) * * Memory will be allocated for the result. * * RETURNS: Success: Pointer to result line * Error: 0 (e.g. out of memory) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { static char temp .... int ii; .... ends indent "none" # alternatives: "box", "text" replace "\\*/" with "*\\/" # quote closing comment tags reverse "\\*\\\\/" to "*/" shapes { wnw ("/*") w (" *") sw ("* ", " *") ssw ("*", "/") s (" *", " ") } elastic (n, s, w) padding { left 2 vertical 1 } END tjc # ============================================================================ BOX netdata author "Thomas Jensen " designer "Thomas Jensen " revision "1.0" revdate "April 09, 1999 (Friday, 19:06h)" created "April 09, 1999 (Friday, 19:06h)" sample %{-----------------------------------------------------------------+ | IBM Net.Data Macro Sample - Perl and SQL Backends | | Thomas Jensen, February 17, 1998 (Tuesday, 16:40h) | +-----------------------------------------------------------------%} ends shapes { nw ("%{") ne ("+ ") sw (" +") se ("%}") e ("| ") w (" |") n ("-") s ("-") } replace "%}" with "%\\}" reverse "%\\\\}" to "%}" padding { horizontal 1 } elastic (n, e, s, w) END netdata # ============================================================================ BOX xes author "Thomas Jensen " designer "Joan G. Stark " revision "1.1" revdate "August 18, 1999 (Wednesday, 17:04h)" created "April 09, 1999 (Friday, 20:05h)" sample <\/><\/><\/> <\/><\/> <\/> <\/> <\/> <\/> <\/> <\/> <\/> <\/> <\/><\/><\/> jgs ends delim ?" shapes { nw (" ", " <", " <") nnw (" ", "\/>", "/\>") n ("<\/>", "", " ") nne (" ", "<\/", " ", "> ") wnw (" <\/>", " ") w ("<\/> ", " ") wsw (" <\/>", " ") sw (" <", " <", " ") ssw ("\/>", "/\>", " ") s (" ", "<\/>", "") sse ("<\/", " ", "> ", " ") ese ("<\/> ", " ") e (" <\/>", " ") ene ("<\/> ", " ") } elastic (n, e, s, w) END xes # ============================================================================ BOX dog author "Thomas Jensen " designer "Joan G. Stark " revision "1.0" revdate "April 09, 1999 (Friday, 19:45h)" created "April 09, 1999 (Friday, 19:45h)" sample __ _,--="=--,_ __ / \." .-. "./ \ / ,/ _ : : _ \/` \ \ `| /o\ :_: /o\ |\__/ `-'| :="~` _ `~"=: | \` (_) `/ jgs .-"-. \ | / .-"-. .-----{ }--| /,.-'-.,\ |--{ }-----. ) (_)_)_) \_/`~-===-~`\_/ (_(_(_) ( ( joan stark ) ) < spunk1111@juno.com > ( ( ASCII ART GALLERY: ) ) < http://www.geocities.com/SoHo/7373/ > ( '-------------------------------------------' ends shapes { nnw (" ", " ", " ", " ", " ", " ", " ", "-", " ") nne (" ", " ", " ", " ", " ", " ", " ", "-", " ") nw (" ", " ", " ", " ", " ", " ", " ", ".--", " ) ") ne (" ", " ", " ", " ", " ", " ", " ", "--.", " ( ") w ("( ", " ) ") e (" )", " ( ") sw ("'--") se ("--'") s ("-") n (" __ _,--=\"=--,_ __ ", " / \\.\" .-. \"./ \\ ", " / ,/ _ : : _ \\/` \\ ", " \\ `| /o\\ :_: /o\\ |\\__/ ", " `-'| :=\"~` _ `~\"=: | ", " \\` (_) `/ ", " .-\"-. \\ | / .-\"-. ", "{ }--| /,.-'-.,\\ |--{ }", "(_)_)_) \\_/`~-===-~`\\_/ (_(_(_)") } elastic (nnw, nne,e,s,w) END dog # ============================================================================ BOX cat author "Thomas Jensen " designer "Joan G. Stark " revision "1.0" revdate "April 09, 1999 (Friday, 19:45h)" created "April 09, 1999 (Friday, 19:45h)" sample /\ /\ |`\\_,--="=--,_//`| \ ." :'. .': ". / ==) _ : ' : _ (== |>/O\ _ /O\<| | \-"~` _ `~"-/ | >|`===. \_/ .===`|< jgs .-"-. \===' | '===/ .-"-. .-----{'. '`}---\, .-'-. ,/---{.'. '}-----. ) `"---"` `~-===-~` `"---"` ( ( joan stark ) ) < spunk1111@juno.com > ( ( ASCII ART GALLERY: ) ) < http://www.geocities.com/SoHo/7373/ > ( '-------------------------------------------' ends shapes { nnw (" ", " ", " ", " ", " ", " ", " ", " ", "-", " ") nne (" ", " ", " ", " ", " ", " ", " ", " ", "-", " ") nw (" ", " ", " ", " ", " ", " ", " ", " ", ".--", " ) ") ne (" ", " ", " ", " ", " ", " ", " ", " ", "--.", " ( ") w ("( ", " ) ") e (" )", " ( ") sw ("'--") se ("--'") s ("-") n (" /\\ /\\ ", " |`\\\\_,--=\"=--,_//`| ", " \\ .\" :'. .': \". / ", " ==) _ : ' : _ (== ", " |>/O\\ _ /O\\<| ", " | \\-\"~` _ `~\"-/ | ", " >|`===. \\_/ .===`|< ", " .-\"-. \\===' | '===/ .-\"-. ", "{'. '`}---\\, .-'-. ,/---{.'. '}", "`\"---\"` `~-===-~` `\"---\"`") } elastic (nnw, nne,e,s,w) END cat # ============================================================================ BOX capgirl author "Thomas Jensen " designer "Joan G. Stark " revision "1.0" revdate "April 09, 1999 (Friday, 19:24h)" created "April 09, 1999 (Friday, 19:24h)" sample .-"```"-. /_______; \ (_________)\| / / a a \ \(_) / ( \___/ ) \ ________ooo\__\_____/__/___________ / \ | joan stark spunk1111@juno.com | | VISIT MY ASCII ART GALLERY: | | http://www.ascii-art.com | \________________________ooo________/ / \ jgs /:.:.:.:.:.:.:\ | | | \==|==/ /-'Y'-\ (__/ \__) ends shapes { n (" .-\"```\"-. ", " /_______; \\ ", " (_________)\\| ", " / / a a \\ \\(_) ", " / ( \\___/ ) \\ ", "ooo\\__\\_____/__/___", " ") s ("________________ooo", " / \\ ", " /:.:.:.:.:.:.:\\ ", " | | | ", " \\==|==/ ", " /-'Y'-\\ ", " (__/ \\__) ") e (" |") w ("| ") sw (" \\", " ", " ", " ", " ", " ", " ") se ("/ ", " ", " ", " ", " ", " ", " ") ssw ("_", " ", " ", " ", " ", " ", " ") sse ("_", " ", " ", " ", " ", " ", " ") nw (" ", " ", " ", " ", " ", " ", " /") nnw (" ", " ", " ", " ", " ", "_", " ") nne (" ", " ", " ", " ", " ", "_", " ") ne (" ", " ", " ", " ", " ", " ", "\\ ") } elastic (nne,nnw, sse,ssw, e, w) END capgirl # ============================================================================ BOX santa author "Thomas Jensen " designer "Joan G. Stark " revision "1.0" revdate "April 09, 1999 (Friday, 19:24h)" created "April 09, 1999 (Friday, 19:24h)" sample .-"``"-. /______; \ {_______}\| (/ a a \)(_) (.-.).-.) _______ooo__( ^ )____________ / '-.___.-' \ | joan stark | | spunk1111@juno.com | | ASCII ART GALLERY: | | http://www.ascii-art.com | \________________________ooo________/ |_ | _| jgs \___|___/ {___|___} |_ | _| /-'Y'-\ (__/ \__) ends shapes { n (" .-\"``\"-. ", " /______; \\ ", " {_______}\\| ", " (/ a a \\)(_) ", " (.-.).-.) ", "ooo__( ^ )____", " '-.___.-' ") s ("_________________ooo", " |_ | _| jgs", " \\___|___/ ", " {___|___} ", " |_ | _| ", " /-'Y'-\\ ", " (__/ \\__) ") e (" |") w ("| ") sw (" \\", " ", " ", " ", " ", " ", " ") se ("/ ", " ", " ", " ", " ", " ", " ") ssw ("_", " ", " ", " ", " ", " ", " ") sse ("_", " ", " ", " ", " ", " ", " ") nw (" ", " ", " ", " ", " ", " ", " /") nnw (" ", " ", " ", " ", " ", "_", " ") nne (" ", " ", " ", " ", " ", "_", " ") ne (" ", " ", " ", " ", " ", " ", "\\ ") } elastic (nne,nnw, sse,ssw, e, w) END santa # ============================================================================ BOX spring author "Thomas Jensen " designer "Joan G. Stark " revision "1.1" revdate "August 18, 1999 (Wednesday, 17:05h)" created "April 09, 1999 (Friday, 15:53h)" sample , /\^/`\ | \/ | | | | SPRING IS IN THE AIR! jgs \ \ / _ _ '\\//' _{ ' }_ || joan stark { `.!.` } || ',_/Y\_,' || , {_,_} |\ || |\ | | | || | | ASCII ART GALLERY: (\| /) | | || / / \| // \ \||/ / |// `\\//` \\ \./ \\ / // \\./ \\ // \\ |/ / ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ends delim ?" shapes { nw (" , ") wnw (" /\^/`\ ", " | \/ | ", " | | | ", " \ \ / ", " '\\//' ") w (" || ") wsw (" || , ", "|\ || |\ ", "| | || | |", "| | || / / ", " \ \||/ / ") sw (" `\\//` ", " ^^^^^^^^^^") ene (" ", " ", " jgs ", " _ _ ", " _{ ' }_ ", "{ `.!.` }", "',_/Y\_,'", " {_,_} ") e (" | ") ese (" (\| /)", " \| // ", " |// ") se (" \\ |/ / ", "^^^^^^^^^") s ("\ \./ \", "^^^^^^^^^^^^") } elastic (s,e,w) END spring # ============================================================================ BOX stark2 author "Thomas Jensen " designer "Joan G. Stark " revision "1.0" revdate "April 05, 1999 (Monday, 21:55h)" created "April 05, 1999 (Monday, 21:55h)" sample .:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@-:. .:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@-:. .:-@ ____ (_, _, _, _, _, @-:. .:-@ (-(__`,_ ,_ |_, | | | | Spunk1111@juno.com @-:. .:-@ ____)|_)|_|| || \__, _|_ _|_ _|_ _|_ @-:. .:-@ ( _| |_, @-:. .:-@ ( ____, ____ (_, @-:. .:-@ (-| _ _ ,_ (-(__`_|_ _ ,_ |_, @-:. .:-@ _ |(_)(_|| | ____) | (_|| | \_, @-:. .:-@ (__/ ( |_, @-:. .:-@ @-:. .:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@-:. .:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@.:-@-:. ends shapes { nw (".:-@", ".:-@") n (".:-@", ".:-@") nne (".:-", ".:-") ne ("@-:.", "@-:.") e ("@-:.") w (".:-@") sw (".:-@", ".:-@") s (".:-@", ".:-@") sse (".:-", ".:-") se ("@-:.", "@-:.") } elastic (n,s,e, w) END stark2 # ============================================================================ BOX stark1 author "Thomas Jensen " designer "Joan G. Stark " revision "1.0" revdate "April 05, 1999 (Monday, 21:55h)" created "April 05, 1999 (Monday, 21:55h)" sample =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ^ -, ,-. . . ^ ^ | ,-. ,-. ;-. `-, |- ,-. ;-. | ' ^ ^ , | | | ,-| | | , ; | ,-| | |`. ^ ^ `-' `-' `-^ ' ^ `-' `- `-^ ' ` ` ^ ^ Spunk1111@juno.com ^ ^ ,-. . . . . . ^ ^ `-, ;-. . . ;-. | ' | | | | ^ ^ , ; | | | | | | |`. | | | | ^ ^ `-' |-' `-^ ' ^ ` ` ` ` ` ` ^ ^ ` ^ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ends shapes { nw ("=") ne ("=") nne ("-") N ("-=") e ("^") w ("^") sw ("=") ssw ("-") s ("=-") se ("=") } padding {h 1} elastic (n,s,e, w) END stark1 # ============================================================================ BOX peek author "Thomas Jensen " revision "1.0" revdate "April 12, 1999 (Monday, 12:52h)" created "April 12, 1999 (Monday, 12:52h)" sample /* _\|/_ (o o) +----oOO-{_}-OOo---------------------+ | | | C function headers? | | | | | +-----------------------------------*/ ends shapes { nw ("/*", " ", " +") nnw (" _\\|/_ ", " (o o) ", "----oOO-{_}-OOo") n (" ", " ", "-") ne (" ", " ", "+") e ("|") w (" |") sw (" +") s ("-") sse ("*") se ("/") } replace "\\*/" with "*\\/" # quote closing comment tags reverse "\\*\\\\/" to "*/" elastic (n,e,s,w) END peek # ============================================================================ BOX java-cmt author "Thomas Jensen " designer "(public domain)" revision "1.0" revdate "June 17, 1999 (Thursday, 19:59h)" created "June 17, 1999 (Thursday, 19:59h)" sample // // regular Java // comments // ends shapes { w ("//") } padding {lef 1} elastic (w) END java-cmt # ============================================================================ BOX pound-cmt author "Thomas Jensen " designer "(public domain)" revision "1.0" revdate "June 17, 1999 (Thursday, 19:59h)" created "June 17, 1999 (Thursday, 19:59h)" sample # # regular comments used in Perl, Shell scripts, etc. # ends shapes { w ("#") } padding { left 1} elastic (w) END pound-cmt # ============================================================================ BOX html-cmt author "Thomas Jensen " designer "(public domain)" revision "1.0" revdate "June 17, 1999 (Thursday, 19:59h)" created "June 17, 1999 (Thursday, 19:59h)" sample ends shapes { w ("") } elastic (e,w) END html-cmt # ============================================================================ BOX vim-cmt author "Thomas Jensen " designer "Bram Moolenaar" revision "1.0" revdate "June 17, 1999 (Thursday, 19:59h)" created "June 17, 1999 (Thursday, 19:59h)" sample " " comments used in the vim editor's config file (.vimrc) " ends shapes { w ("\"") } padding { left 1 } elastic ( w ) END vim-cmt # ============================================================================ BOX right author "Thomas Jensen " designer "Thomas Jensen " revision "1.0" revdate "June 17, 1999 (Thursday, 19:59h)" created "June 17, 1999 (Thursday, 19:59h)" sample This can be used for marking code changes with your initials (I don't like it, but some people work this way): for (j=0; j" designer "(public domain)" revision "1.0" revdate "March 15, 2000 (Wednesday 12:17h)" created "March 15, 2000 (Wednesday 12:17h)" sample -- -- regular Ada -- comments -- ends shapes { w ("--") } padding {lef 1} elastic (w) END ada-cmt # ============================================================================ BOX ada-box author "Neil Bird " designer "(public domain)" revision "1.0" revdate "March 15, 2000 (Wednesday 12:24h)" created "March 15, 2000 (Wednesday 12:24h)" sample --------------- -- -- -- -- --------------- ends shapes { nw ("--") n ("-") ne ("--") w ("--") e ("--") sw ("--") s ("-") se ("--") } padding { horiz 1 } elastic (n,e,s,w) END ada-box # ============================================================================ BOX tex-cmt author "Nic H " designer "(public domain)" revision "1.0" revdate "December 01, 2016 (Thursday 15:20h)" created "December 01, 2016 (Thursday 15:20h)" sample % % regular TeX/LaTeX % comments % ends shapes { w ("%") } padding {lef 1} elastic (w) END tex-cmt # ============================================================================ BOX tex-box author "Nic H " designer "(public domain)" revision "1.0" revdate "December 01, 2016 (Thursday 15:21h)" created "December 01, 2016 (Thursday 15:21h)" sample %=============% % TeX is love % % Tex is life % %=============% ends shapes { nw ("%") n ("=") ne ("%") w ("%") e ("%") sw ("%") s ("=") se ("%") } padding { horiz 1 } elastic (n,e,s,w) END tex-box # ============================================================================ BOX boxquote author "Christian Molls " designer "Christian Molls " revdate "Tue Aug 15 23:02:02 CEST 2000" created "Tue Aug 15 23:01:50 CEST 2000" revision "1.0" sample ,----[ mp3-wav ] | #!/bin/sh | # konvertiert im aktuellen Verzeichnis .mp3 in .wav | for i in *.mp3; do | mpg123 -v --stereo --rate 44100 -w "`basename "$i" .mp3`".wav "$i" | done `---- ends shapes { nw (",") nnw ("---- [ ]") n (" ") w ("|") sw ("`") ssw ("---- ") s (" ") } padding { horiz 1 } elastic (w,n,s) END boxquote # ============================================================================ BOX cc author "Bas van Gils " designer "(public domain)" revision "1.0" revdate "Tue Sep 19 12:06:51 CEST 2000" created "Tue Sep 19 12:06:51 CEST 2000" sample /**************** * * * * ****************/ ends shapes { nw ("/*") n ("*") ne ("* ") w (" *") e ("* ") sw (" *") s ("*") se ("*/") } delim ?" replace "\*/" with "*\/" # quote closing comment tags reverse "\*\\/" to "*/" padding { horiz 1 } elastic (n,e,s,w) END cc # ============================================================================ BOX stone author "Fredrik Steen " designer "Fredrik Steen " revision "1.0" created "April 25, 2001 (Wed 11:00)" sample +-------------+ | stone | +-------------+ ends shapes { nw ("+") n ("-") ne ("+") w ("|") e ("|") sw ("+") s ("-") se ("+") } padding { horiz 1 } elastic (n,e,s,w) END stone # ============================================================================ BOX test1 author "Thomas Jensen " designer "Thomas Jensen " sample test1 ends shapes { nw ("#") n ("123") s ("12345") se ("#") e ("#") sw ("#") ne ("#") w ("#") } elastic (n,s,e, w) END test1 # ============================================================================ BOX test2 author "Thomas Jensen " designer "Thomas Jensen " sample test2 ends shapes { nw ("#") nnw ("--") sse ("---") n ("123") s ("12345") se ("#") e ("#") sw ("#") ne ("#") w ("#") } elastic (n,s,e, w) END test2 # ============================================================================ BOX test3 author "Thomas Jensen " designer "Thomas Jensen " sample test3 ends shapes { nnw ("123") nne ("456") n ("---") s ("<>") ssw ("12345") sse ("67890") nw ("#") se ("#") e ("#") sw ("#") ne ("#") w ("#") } elastic (nne,nnw,ssw,sse,e, w) END test3 # ============================================================================ BOX test4 author "Thomas Jensen " designer "Thomas Jensen " sample test4 ends shapes { e ("1","2","3") w ("1","2","3","4","5") s ("#") n ("#") nw ("#") se ("#") sw ("#") ne ("#") } elastic (n,s,e, w) END test4 # ============================================================================ BOX test5 author "Thomas Jensen " designer "Thomas Jensen " sample test5 ends shapes { e ("1","2","3") w ("1","2","3","4","5") ene ("|","|") wsw ("|","|","|") s ("#") n ("#") nw ("#") se ("#") sw ("#") ne ("#") } elastic (n,s,e, w) END test5 # ============================================================================ BOX test6 author "Thomas Jensen " designer "Thomas Jensen " sample test6 ends shapes { ene ("1","2","3") ese ("4","5","6") wnw ("1","2","3","4","5") wsw ("6","7","8","9","0") e ("|","|") w ("|","|","|") s ("#") n ("#-") nw ("#") se ("#") sw ("#") ne ("#") } elastic (ene,ese,wnw,wsw,n,s) END test6 # ============================================================================ BOX retest author "Thomas Jensen " designer "Thomas Jensen " revision "1.1" revdate "August 18, 1999 (Wednesday, 17:07h)" created "April 04, 1999 (Sunday, 18:00h)" sample regular expression test use "foo", "bar", and "--" repeatedly in input ends delimiter ?" shapes { nw ("*") ne ("*") sw ("*") se ("*") n ("*") e ("*") s ("*") w ("*") } elastic (n,e,s,W) replace once "bar" with "raba-raba" replace global "f(o)o" with "fu\1\1\1\1\1\1" replace "--" with "++++" END retest # ============================================================================ BOX headline author "Thomas Jensen " designer "Thomas Jensen " revision "1.2" revdate "August 22, 1999 (Sunday, 13:22h)" created "March 18, 1999 (Thursday, 15:25h)" sample /*************/ /* */ /* */ /*************/ ends shapes { nw ("/*") n ("*") ne ("*/") w ("/*") e ("*/") sw ("/*") s ("*") se ("*/") } replace "^( *)([^ ])" with "\\1\\2 " replace "([^ ]) ([^ ])" with "\\1 \\2" reverse "^( *)([^ ]*) " to "\\1\\2" # \1 to leave indentation untouched reverse "([^ ]) ([^ ])" to "\\1 \\2" padding { left 2 right 1 } elastic (n,e,s,w) END headline # ============================================================================ BOX lisp-cmt author "Vijay Lakshminarayanan " designer "(public domain)" revision "1.0" revdate "February 20, 2006 (Monday, 20:36h)" created "February 20, 2006 (Monday, 20:36h)" sample ;; ;; regular comments used in Lisp ;; ends shapes { w (";;") } padding { left 1 } elastic (w) END lisp-cmt #============================================================================ BOX ccel author "Elmar Loos " designer "Elmar Loos " revision "1.0" sample /////////////// text // here // /////////////// ends shapes { nnw ("/") n ("/") ne ("//") e ("//") ssw ("//") s ("/") se ("//") } padding { right 1 } elastic (n,e,s) END ccel #============================================================================ BOX underline author "Elmar Loos " designer "Elmar Loos " revision "1.0" sample // Bla, foo bar! // ~~~~~~~~~~~~~ ends shapes { w ("// ") sw ("// ") s ("~") } elastic (s,w) END underline #============================================================================ BOX ian_jones author "Karl E. Jorgensen " created "Fri Jul 20 16:52:39 BST 2001" revision "0.1" sample \\\/// / _ _ \ (| (.)(.) |) .----------------------.OOOo--()--oOOO.-----------------. | | | Your Text Here Your Text Here Your Text Here Your Tex | | Your Text Here Your Text Here Your Text Here Your Tex | | Your Text Here Your Text Here Your Text Here Your Tex | | Your Text Here Your Text Here Your Text Here Your Tex | | | '--------------------.oooO------------------------------' ( ) Oooo. \ ( ( ) \_) ) / (_/ ends shapes { nw(" ", " ", " ", ".") w ("|") sw("'", " ", " ", " ", " ") nnw(" ", " ", " ", "-") n (" \\\\\\/// ", " / _ _ \\ ", " (| (.)(.) |) ", ".OOOo--()--oOOO.") nne(" ", " ", " ", "-") ne (" ", " ", " ", ".") e ("|") se ("'", " ", " ", " ", " ") ssw("-", " ", " ", " ", " ") s (".oooO-----------", " ( ) Oooo. ", " \\ ( ( ) ", " \\_) ) / ", " (_/ ") sse("-", " ", " ", " ", " ") } elastic (w,e,nnw,nne,ssw,sse) padding { all 1 } END ian_jones # ============================================================================ BOX unicornthink author "Mike Meyer " revision "1.1" revdate "November 08, 2014 (Saturday, 11:08h)" created "September 02, 2013 (Monday, 14:43h)" sample _________________________________ / \ | E L E C T R O L Y T E S | \______________________________ '\ () \\ O \\ . o |\\/| / " '\ . . . / ) | ' _.' | '-'/ \ ends shapes { nw (" __", " / ") n ("____", " ") ne ("__ ", " \\ ") sw (" \\__", " ", " ", " ", " ", " ", " ", " ", " ", " ") s ("_____", " ", " ", " ", " ", " ", " ", " ", " ", " ") nnw ("____", " ") nne ("_____", " ") w (" | ") e (" | ") se ("'\\ ", " \\\\ ", " \\\\ . ", " |\\\\/| ", " / \" '\\ ", " . . . ", " / ) | ", "' _.' | ", "'-'/ \\ ", " ") ssw ("____", " ", " ", " ", " ", " ", " ", " ", " ", " ") sse ("____ ", "() ", " O ", " o", " ", " ", " ", " ", " ", " ") } elastic (n, s, e, w) END unicornthink # ============================================================================ BOX unicornsay author "Mike Meyer " revision "1.1" revdate "November 08, 2014 (Saturday, 11:08h)" created "September 02, 2013 (Monday, 14:43h)" sample _________________________________ / \ | E L E C T R O L Y T E S | \___________________________ __'\ |/ \\ \ \\ . |\\/| / " '\ . . . / ) | ' _.' | '-'/ \ ends shapes { nw (" __", " / ") n ("____", " ") ne ("__ ", " \\ ") sw (" \\__", " ", " ", " ", " ", " ", " ", " ", " ", " ") s ("_____", " ", " ", " ", " ", " ", " ", " ", " ", " ") nnw ("____", " ") nne ("_____", " ") w (" | ") e (" | ") se ("'\\ ", " \\\\ ", " \\\\ . ", " |\\\\/| ", " / \" '\\ ", " . . . ", " / ) | ", "' _.' | ", "'-'/ \\ ", " ") ssw ("____", " ", " ", " ", " ", " ", " ", " ", " ", " ") sse ("_ __", " |/ ", " \\ ", " ", " ", " ", " ", " ", " ", " ") } elastic (n, s, e, w) END unicornsay # ============================================================================ BOX caml author "Michael Tiernan " designer "Michael Tiernan " revision "1.5" revdate "Wed May 14 11:41:27 EDT 2014" created "Wed May 14 11:41:27 EDT 2014" sample (*************) (* *) (* *) (*************) ends shapes { nw ("(*") n ("*") ne ("*)") w ("(*") e ("*)") sw ("(*") s ("*") se ("*)") } elastic (n,e,s,w) padding { horiz 1 } replace "\\(\\*" with "(+*" replace "\\*\\)" with "*+)" reverse "\\(\\+\\*" to "(*" reverse "\\*\\+\\)" to "*)" END caml # ============================================================================ BOX twisted author "Tristano Ajmone " designer "Michael Naylor" revision "1.0" created "Saturday, 02-Jan-16 12:42:31 UTC+1" revdate "Saturday, 02-Jan-16 12:42:31 UTC+1" tags "geometry, frame" # Minimum Text-Area in output: 17x8 # Minimum Frame size: 21x42 # This ASCII Frame is a derivative adaptation from a frame created by # michael naylor - mnaylor@math.fsu.edu # freely downloaded from: # http://www.retrojunkie.com/asciiart/designs/borders.htm sample ._____. ._____. .________________________________________. ._____. ._____. | ._. | | ._. | | .____________________________________. | | ._. | | ._. | | !_| |_|_|_! | | !____________________________________! | | !_| |_|_|_! | !___| |_______! !________________________________________! !___| |_______! .___|_|_| |____________________________________________________|_|_| |___. | ._____| |________________________________________________________| |_. | | !_! | | | | | ! !_! | !_____! | | * * * * * * * * * * * TWISTED * * * * * * * * * * | | !_____! ._____. | | -----------------------|------------------------- | | ._____. | ._. | | | Just another cool ascii frame, brought to you by: | | | ._. | | | | | | | | | | | | | | | | | | | -~{ Tristano Ajmone }~- | | | | | | | !_! | | | -----------------------|------------------------- | | ! !_! | !_____! | | Derived from an ascii frame originally created by: | | !_____! ._____. | | | | ._____. | ._. | | | -~{ Michael Naylor }~ | | | ._. | | !_| |_|_|____________________________________________________| |_|_|_! | !___| |________________________________________________________| |_______! .___|_|_| |___. .________________________________________. .___|_|_| |___. | ._____| |_. | | .____________________________________. | | ._____| |_. | | !_! | | !_! | | !____________________________________! | | !_! | | !_! | !_____! !_____! !________________________________________! !_____! !_____! ends shapes { NW ("._____. .__", "| ._. | | .", "| !_| |_|_|", "!___| |____", ".___|_|_| |", "| ._____| |") WNW ("| !_! | | |", "!_____! | |", "._____. | |", "| ._. | | |") W ("| | | | | |") WSW ("| !_! | | |", "!_____! | |", "._____. | |", "| ._. | | |") SW ("| !_| |_|_|", "!___| |____", ".___|_|_| |", "| ._____| |", "| !_! | | !", "!_____! !__") NNW ("___. .___", "_. | | ._", "_! | | !_", "___! !___", "_________", "_________") N ("_", "_", "_", "_", "_", "_") NNE ("___. .___", "_. | | ._", "_! | | !_", "___! !___", "_________", "_________") NE ("__. ._____.", ". | | ._. |", "| |_|_|_! |", "| |_______!", "|_|_| |___.", "____| |_. |") ENE ("| | ! !_! |", "| | !_____!", "| | ._____.", "| | | ._. |") E ("| | | | | |") ESE ("| | ! !_! |", "| | !_____!", "| | ._____.", "| | | ._. |") SE ("| |_|_|_! |", "| |_______!", "|_|_| |___.", "____| |_. |", "! | | !_! |", "__! !_____!") S ("_", "_", "_", "_", "_", "_") SSE ("________", "________", "__. .___", ". | | ._", "! | | !_", "__! !___") SSW ("_________", "_________", "___. .___", "_. | | ._", "_! | | !_", "___! !___") } padding { all 1 bottom 0 } elastic (n,e,s,w) END twisted # ============================================================================ BOX scroll-akn author "Tristano Ajmone " designer "akn" created "Saturday, 02-Jan-16 03:34:03 UTC+1" revision "1.0" tags "scroll" sample /"\/\_..---------------------------------._/\/"\ ( _|| ||| Scroll-AKN... ||| ||_ ) \_/\/ || ------------------------------ || \/\_/ || Original Design by "akn" (???) || || Implemented in boxes by: || || -~{ Tristano Ajmone }~- || /"\/\_|----------------------------------|_/\/"\ ( _| |_ ) \_/\/ `----------------------------------' \/\_/ ends shapes { NW (" /\"\\/\\_..") WNW ("( _||", " \\_/\\/ ||") W (" ||") SW (" /\"\\/\\_|-", "( _| ", " \\_/\\/ `-") N ("-") S ("-", " ", "-") NE ("-._/\\/\"\\ ") ENE ("||_ )", "|| \\/\\_/ ") E ("|| ") SE ("-|_/\\/\"\\ ", " |_ )", "-' \\/\\_/ ") } elastic (W,E,N,S) padding { horizontal 1 vertical 0 } END scroll-akn # ============================================================================ BOX face author "Dmitry Bolshakov " designer "Dmitry Bolshakov " created "2014-02-13 08:41:11" revision "1.0" sample .--(0) (0)--. ( \/ ) ( \____/ ) ( ) ( face face face ) ( face face face ) '--------------' ends shapes { nw (" .", "( ", "( ") nnw ("-", " ", " ") n ( "(0) (0)", " \\/ ", " \\____/ " ) nne ("-", " ", " ") ne (". ", " )", " )") e (" )") se ("' ") s ("-") sw (" '") w ("( ") } padding { top 1 } elastic (nnw, nne, e, s, w) END face #EOF vim: set ai sw=4: boxes-1.2/boxes-pkg.openwrt000066400000000000000000000035111306272555200160220ustar00rootroot00000000000000# Copyright (C) boxes (c)1999 by Thomas Jensen # All rights reserved. # # This is free software, licensed under the GNU General Public License # See /LICENSE for more information. # # File: $(TOPDIR)/feeds/packages/utils/boxes/Makefile # Date created: 2014-09-12 23:28 # Author: Lu Weifeng # usage: # +-------------------------------------------------------------------------+ # |$cd $(TOPDIR) | # |$./scripts/feeds update -i | # |$./scripts/feeds install boxes | # |$apt-get install binutils-multiarch | # |$make package/boxes/compile package/index | # |$scp $(TOPDIR)/bin/ar71xx/packages/boxes_1.1-1_ar71xx.ipk openwrt:/tmp/| # |$opkg install --force-depends /tmp/boxes_1.1-1_ar71xx.ipk | # +-------------------------------------------------------------------------+ #____________________________________________________________________________ #============================================================================ include $(TOPDIR)/rules.mk PKG_NAME:=boxes PKG_VERSION:=1.2 PKG_RELEASE:=1 PKG_BUILD_DIR:=$(PKG_NAME)-$(PKG_VERSION).$(PKG_RELEASE) PKG_SOURCE:=v1.2.tar.gz PKG_SOURCE_URL:=http://github.com/ascii-boxes/boxes/archive/ include $(INCLUDE_DIR)/package.mk define Package/boxes SECTION:=utils CATEGORY:=Utilities TITLE:=HW endef define Package/boxes/description boxes endef define Package/boxes/Build/Compile $(MAKE) -C $(PKG_BUILD_DIR) boxes endef define Package/boxes/install $(INSTALL_DIR) $(1)/bin/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/boxes $(1)/bin/ endef $(eval $(call BuildPackage,boxes)) boxes-1.2/boxes.spec000066400000000000000000000042701306272555200145020ustar00rootroot00000000000000%define name boxes %define version 1.2 %define release 0 %define prefix /usr %define cfgfile %prefix/share/boxes %define nvr %{name}-%{version}-%{release} %define defbr /var/tmp/%{nvr}-build name: %name version: %version release: %release vendor: Thomas Jensen packager: Thomas Jensen summary: Command line ASCII boxes unlimited group: Applications/Text copyright: GPL Version 2 URL: http://boxes.thomasjensen.com/ source: http://github.com/ascii-boxes/%{name}/archive/v%{version}.tar.gz buildroot: %defbr %description "boxes" can draw all kinds of boxes around its input text, ranging from a C comment box to complex ASCII art. These boxes may also be removed, even if they have been badly damaged by editing of the text inside. Since boxes may be open on any side, "boxes" can also be used to create regional comments in any programming language. With the help of an editor macro or mapping, damaged boxes can easily be repaired. New box designs of all sorts can easily be added and shared by appending to a free format configuration file. ########################################################################### # useful macros ########################################################################### %define cleanroot [ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" = "%defbuildroot" ] && rm -rf "$RPM_BUILD_ROOT" %define restorebins [ -f $RPM_BUILD_DIR/$RPM_PACKAGE_NAME.cpio ] && cpio -iv -I $RPM_BUILD_DIR/$RPM_PACKAGE_NAME.cpio ########################################################################### %prep %setup %build rm doc/boxes.1 rm src/boxes.h make GLOBALCONF=%cfgfile %install mkdir -p $RPM_BUILD_ROOT/%prefix/bin mkdir -p $RPM_BUILD_ROOT/%prefix/share/man/man1 install -m 0755 src/boxes $RPM_BUILD_ROOT/%prefix/bin install -m 0644 doc/boxes.1 $RPM_BUILD_ROOT/%prefix/share/man/man1 install -m 0644 boxes-config $RPM_BUILD_ROOT/%cfgfile # write filelisting to /tmp find "$RPM_BUILD_ROOT" -type f -printf "/%P\n" > /tmp/FILES-%nvr %clean # delete stuff [ "$RPM_BUILD_ROOT" = "%defbr" -a -d "%defbr" ] && rm -rf %defbr %files %defattr(-, root, root) /usr/bin/boxes /usr/share/man/man1/boxes.1.gz %config /usr/share/boxes %doc COPYING README boxes-1.2/boxes.vim000066400000000000000000000074571306272555200143550ustar00rootroot00000000000000" Vim syntax file " Language: "boxes" configuration file " Maintainer: Thomas Jensen " Latest Change: September 12, 1999 (Sunday, 01:14h) " Vim Version: 5.4 " Filenames: .boxes boxes-config boxes " URL: https://github.com/ascii-boxes/boxes/blob/master/boxes.vim " " Problems: - Strings must start and end with double quotes (") and the " escape character is always backslash (\), which does not " allow correct colorization of strings following a DELIM. " " + Region ends are matched inside contained strings " SOLVED! Thanks Dr. Charles E. Campbell! " Removes any old syntax stuff hanging around syntax clear " ignore case syntax case ignore " Set the keyword characters set iskeyword=a-z,A-Z " " Key Words " syntax keyword boxesClassicKeywords contained author revision created revdate indent skipwhite skipempty nextgroup=boxesString syntax keyword boxesBlocks contained elastic replace reverse padding shapes syntax keyword boxesRegStuff contained with to once global " Shape Names syntax keyword boxesShapes contained nw nnw n nne ne ene e ese syntax keyword boxesShapes contained se sse s ssw sw wsw w wnw " Padding Areas syntax keyword boxesPads contained a[ll] l[eft] r[ight] t top syntax keyword boxesPads contained b[ottom] h[orizontal] v[ertical] " Delimiter statement syntax keyword boxesDelim contained delim delimiter skipwhite skipempty nextgroup=boxesDelSpec " " Error - this is matched when the others don't match " syntax match boxesError /\S/ " " Main syntax definition part " syntax match boxesComma contained /,/ syntax match boxesBraces contained /[{}]/ syntax match boxesDelSpec contained /[^ \t\r]\+/ syntax match boxesWord contained /[a-zA-ZäöüÄÖÜ][a-zA-Z0-9\-_üäöÜÄÖß]*/ syntax match boxesNumber contained /[-+]\=\d\+/ " a list, used inside shape blocks and for the elastic list syntax region boxesList contained matchgroup=Normal start="(" end=")" contains=boxesString,boxesShapes,boxesComma,boxesError,boxesComment " Strings syntax region boxesString contained start=/"/ skip=/\\\\\|\\"/ end=/"/ oneline " These items may appear inside a BOX..END block syntax cluster boxesInside contains=boxesComment,boxesWord,boxesElasticList syntax cluster boxesInside add=boxesError,boxesBlocks,boxesSample,boxesDelim syntax cluster boxesInside add=boxesClassicKeywords,boxesShapeBlk,boxesPadBlock syntax cluster boxesInside add=boxesRegStuff,boxesShapes,boxesList syntax cluster boxesInside add=boxesString,boxesPads,boxesNumber,boxesBraces " The main box design blocks BOX..END syntax region boxesDesign matchgroup=boxesBoxStmt start="box" skip="ends" end="end" keepend contains=@boxesInside skipwhite skipempty nextgroup=boxesWord " The SAMPLE block syntax region boxesSample contained matchgroup=boxesBlocks start="sample" end=+^[ \t]*ends[ \t\r]*$+ keepend contains=NONE " Comments may appear anywhere in the file syntax match boxesComment /#.*$/ " " Synchronisation " syntax sync clear syntax sync match boxesSync grouphere boxesDesign "box" " " Highlighting " if !exists("did_boxes_syntax_inits") let did_boxes_syntax_inits = 1 hi link boxesBoxStmt Define hi link boxesNumber Number hi link boxesString String hi link boxesDelSpec boxesString hi link boxesComment Comment hi link boxesError Error hi link boxesClassicKeywords Keyword hi link boxesBlocks Statement hi link boxesDelim boxesBlocks hi link boxesRegStuff Label hi link boxesShapes Type hi link boxesPads Type hi clear boxesSample hi clear boxesWord hi clear boxesBraces hi clear boxesComma endif " " The current buffer now uses "boxes" syntax highlighting " let b:current_syntax = "boxes" "EOF vim: sw=4 boxes-1.2/doc/000077500000000000000000000000001306272555200132505ustar00rootroot00000000000000boxes-1.2/doc/boxes.1.in000066400000000000000000000261041306272555200150620ustar00rootroot00000000000000.\" @(#)boxes.1 1.2 10/19/12 .\" .\" boxes.1.in .\" Thomas Jensen .\" .TH boxes 1 "March 16 2017" .UC 4 .SH NAME boxes \- text mode box and comment drawing filter .SH SYNOPSIS .B boxes [\-hlmrv] [\-a\ format] [\-d\ design] [\-f\ file] [\-i\ indent] [\-k\ bool] [\-p\ pad] [\-s\ size] [\-t\ tabopts] [infile [outfile]] .SH DESCRIPTION .I Boxes is a text filter which can draw any kind of box around its input text. Box design choices range from simple boxes to complex ASCII art. A box can also be removed and repaired, even if it has been badly damaged by editing of the text inside. Since boxes may be open on any side, .I boxes can also be used to create regional comments in any programming language. New box designs of all sorts can easily be added and shared by appending to a free format configuration file. .br .I boxes was originally intended to be used with the .I vim(1) text editor, but it can be tied to any text editor which supports filters, as well as called from the command line as a standalone tool. .\" ======================================================================= .SH OPTIONS Options offered by .I boxes are the following: .TP 0.6i .B \-a \fIstring\fP Alignment/positioning of text inside box. This option takes a format string argument which is read from left to right. The format string may not contain whitespace and must consist of one or more of the following components: .br .B h\fPx \- horizontal alignment of the input text block inside a potentially larger box. Possible values for .I x are .B l (ell, for left alignment), .B c (center), or .B r (right). This does not affect the justification of text lines within the input text block (use the .B j argument instead). .br .B v\fPx \- vertical alignment of the input text block inside a potentially larger box. Possible values for .I x are .B t (for top alignment), .B c (center), or .B b (bottom). .br .B j\fPx \- justification of lines within the input text block. Possible values for .I x are .B l (ell, for left justification), .B c (center), or .B r (right). This does not affect the alignment of the input text block itself within the box. Use the .B h and .B v arguments for input text block positioning. .br Short hand notations (can be combined with the above arguments): .br .B l (ell) \- short for .B h\fPl\fBv\fPc\fBj\fPl .br .B c \- short for .B h\fPc\fBv\fPc\fBj\fPc .br .B r \- short for .B h\fPr\fBv\fPc\fBj\fPr .br The factory default setting for .B \-a is .B h\fPl\fBv\fPt. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-c \fIstring\fP Command line design definition for simple cases. The argument of this option is the definition for the "west" (W) shape. The defined shape must consist of exactly one line, i.e. no multi\-line shapes are allowed. The .B \-c option is intended as a shortcut for those cases where simple regional comments are to be created, which only need a certain character or sequence of characters to be placed in front of every line. In such cases, it is much more convenient to simply specify .B \-c than to do a complete design definition in one's config file, where the only shape defined is the west shape. .br This option implies a .B \-d and does not access the config file. .B \-c may of course be used in conjunction with any of the other options. By default, .B \-c is not specified. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-d \fIstring\fP Design selection. The one argument of this option is the name of the design to use. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-f \fIstring\fP Use alternate config file. The one argument of this option is the name of a valid .I boxes config file, containing new and exciting designs! .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-h Print usage information. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-i \fIstring\fP Indentation mode. Possible arguments are "text" (indent text inside of box), "box" (indent box, not text inside of box), or "none" (throw away indentation). Arguments may be abbreviated. The default is to indent the box, but not the text. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-k \fIbool\fP Kill leading/trailing blank lines on removal. The value of .I bool can be specified as on, yes, true, 1, or t, all meaning yes, or off, no, false, 0, or f, which mean no. This is case\-insensitive. This option only takes effect in connection with .B \-r\fP. If set to yes, leading and trailing blank lines will be removed from the output. If set to no, the entire content of the former box is returned. The default is no, if both the top and the bottom part of the box are open, as is the case with most regional comments. If the box's design defines a top part or a bottom part, the default is yes. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-l (ell) List designs. Produces a listing of all available box designs in the config file, along with a sample box and information about it's creator. Also checks syntax of the entire config file. If used in connection with .B \-d\fP, displays detailed information about the specified design. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-m Mend box. This removes a (potentially broken) box as with .B \-r\fP, and redraws it afterwards. The mended box is drawn according to the options given. This may be important to know when it comes to restoring padding, identation, etc. for the mended box. Implies .B \-k false. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-p \fIstring\fP Padding. Specify padding in spaces around the input text block for all sides of the box. The argument string may not contain whitespace and must consist of a combination of the following characters, each followed by a number indicating the padding in spaces: .br .B a \- (all) give padding for all sides at once .br .B h \- (horiz) give padding for both horizontal sides .br .B v \- (vertical) give padding for both vertical sides .br .B b \- (bottom) give padding for bottom (south) side .br .B l \- (left) give padding for left (west) side .br .B t \- (top) give padding for top (north) side .br .B r \- (right) give padding for right (east) side .br Example: .B \-p a\fP4\fBt\fP2 would define the padding to be 4 characters on all sides, except for the top of the box, where the input text block will be only 2 lines away from the box. .br By default, unless specified otherwise in the config file, no padding is used. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-r Remove box. Removes an existing box instead of drawing it. Which design to use is detected automatically. In order to save time or in case the detection does not decide correctly, combine with .B \-d to specify the design. The default is to draw a new box. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-s \fIwidth\fBx\fPheight\fP Box size. This option specifies the desired box size in units of columns (for width) and lines (for height). If only a single number is given as argument, this number specifies the desired box width. A single number prefixed by 'x' specifies only the box height. The actual resulting box size may vary depending on the individual shape sizes of the chosen design. Also, other command line options may influence the box size (such as .B \-p\fP). .br By default, the smallest possible box is created around the text. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-t \fIstring\fP Tab handling. This option controls how tab characters in the input text are handled. The option string must always begin with a .I uint number indicating the distance between tab stops. It is important that this value be set correctly, or tabulator characters will upset your input text. The correct tab distance value depends on the settings used for the text you are processing. A common value is 8. .br Immediately following the tab distance, an optional character can be appended, telling .I boxes how to treat the leading tabs. The following options are available: .br .B e \- expand tabs into spaces .br .B k \- keep tabs as close to what they were as possible .br .B u \- unexpand tabs. This makes .I boxes turn as many spaces as possible into tabs. .br In order to maintain backwards compatibility, the .B \-t .I string can be just a number. In that case, .B e is assumed for tab handling, which removes all tabs and replaces them with spaces. The factory default for the .B \-t option is simply 8, which is just such a case. .br For example, you could specify .B \-t \fP4u in order to have your leading tabs unexpanded. In the box content, tabs are always converted into spaces. The tab distance in this example is 4. .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .TP 0.6i .B \-v Print out current version number. .\" ======================================================================= .SH CONFIGURATION FILES .I Boxes will use the configuration file specified on the command line (using .B \-f\fP). If no config file is specified on the command line, .I boxes will check for the BOXES environment variable, which may contain a filename to use. If BOXES is not set, .I boxes will try to read $HOME/.boxes and use it as a config file. Failing that, .I boxes will try to read the system\-wide config file (see FILES). .PP The syntax of .I boxes config files is described on the website (see below). They are quite self\-explanatory, though. .\" ======================================================================= .SH AVAILABILITY .I Boxes is available from its website at . The website also features a number of examples illustrating this manual page as well as more in\-depth documentation. .PP Check out .I vim(1) at ! .\" ======================================================================= .SH AUTHOR .I Boxes was made by Thomas Jensen . .br Please see the .I boxes website for a current email address. .\" ======================================================================= .SH VERSION This is .I boxes version --BVERSION--. .\" ======================================================================= .SH BUGS Although it is doing fine in most cases, imho the design autodetector needs some more work. .br Should you notice any other unspecified behavior, please tell the author! .\" ======================================================================= .SH ENVIRONMENT .I Boxes recognizes the following environment variables: .TP 1.0i HOME The user's home directory. .TP 1.0i BOXES Name of .I boxes configuration file, if different from ~/.boxes. .\" ======================================================================= .SH FILES .TP 1.0i $HOME/.boxes .I boxes configuration file .TP 1.0i --GLOBALCONF-- system\-wide configuration file .\" ======================================================================= .SH "SEE ALSO" .I tal(1) , .I vim(1) boxes-1.2/doc/boxes.el000066400000000000000000000107151306272555200147160ustar00rootroot00000000000000;;; boxes.el --- use boxes to comment regions ;; Copyright (C) 1999, 2001, 2006 Jason L. Shiffer ;; Author: Jason L. Shiffer ;; Maintainer: jshiffer@zerotao.com ;; Keywords: extensions ;; Created: 1999-10-30 ;; Others: ;; Vijay Lakshminarayanan: support for choosing boxes comment by current buffer mode. ;; 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, you can either send email to this ;; program's maintainer or write to: The Free Software Foundation, ;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA. ;;; Commentary: ;; This program provides an interface to the boxes application which can be found at ;; http://boxes.thomasjensen.com/ ;; To use this, put it somewhere in your load path and add the following ;; lines to your .emacs: ;; ;; (autoload 'boxes-command-on-region "boxes" nil t) ;; (autoload 'boxes-remove "boxes" nil t) ;; (autoload 'boxes-create "boxes" nil t) ;; (global-set-key "\C-cq" 'boxes-create) ;; (global-set-key "\C-cr" 'boxes-remove) ;;; Code: (eval-when-compile (require 'cl)) ;;;###autoload (defvar boxes-command "boxes" "The boxes command.") (defvar boxes-types-alist (ignore-errors (with-temp-buffer (call-process "boxes" nil t nil "-l") (goto-char (point-min)) (let ((retval nil)) (while (re-search-forward "^\\([a-zA-Z][a-zA-Z0-9-]+\\) (.*):" nil t) (add-to-list 'retval (cons (match-string 1) (match-string 1)))) retval))) "Association of types available to the current boxes implementation." ) (make-variable-buffer-local 'boxes-types-alist) (defvar boxes-history nil) ;;;###autoload (defvar boxes-known-modes '((c-mode . "c-cmt2") (c++-mode . "c-cmt2") (java-mode . "java-cmt") (html-mode . "html-cmt") (sh-mode . "pound-cmt") (perl-mode . "pound-cmt") (python-mode . "pound-cmt") (ruby-mode . "pound-cmt") (emacs-lisp-mode . "lisp-cmt") (lisp-mode . "lisp-cmt")) "The default comment type based on file names.") (make-variable-buffer-local 'boxes-known-modes) ;;;###autoload (defun boxes-set-default-type (mode) "Set the default box mode according to the buffer's major mode." (setq boxes-default-type (or (cdr (assoc mode boxes-known-modes)) "c-cmt2"))) ;;;###autoload (defvar boxes-default-type nil "The default type of comment.") (make-variable-buffer-local 'boxes-default-type) ;;;###autoload (defvar boxes-args "" "Arguments to the boxes command.") (make-variable-buffer-local 'boxes-args) ;;;###autoload (defun boxes-create () "Automagicly create a new box around the region based on the default type." (interactive "*") (boxes-command-on-region (region-beginning) (region-end) boxes-default-type)) ;;;###autoload (defun boxes-remove () "Automagicly remove a new box around the region based on the default type." (interactive "*") (boxes-command-on-region (region-beginning) (region-end) boxes-default-type 1)) ;;;###autoload (defun boxes-command-on-region (start end type &optional remove) "Create/Remove boxes from a region. To create just select a region and M-x boxes-command-on-region then you will be prompted to enter a box type. The type selection can use tab completion on the types available. To remove a box simply prefix a 1 to the callL M-1 M-x boxes-command-on-region will remove a box from a region." (interactive (let ((string (completing-read (format "Box type (%s): " boxes-default-type) boxes-types-alist nil t nil 'boxes-history boxes-default-type))) (list (region-beginning) (region-end) string current-prefix-arg))) (if type (setq boxes-default-type type) (setq boxes-default-type (boxes-set-default-type major-mode) type boxes-default-type)) (let ((command-string (concat boxes-command (if remove (concat boxes-args " -r ")) (if type (concat boxes-args " -d " type))))) (shell-command-on-region start end command-string nil 1))) (provide 'boxes) ;;; boxes.el ends here boxes-1.2/doc/makehtmlman000066400000000000000000000010001306272555200154600ustar00rootroot00000000000000# Note: Better user vh-man2html !! outfile=boxes.1.shtml if [ -e $outfile ]; then cp -a $outfile $outfile"."$$".bak" fi cat ./boxes.1 | sed -e 's/^\.br/--LINEBREAK--/' | man -l - | man2html -title 'boxes(1)' | sed -e 's/boxes@thomasjensen.com/boxes(at)thomasjensen(dot)com/g' -e 's/<URL:\([^&]\+\)>/\1<\/a>/g' -e 's/<\/BODY>/\n\n\n<\/BODY>/' > $outfile echo "Conversion complete. Excessive manual work remains." # vim: set wrap : boxes-1.2/src/000077500000000000000000000000001306272555200132725ustar00rootroot00000000000000boxes-1.2/src/Makefile000066400000000000000000000102211306272555200147260ustar00rootroot00000000000000# # File: Makefile.Win32 # Creation: March 18, 1999 (Thursday, 15:10h) # Author: Copyright (C) 1999 Thomas Jensen # Win32 Modifications by Ron Aaron # Format: GNU make # Web Site: http://boxes.thomasjensen.com/ # Platforms: win32 # Purpose: Makefile for boxes, the box drawing program # # License: o 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. # o 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. # o 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 #____________________________________________________________________________ #============================================================================ LEX = flex YACC = bison CC = gcc GEN_HDR = parser.h boxes.h GEN_SRC = parser.c lex.yy.c GEN_FILES = $(GEN_SRC) $(GEN_HDR) ORIG_HDRCL = boxes.h.in config.h ORIG_HDR = $(ORIG_HDRCL) lexer.h tools.h shape.h generate.h remove.h ORIG_GEN = lexer.l parser.y ORIG_NORM = boxes.c tools.c shape.c generate.c remove.c ORIG_SRC = $(ORIG_GEN) $(ORIG_NORM) ORIG_FILES = $(ORIG_SRC) $(ORIG_HDR) OTH_FILES = Makefile ALL_FILES = $(ORIG_FILES) $(GEN_FILES) $(OTH_FILES) .PHONY: clean build debug package flags_unix flags_win32 flags_ build: flags_$(BOXES_PLATFORM) $(MAKE) BOXES_PLATFORM=$(BOXES_PLATFORM) ALL_OBJ="$(ALL_OBJ)" CFLAGS_ADDTL="-O $(CFLAGS_ADDTL)" STRIP=true flags_$(BOXES_PLATFORM) $(BOXES_EXECUTABLE_NAME) debug: flags_$(BOXES_PLATFORM) $(MAKE) BOXES_PLATFORM=$(BOXES_PLATFORM) ALL_OBJ="$(ALL_OBJ)" CFLAGS_ADDTL="-g $(CFLAGS_ADDTL)" STRIP=false flags_$(BOXES_PLATFORM) $(BOXES_EXECUTABLE_NAME) boxes: $(ALL_OBJ) $(MAKE) -C regexp CC=$(CC) libregexp.a $(CC) $(LDFLAGS) $(ALL_OBJ) -o $(BOXES_EXECUTABLE_NAME) -lregexp if [ $(STRIP) == true ] ; then strip $(BOXES_EXECUTABLE_NAME) ; fi boxes.exe: $(ALL_OBJ) $(CC) $(LDFLAGS) $(ALL_OBJ) -o $(BOXES_EXECUTABLE_NAME) -lkernel32 if [ $(STRIP) == true ] ; then strip $(BOXES_EXECUTABLE_NAME) ; fi flags_unix: $(eval CFLAGS := -I. -Iregexp -Wall -W $(CFLAGS_ADDTL)) $(eval LDFLAGS := -Lregexp $(LDFLAGS_ADDTL)) $(eval BOXES_EXECUTABLE_NAME := boxes) $(eval ALL_OBJ := $(GEN_SRC:.c=.o) $(ORIG_NORM:.c=.o)) flags_win32: $(eval CFLAGS := -Os -s -m32 -I. -Iregexp -Wall -W $(CFLAGS_ADDTL)) $(eval LDFLAGS := -s -m32) $(eval BOXES_EXECUTABLE_NAME := boxes.exe) $(eval ALL_OBJ := $(GEN_SRC:.c=.o) $(ORIG_NORM:.c=.o) regexp/regexp.o regexp/regsub.o misc/getopt.o) flags_: @echo Please call make from the top level directory. exit 1 parser.c parser.h: parser.y boxes.h regexp/regexp.h $(YACC) -o parser.c -d parser.y lex.yy.c: lexer.l boxes.h $(LEX) -t lexer.l > lexer.tmp.c echo '#include "config.h"' > lex.yy.c cat lexer.tmp.c >> lex.yy.c rm lexer.tmp.c boxes.o: boxes.c boxes.h regexp/regexp.h shape.h tools.h generate.h remove.h config.h tools.o: tools.c tools.h boxes.h shape.h config.h shape.o: shape.c shape.h boxes.h config.h tools.h generate.o: generate.c generate.h boxes.h shape.h tools.h config.h remove.o: remove.c remove.h boxes.h shape.h tools.h config.h lex.yy.o: lex.yy.c parser.h tools.h shape.h lexer.h config.h parser.o: parser.c parser.h tools.h shape.h lexer.h config.h regexp/regexp.o: regexp/regexp.c regexp/regsub.o: regexp/regsub.c misc/getopt.o: misc/getopt.c package: $(BOXES_EXECUTABLE_NAME) if [ -z "$(PKG_NAME)" ] ; then exit 1 ; fi cp $(BOXES_EXECUTABLE_NAME) ../$(PKG_NAME) clean: flags_unix rm -f $(ALL_OBJ) rm -f $(GEN_FILES) rm -f core boxes boxes.exe $(MAKE) -C regexp clean #EOF boxes-1.2/src/boxes.c000066400000000000000000001566431306272555200145750ustar00rootroot00000000000000/* * File: boxes.c * Date created: March 18, 1999 (Thursday, 15:09h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Filter to draw boxes around input text (and remove it). * * License: o 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. * o 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. * o 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 * * - This version is leaking small bits of memory. Since boxes * runs as a filter in its own process, the leaks are irrelevant. * - The decision to number box shapes in clockwise order was a * major design mistake. Treatment of box parts of the same * alignment (N-S and E-W) is usually combined in one function, * which must now deal with the numbering being reversed all the * time. This is nasty, but changing the shape order would * pretty much mean a total rewrite of the code, so we'll have * to live with it. * - All shapes defined in a box design must be used in any box of * that design at least once. In other words, there must not be * a shape which is defined in the config file but cannot be * found in an actual box of that design. This sort of limits * how small your boxes can get. However, in practice it is not * a problem, because boxes which must be small usually consist * of small shapes which can be packed pretty tightly anyway. * And again, changing this would pretty much mean a total * rewrite. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "config.h" #include #include #include #include #include #include #include #include #include "shape.h" #include "boxes.h" #include "tools.h" #include "regexp.h" #include "generate.h" #include "remove.h" #ifdef __MINGW32__ #include #endif extern char *optarg; /* for getopt() */ extern int optind, opterr, optopt; /* for getopt() */ #ifdef __MINGW32__ #define BOXES_CONFIG "boxes.cfg" /* filename of config file in $HOME */ #else #define BOXES_CONFIG ".boxes" #endif static const char rcsid_boxes_c[] = "$Id: boxes.c,v 1.39 2006/08/28 15:53:46 tsjensen Exp $"; /* _\|/_ (o o) +----oOO-{_}-OOo------------------------------------------------------------+ | G l o b a l V a r i a b l e s | +--------------------------------------------------------------------------*/ extern int yyparse(); extern FILE *yyin; /* lex input file */ char *yyfilename = NULL; /* file name of config file used */ design_t *designs = NULL; /* available box designs */ int design_idx = 0; /* anz_designs-1 */ int anz_designs = 0; /* no of designs after parsing */ opt_t opt; /* command line options */ input_t input = INPUT_INITIALIZER; /* input lines */ /* _\|/_ (o o) +----oOO-{_}-OOo------------------------------------------------------------+ | F u n c t i o n s | +--------------------------------------------------------------------------*/ static void usage (FILE *st) /* * Print usage information on stream st. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { fprintf (st, "Usage: %s [options] [infile [outfile]]\n", PROJECT); fprintf (st, " -a fmt alignment/positioning of text inside box [default: hlvt]\n"); fprintf (st, " -c str use single shape box design where str is the W shape\n"); fprintf (st, " -d name box design [default: first one in file]\n"); fprintf (st, " -f file configuration file\n"); fprintf (st, " -h print usage information\n"); fprintf (st, " -i mode indentation mode [default: box]\n"); fprintf (st, " -k bool leading/trailing blank line retention on removal\n"); fprintf (st, " -l list available box designs w/ samples\n"); fprintf (st, " -m mend box, i.e. remove it and redraw it afterwards\n"); fprintf (st, " -p fmt padding [default: none]\n"); fprintf (st, " -r remove box\n"); fprintf (st, " -s wxh box size (width w and/or height h)\n"); fprintf (st, " -t str tab stop distance and expansion [default: %de]\n", DEF_TABSTOP); fprintf (st, " -v print version information\n"); } static void usage_short (FILE *st) /* * Print abbreviated usage information on stream st. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { fprintf (st, "Usage: %s [options] [infile [outfile]]\n", PROJECT); fprintf (st, "Try `%s -h' for more information.\n", PROJECT); } static void usage_long (FILE *st) /* * Print usage information on stream st, including a header text. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { fprintf (st, "%s - draws any kind of box around your text (and removes it)\n", PROJECT); fprintf (st, " (c) Thomas Jensen \n"); fprintf (st, " Web page: http://boxes.thomasjensen.com/\n"); usage (st); } static int is_dir (const char *path) /* * Return true if file specified by path is a directory * * path file name to check * * On Windows, this check seems unnecessary, because fopen() seems to fail * when applied to a directory. * * RETURNS: == 0 path is not a directory * > 0 path is a directory * == -1 error in stat() call * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { struct stat sinf; int rc; rc = stat (path, &sinf); if (rc) { perror (PROJECT); return -1; } return S_ISDIR(sinf.st_mode); } static int get_config_file() /* * Set yyin and yyfilename to the config file to be used. * * If no config file was specified on the command line (yyin == stdin), * try getting it from other locations: * (1) contents of BOXES environment variable * (2) file ~/.boxes * (3) system-wide config file from GLOBALCONF macro. * If neither file exists, return complainingly. * * May change current working directory to $HOME. * * RETURNS: == 0 success (yyin and yyfilename are set) * != 0 error (yyin is unmodified) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { FILE *new_yyin = NULL; char *s; /* points to data from environment */ int rc; #ifdef __MINGW32__ char exepath[256]; /* for constructing config file path */ #endif if (yyin != stdin) return 0; /* we're already ok */ /* * Try getting it from the BOXES environment variable */ s = getenv ("BOXES"); if (s) { new_yyin = fopen (s, "r"); if (new_yyin == NULL) { fprintf (stderr, "%s: Couldn't open config file '%s' " "for input (taken from $BOXES).\n", PROJECT, s); return 1; } rc = is_dir (s); if (rc == -1) { fclose (new_yyin); return 1; } else if (rc) { fprintf (stderr, "%s: Alleged config file '%s' is a directory " "(taken from $BOXES)\n", PROJECT, s); fclose (new_yyin); return 1; } yyfilename = (char *) strdup (s); if (yyfilename == NULL) { perror (PROJECT); fclose (new_yyin); return 1; } yyin = new_yyin; return 0; } /* * Try getting it from ~/.boxes */ s = getenv ("HOME"); if (s) { rc = chdir (s); if (rc) { perror (PROJECT); return 1; } new_yyin = fopen (BOXES_CONFIG, "r"); if (new_yyin) { rc = is_dir (BOXES_CONFIG); if (rc == -1) { fclose (new_yyin); return 1; } else { if (rc == 0) { yyfilename = (char *) strdup (BOXES_CONFIG); if (yyfilename == NULL) { perror (PROJECT); fclose (new_yyin); return 1; } yyin = new_yyin; return 0; } else { fclose (new_yyin); new_yyin = NULL; } } } } else { #ifndef __MINGW32__ /* Do not print this warning on windows. */ fprintf (stderr, "%s: warning: Environment variable HOME not set!\n", PROJECT); #endif } /* * Try reading the system-wide config file * On UNIX, the global config file must be given by the GLOBALCONF macro. * On Win32, it is expected to reside in the same directory as the binary * used, and its name is assumed to be execfilename+".cfg". */ #ifdef __MINGW32__ if (GetModuleFileName (NULL, exepath, 255) != 0) { char *p = strrchr (exepath, '.') + 1; if (p) { /* p is always != NULL, because we get the full path */ *p = '\0'; if (strlen(exepath) < 253) { strcat (exepath, "cfg"); /* c:\blah\boxes.cfg */ } else { fprintf (stderr, "%s: path too long. Using C:\\boxes.cfg.\n", PROJECT); strcpy (exepath, "C:\\boxes.cfg"); } } } else { strcpy (exepath, "C:\\boxes.cfg"); } new_yyin = fopen (exepath, "r"); #else new_yyin = fopen (GLOBALCONF, "r"); #endif if (new_yyin) { #ifdef __MINGW32__ yyfilename = (char *) strdup (exepath); #else rc = is_dir (GLOBALCONF); if (rc == -1) { fclose (new_yyin); return 1; } else if (rc) { fprintf (stderr, "%s: Alleged system-wide config file '%s' " "is a directory\n", PROJECT, GLOBALCONF); fclose (new_yyin); return 1; } yyfilename = (char *) strdup (GLOBALCONF); #endif if (yyfilename == NULL) { perror (PROJECT); fclose (new_yyin); return 1; } yyin = new_yyin; return 0; } /* * Darn. No luck today. */ fprintf (stderr, "%s: Can't find config file.\n", PROJECT); return 2; } static int process_commandline (int argc, char *argv[]) /* * Process command line options. * * argc, argv command line as passed to main() * * RETURNS: == 0 success, continue * == 42 success, but terminate anyway (e.g. help/version) * != 0/42 error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int oc; /* option character */ FILE *f; /* potential input file */ int idummy; char *pdummy; char c; int errfl = 0; /* true on error */ size_t optlen; int rc; /* * Set default values */ memset (&opt, 0, sizeof(opt_t)); opt.tabstop = DEF_TABSTOP; opt.tabexp = 'e'; opt.killblank = -1; for (idummy=0; idummy= 2 && argv[1] != NULL && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)) { usage_long (stdout); return 42; } /* * Parse Command Line */ do { oc = getopt (argc, argv, "a:c:d:f:hi:k:lmp:rs:t:v"); switch (oc) { case 'a': /* * Alignment/positioning of text inside box */ errfl = 0; pdummy = optarg; while (*pdummy) { if (pdummy[1] == '\0' && !strchr ("lLcCrR", *pdummy)) { errfl = 1; break; } switch (*pdummy) { case 'h': case 'H': switch (pdummy[1]) { case 'c': case 'C': opt.halign = 'c'; break; case 'l': case 'L': opt.halign = 'l'; break; case 'r': case 'R': opt.halign = 'r'; break; default: errfl = 1; break; } ++pdummy; break; case 'v': case 'V': switch (pdummy[1]) { case 'c': case 'C': opt.valign = 'c'; break; case 't': case 'T': opt.valign = 't'; break; case 'b': case 'B': opt.valign = 'b'; break; default: errfl = 1; break; } ++pdummy; break; case 'j': case 'J': switch (pdummy[1]) { case 'l': case 'L': opt.justify = 'l'; break; case 'c': case 'C': opt.justify = 'c'; break; case 'r': case 'R': opt.justify = 'r'; break; default: errfl = 1; break; } ++pdummy; break; case 'l': case 'L': opt.justify = 'l'; opt.halign = 'l'; opt.valign = 'c'; break; case 'r': case 'R': opt.justify = 'r'; opt.halign = 'r'; opt.valign = 'c'; break; case 'c': case 'C': opt.justify = 'c'; opt.halign = 'c'; opt.valign = 'c'; break; default: errfl = 1; break; } if (errfl) break; else ++pdummy; } if (errfl) { fprintf (stderr, "%s: Illegal text format -- %s\n", PROJECT, optarg); return 1; } break; case 'c': /* * Command line design definition */ opt.cld = (char *) strdup (optarg); if (opt.cld == NULL) { perror (PROJECT); return 1; } else { line_t templine = {0}; templine.len = strlen (opt.cld); templine.text = opt.cld; if (empty_line(&templine)) { fprintf (stderr, "%s: boxes may not consist entirely " "of whitespace\n", PROJECT); return 1; } } opt.design_choice_by_user = 1; break; case 'd': /* * Box design selection */ BFREE (opt.design); opt.design = (design_t *) ((char *) strdup (optarg)); if (opt.design == NULL) { perror (PROJECT); return 1; } opt.design_choice_by_user = 1; break; case 'f': /* * Input File */ f = fopen (optarg, "r"); if (f == NULL) { fprintf (stderr, "%s: Couldn\'t open config file \'%s\' " "for input.\n", PROJECT, optarg); return 1; } rc = is_dir (optarg); if (rc == -1) { fclose (f); return 1; } else if (rc) { fprintf (stderr, "%s: Alleged config file '%s' is a " "directory\n", PROJECT, optarg); fclose (f); return 1; } yyfilename = (char *) strdup (optarg); if (yyfilename == NULL) { perror (PROJECT); fclose (f); return 1; } yyin = f; break; case 'h': /* * Display usage information and terminate */ usage_long (stdout); return 42; case 'i': /* * Indentation mode */ optlen = strlen (optarg); if (optlen <= 3 && !strncasecmp ("box", optarg, optlen)) opt.indentmode = 'b'; else if (optlen <= 4 && !strncasecmp ("text", optarg, optlen)) opt.indentmode = 't'; else if (optlen <= 4 && !strncasecmp ("none", optarg, optlen)) opt.indentmode = 'n'; else { fprintf (stderr, "%s: invalid indentation mode\n", PROJECT); return 1; } break; /* * Kill blank lines or not [default: design-dependent] */ case 'k': if (opt.killblank == -1) { if (strisyes (optarg)) opt.killblank = 1; else if (strisno (optarg)) opt.killblank = 0; else { fprintf (stderr, "%s: -k: invalid parameter\n", PROJECT); return 1; } } break; case 'l': /* * List available box styles */ opt.l = 1; break; case 'm': /* * Mend box: remove, then redraw */ opt.mend = 2; opt.r = 1; opt.killblank = 0; break; case 'p': /* * Padding. format is ([ahvtrbl]n)+ */ errfl = 0; pdummy = optarg; while (*pdummy) { if (pdummy[1] == '\0') { errfl = 1; break; } c = *pdummy; errno = 0; idummy = (int) strtol (pdummy+1, &pdummy, 10); if (errno || idummy < 0) { errfl = 1; break; } switch (c) { case 'a': case 'A': opt.padding[BTOP] = idummy; opt.padding[BBOT] = idummy; opt.padding[BLEF] = idummy; opt.padding[BRIG] = idummy; break; case 'h': case 'H': opt.padding[BLEF] = idummy; opt.padding[BRIG] = idummy; break; case 'v': case 'V': opt.padding[BTOP] = idummy; opt.padding[BBOT] = idummy; break; case 't': case 'T': opt.padding[BTOP] = idummy; break; case 'l': case 'L': opt.padding[BLEF] = idummy; break; case 'b': case 'B': opt.padding[BBOT] = idummy; break; case 'r': case 'R': opt.padding[BRIG] = idummy; break; default: errfl = 1; break; } if (errfl) break; } if (errfl) { fprintf (stderr, "%s: invalid padding specification - " "%s\n", PROJECT, optarg); return 1; } break; case 'r': /* * Remove box from input */ opt.r = 1; break; case 's': /* * Specify desired box target size */ pdummy = strchr (optarg, 'x'); if (!pdummy) pdummy = strchr (optarg, 'X'); if(pdummy) { *pdummy = '\0'; } errno = 0; if (optarg != pdummy) opt.reqwidth = strtol (optarg, NULL, 10); if (pdummy) { opt.reqheight = strtol (pdummy+1, NULL, 10); *pdummy = 'x'; } if(errno){ fprintf (stderr, "%s: box size: %s, '%s'\n", PROJECT, strerror(idummy), optarg); return 1; } else if ((opt.reqwidth == 0 && opt.reqheight == 0) || opt.reqwidth < 0 || opt.reqheight < 0) { fprintf (stderr, "%s: invalid box size specification -- %s\n", PROJECT, optarg); return 1; } break; case 't': /* * Tab handling. Format is n[eku] */ idummy = (int) strtol (optarg, &pdummy, 10); if (idummy < 1 || idummy > MAX_TABSTOP) { fprintf (stderr, "%s: invalid tab stop distance -- %d\n", PROJECT, idummy); return 1; } opt.tabstop = idummy; errfl = 0; if (*pdummy != '\0') { if (pdummy[1] != '\0') { errfl = 1; } else { switch (*pdummy) { case 'e': case 'E': opt.tabexp = 'e'; break; case 'k': case 'K': opt.tabexp = 'k'; break; case 'u': case 'U': opt.tabexp = 'u'; break; default: errfl = 1; break; } } } if (errfl) { fprintf (stderr, "%s: invalid tab handling specification - " "%s\n", PROJECT, optarg); return 1; } break; case 'v': /* * Print version number */ printf ("%s version %s\n", PROJECT, VERSION); return 42; case ':': case '?': /* * Missing argument or illegal option - do nothing else */ usage_short (stderr); return 1; case EOF: /* * End of list, do nothing more */ break; default: /* This case must never be */ fprintf (stderr, "%s: internal error\n", PROJECT); return 1; } } while (oc != EOF); /* * Input and Output Files * * After any command line options, an input file and an output file may * be specified (in that order). "-" may be substituted for standard * input or output. A third file name would be invalid. */ if (argv[optind] == NULL) { /* neither infile nor outfile given */ opt.infile = stdin; opt.outfile = stdout; } else if (argv[optind+1] && argv[optind+2]) { /* illegal third file */ fprintf (stderr, "%s: illegal parameter -- %s\n", PROJECT, argv[optind+2]); usage_short (stderr); return 1; } else { if (strcmp (argv[optind], "-") == 0) { opt.infile = stdin; /* use stdin for input */ } else { opt.infile = fopen (argv[optind], "r"); if (opt.infile == NULL) { fprintf (stderr, "%s: Can\'t open input file -- %s\n", PROJECT, argv[optind]); return 9; /* can't read infile */ } } if (argv[optind+1] == NULL) { opt.outfile = stdout; /* no outfile given */ } else if (strcmp (argv[optind+1], "-") == 0) { opt.outfile = stdout; /* use stdout for output */ } else { opt.outfile = fopen (argv[optind+1], "w"); if (opt.outfile == NULL) { perror (PROJECT); if (opt.infile != stdin) fclose (opt.infile); return 10; } } } /* * If no config file has been specified yet, try getting it elsewhere. */ if (opt.cld == NULL) { rc = get_config_file(); /* sets yyin and yyfilename */ if (rc) /* may change working directory */ return rc; } #if defined(DEBUG) || 0 fprintf (stderr, "Command line option settings (excerpt):\n"); fprintf (stderr, "- Padding: l:%d t:%d r:%d b:%d\n", opt.padding[BLEF], opt.padding[BTOP], opt.padding[BRIG], opt.padding[BBOT]); fprintf (stderr, "- Requested box size: %ldx%ld\n", opt.reqwidth, opt.reqheight); fprintf (stderr, "- Tabstop distance: %d\n", opt.tabstop); fprintf (stderr, "- Tab handling: \'%c\'\n", opt.tabexp); fprintf (stderr, "- Alignment: horiz %c, vert %c\n", opt.halign?opt.halign:'?', opt.valign?opt.valign:'?'); fprintf (stderr, "- Indentmode: \'%c\'\n", opt.indentmode? opt.indentmode: '?'); fprintf (stderr, "- Line justification: \'%c\'\n", opt.justify? opt.justify: '?'); fprintf (stderr, "- Kill blank lines: %d\n", opt.killblank); fprintf (stderr, "- Remove box: %d\n", opt.r); fprintf (stderr, "- Mend box: %d\n", opt.mend); fprintf (stderr, "- Design Definition W shape: %s\n", opt.cld? opt.cld: "n/a"); #endif return 0; } static int build_design (design_t **adesigns, const char *cld) /* * Build a box design. * * adesigns Pointer to global designs list * cld the W shape as specified on the command line * * Builds the global design list containing only one design which was * built from the -c command line definition. * * RETURNS: != 0 on error (out of memory) * == 0 on success * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { design_t *dp; /* pointer to design to be created */ sentry_t *c; /* pointer to current shape */ int i; int rc; *adesigns = (design_t *) calloc (1, sizeof(design_t)); if (*adesigns == NULL) { perror (PROJECT); return 1; } dp = *adesigns; /* for readability */ dp->name = ""; dp->created = "now"; dp->revision = "1.0"; dp->sample = "n/a"; dp->indentmode = DEF_INDENTMODE; dp->padding[BLEF] = 1; dp->shape[W].height = 1; dp->shape[W].width = strlen(cld); dp->shape[W].elastic = 1; rc = genshape (dp->shape[W].width, dp->shape[W].height, &(dp->shape[W].chars)); if (rc) return rc; strcpy (dp->shape[W].chars[0], cld); for (i=0; ishape + i; if (i == NNW || i == NNE || i == WNW || i == ENE || i == W || i == WSW || i == ESE || i == SSW || i == SSE) continue; switch (i) { case NW: case SW: c->width = dp->shape[W].width; c->height = 1; c->elastic = 0; break; case NE: case SE: c->width = 1; c->height = 1; c->elastic = 0; break; case N: case S: case E: c->width = 1; c->height = 1; c->elastic = 1; break; default: fprintf (stderr, "%s: internal error\n", PROJECT); return 1; /* never happens ;-) */ } rc = genshape (c->width, c->height, &(c->chars)); if (rc) return rc; } dp->maxshapeheight = 1; dp->minwidth = dp->shape[W].width + 2; dp->minheight = 3; return 0; } static int style_sort (const void *p1, const void *p2) { return strcasecmp ((const char *) ((*((design_t **) p1))->name), (const char *) ((*((design_t **) p2))->name)); } static int list_styles() /* * Generate sorted listing of available box styles. * Uses design name from BOX spec and sample picture plus author. * * RETURNS: != 0 on error (out of memory) * == 0 on success * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int i; if (opt.design_choice_by_user) { design_t *d = opt.design; int until = -1; int sstart = 0; size_t w = 0; size_t j; char space[LINE_MAX+1]; memset (&space, ' ', LINE_MAX); space[LINE_MAX] = '\0'; fprintf (opt.outfile, "Complete Design Information for \"%s\":\n", d->name); fprintf (opt.outfile, "-----------------------------------"); for (i=strlen(d->name); i>0; --i) fprintf (opt.outfile, "-"); fprintf (opt.outfile, "\n"); fprintf (opt.outfile, "Author: %s\n", d->author? d->author: "(unknown author)"); fprintf (opt.outfile, "Original Designer: %s\n", d->designer? d->designer: "(unknown artist)"); fprintf (opt.outfile, "Creation Date: %s\n", d->created? d->created: "(unknown)"); fprintf (opt.outfile, "Current Revision: %s%s%s\n", d->revision? d->revision: "", d->revision && d->revdate? " as of ": "", d->revdate? d->revdate: (d->revision? "": "(unknown)")); fprintf (opt.outfile, "Indentation Mode: "); switch (d->indentmode) { case 'b': fprintf (opt.outfile, "box (indent box)\n"); break; case 't': fprintf (opt.outfile, "text (retain indentation inside of box)\n"); break; default: fprintf (opt.outfile, "none (discard indentation)\n"); break; } fprintf (opt.outfile, "Replacement Rules: "); if (d->anz_reprules > 0) { for (i=0; i<(int)d->anz_reprules; ++i) { fprintf (opt.outfile, "%d. (%s) \"%s\" WITH \"%s\"\n", i+1, d->reprules[i].mode == 'g'? "glob": "once", d->reprules[i].search, d->reprules[i].repstr); if (i < (int) d->anz_reprules - 1) fprintf (opt.outfile, " "); } } else { fprintf (opt.outfile, "none\n"); } fprintf (opt.outfile, "Reversion Rules: "); if (d->anz_revrules > 0) { for (i=0; i<(int)d->anz_revrules; ++i) { fprintf (opt.outfile, "%d. (%s) \"%s\" TO \"%s\"\n", i+1, d->revrules[i].mode == 'g'? "glob": "once", d->revrules[i].search, d->revrules[i].repstr); if (i < (int) d->anz_revrules - 1) fprintf (opt.outfile, " "); } } else { fprintf (opt.outfile, "none\n"); } fprintf (opt.outfile, "Minimum Box Dimensions: %d x %d (width x height)\n", d->minwidth, d->minheight); fprintf (opt.outfile, "Default Padding: "); if (d->padding[BTOP] || d->padding[BRIG] || d->padding[BBOT] || d->padding[BLEF]) { if (d->padding[BLEF]) { fprintf (opt.outfile, "left %d", d->padding[BLEF]); if (d->padding[BTOP] || d->padding[BRIG] || d->padding[BBOT]) fprintf (opt.outfile, ", "); } if (d->padding[BTOP]) { fprintf (opt.outfile, "top %d", d->padding[BTOP]); if (d->padding[BRIG] || d->padding[BBOT]) fprintf (opt.outfile, ", "); } if (d->padding[BRIG]) { fprintf (opt.outfile, "right %d", d->padding[BRIG]); if (d->padding[BBOT]) fprintf (opt.outfile, ", "); } if (d->padding[BBOT]) fprintf (opt.outfile, "bottom %d", d->padding[BBOT]); fprintf (opt.outfile, "\n"); } else { fprintf (opt.outfile, "none\n"); } fprintf (opt.outfile, "Default Killblank: %s\n", empty_side (opt.design->shape, BTOP) && empty_side (opt.design->shape, BBOT)? "no": "yes"); fprintf (opt.outfile, "Elastic Shapes: "); sstart = 0; for (i=0; ishape+i)) continue; if (d->shape[i].elastic) { fprintf (opt.outfile, "%s%s", sstart? ", ": "", shape_name[i]); sstart = 1; } } fprintf (opt.outfile, "\n"); /* * Display all shapes */ fprintf (opt.outfile, "Defined Shapes: "); until = -1; sstart = 0; do { sstart = until + 1; for (w=0, i=sstart; ishape+i)) continue; w += 6; w += d->shape[i].width; w += strlen(shape_name[i]); if (i == 0) w -= 2; else if (w > 56) { /* assuming an 80 character screen */ until = i - 1; break; } } if (i == ANZ_SHAPES) until = ANZ_SHAPES - 1; for (w=0, i=sstart; i<=until; ++i) { if (d->shape[i].height > w) w = d->shape[i].height; } for (j=0; j 0 || sstart > 0) fprintf (opt.outfile, " "); for (i=sstart; i<=until; ++i) { if (isempty(d->shape+i)) continue; fprintf (opt.outfile, " "); if (j == 0) fprintf (opt.outfile, "%s: ", shape_name[i]); else { space[strlen(shape_name[i])+2] = '\0'; fprintf (opt.outfile, "%s", space); space[strlen(shape_name[i])+2] = ' '; } if (j < d->shape[i].height) { fprintf (opt.outfile, "\"%s\"", d->shape[i].chars[j]); } else { space[d->shape[i].width+2] = '\0'; fprintf (opt.outfile, "%s", space); space[d->shape[i].width+2] = ' '; } } fprintf (opt.outfile, "\n"); } if (until < ANZ_SHAPES-1 && d->maxshapeheight > 2) fprintf (opt.outfile, "\n"); } while (until < ANZ_SHAPES-1); } else { design_t **list; /* temp list for sorting */ char buf[42]; list = (design_t **) calloc (design_idx+1, sizeof(design_t *)); if (list == NULL) { perror (PROJECT); return 1; } for (i=0; i0; --i) fprintf (opt.outfile, "-"); fprintf (opt.outfile, "\n\n"); for (i=0; iauthor && list[i]->designer && strcmp(list[i]->author, list[i]->designer) != 0) { fprintf(opt.outfile, "%s\n%s, coded by %s:\n\n%s\n\n", list[i]->name, list[i]->designer, list[i]->author, list[i]->sample); } else if (list[i]->designer) { fprintf(opt.outfile, "%s\n%s:\n\n%s\n\n", list[i]->name, list[i]->designer, list[i]->sample); } else if (list[i]->author) { fprintf(opt.outfile, "%s\nunknown artist, coded by %s:\n\n%s\n\n", list[i]->name, list[i]->author, list[i]->sample); } else { fprintf(opt.outfile, "%s:\n\n%s\n\n", list[i]->name, list[i]->sample); } } BFREE (list); } return 0; } static int get_indent (const line_t *lines, const size_t lanz) /* * Determine indentation of given lines in spaces. * * lines the lines to examine * lanz number of lines to examine * * Lines are assumed to be free of trailing whitespace. * * RETURNS: >= 0 indentation in spaces * < 0 error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t j; int res = LINE_MAX; /* result */ int nonblank = 0; /* true if one non-blank line found */ if (lines == NULL) { fprintf (stderr, "%s: internal error\n", PROJECT); return -1; } if (lanz == 0) return 0; for (j=0; j 0) { size_t ispc; nonblank = 1; ispc = strspn (lines[j].text, " "); if ((int) ispc < res) res = ispc; } } if (nonblank) return res; /* success */ else return 0; /* success, but only blank lines */ } static int apply_substitutions (const int mode) /* * Apply regular expression substitutions to input text. * * mode == 0 use replacement rules (box is being *drawn*) * == 1 use reversion rules (box is being *removed*) * * Attn: This modifies the actual input array! * * RETURNS: == 0 success * != 0 error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t anz_rules; reprule_t *rules; size_t j, k; char buf[LINE_MAX*2]; size_t buf_len; /* length of string in buf */ if (opt.design == NULL) return 1; if (mode == 0) { anz_rules = opt.design->anz_reprules; rules = opt.design->reprules; } else if (mode == 1) { anz_rules = opt.design->anz_revrules; rules = opt.design->revrules; } else { fprintf (stderr, "%s: internal error\n", PROJECT); return 2; } /* * Compile regular expressions */ errno = 0; opt.design->current_rule = rules; for (j=0; jcurrent_rule)) { rules[j].prog = regcomp (rules[j].search); } opt.design->current_rule = NULL; if (errno) return 3; /* * Apply regular expression substitutions to input lines */ for (k=0; kcurrent_rule = rules; for (j=0; jcurrent_rule)) { #ifdef REGEXP_DEBUG fprintf (stderr, "myregsub (0x%p, \"%s\", %d, \"%s\", buf, %d, \'%c\') == ", rules[j].prog, input.lines[k].text, input.lines[k].len, rules[j].repstr, LINE_MAX*2, rules[j].mode); #endif errno = 0; buf_len = myregsub (rules[j].prog, input.lines[k].text, input.lines[k].len, rules[j].repstr, buf, LINE_MAX*2, rules[j].mode); #ifdef REGEXP_DEBUG fprintf (stderr, "%d\n", buf_len); #endif if (errno) return 1; BFREE (input.lines[k].text); input.lines[k].text = (char *) strdup (buf); if (input.lines[k].text == NULL) { perror (PROJECT); return 1; } input.lines[k].len = buf_len; if (input.lines[k].len > input.maxline) input.maxline = input.lines[k].len; #ifdef REGEXP_DEBUG fprintf (stderr, "input.lines[%d] == {%d, \"%s\"}\n", k, input.lines[k].len, input.lines[k].text); #endif } opt.design->current_rule = NULL; } /* * If text indentation was part of the lines processed, indentation * may now be different -> recalculate input.indent. */ if (opt.design->indentmode == 't') { int rc; rc = get_indent (input.lines, input.anz_lines); if (rc >= 0) input.indent = (size_t) rc; else return 4; } return 0; } static int read_all_input (const int use_stdin) /* * Read entire input (possibly from stdin) and store it in 'input' array. * * Tabs are expanded. * Might allocate slightly more memory than it needs. Trade-off for speed. * * use_stdin: flag indicating whether to read from stdin (use_stdin != 0) * or use the data currently present in input (use_stdin == 0). * * RETURNS: != 0 on error (out of memory) * == 0 on success * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { char buf[LINE_MAX+2]; /* input buffer */ size_t input_size = 0; /* number of elements allocated */ line_t *tmp = NULL; char *temp = NULL; /* string resulting from tab exp. */ size_t newlen; /* line length after tab expansion */ size_t i; int rc; input.indent = LINE_MAX; input.maxline = 0; if (use_stdin) { input.anz_lines = 0; /* * Start reading */ while (fgets (buf, LINE_MAX+1, opt.infile)) { if (input_size % 100 == 0) { input_size += 100; tmp = (line_t *) realloc (input.lines, input_size*sizeof(line_t)); if (tmp == NULL) { perror (PROJECT); BFREE (input.lines); return 1; } input.lines = tmp; } input.lines[input.anz_lines].len = strlen (buf); if (opt.r) { input.lines[input.anz_lines].len -= 1; if (buf[input.lines[input.anz_lines].len] == '\n') buf[input.lines[input.anz_lines].len] = '\0'; } else { btrim (buf, &(input.lines[input.anz_lines].len)); } if (input.lines[input.anz_lines].len > 0) { newlen = expand_tabs_into (buf, input.lines[input.anz_lines].len, opt.tabstop, &temp, &(input.lines[input.anz_lines].tabpos), &(input.lines[input.anz_lines].tabpos_len)); if (newlen == 0) { perror (PROJECT); BFREE (input.lines); return 1; } input.lines[input.anz_lines].text = temp; input.lines[input.anz_lines].len = newlen; temp = NULL; } else { input.lines[input.anz_lines].text = (char *) strdup (buf); } /* * Update length of longest line */ if (input.lines[input.anz_lines].len > input.maxline) input.maxline = input.lines[input.anz_lines].len; /* * next please */ ++input.anz_lines; } if (ferror (stdin)) { perror (PROJECT); BFREE (input.lines); return 1; } } else { /* recalculate input statistics for redrawing the mended box */ for (i=0; i input.maxline) input.maxline = input.lines[i].len; } } /* * Exit if there was no input at all */ if (input.lines == NULL || input.lines[0].text == NULL) return 0; /* * Compute indentation */ rc = get_indent (input.lines, input.anz_lines); if (rc >= 0) input.indent = (size_t) rc; else return 1; /* * Remove indentation, unless we want to preserve it (when removing * a box or if the user wants to retain it inside the box) */ if (opt.design->indentmode != 't' && opt.r == 0) { for (i=0; i= input.indent) { memmove (input.lines[i].text, input.lines[i].text+input.indent, input.lines[i].len-input.indent+1); input.lines[i].len -= input.indent; } } input.maxline -= input.indent; } /* * Apply regular expression substitutions */ if (opt.r == 0) { if (apply_substitutions(0) != 0) return 1; } #if 0 /* * Debugging Code: Display contents of input structure */ for (i=0; iminwith backup, used for mending */ int saved_designheight; /* opt.design->minheight backup, used for mending */ #ifdef DEBUG fprintf (stderr, "BOXES STARTING ...\n"); #endif /* * Process command line options */ #ifdef DEBUG fprintf (stderr, "Processing Command Line ...\n"); #endif rc = process_commandline (argc, argv); if (rc == 42) exit (EXIT_SUCCESS); if (rc) exit (EXIT_FAILURE); /* * Parse config file, then reset design pointer */ #ifdef DEBUG fprintf (stderr, "Parsing Config File ...\n"); #endif if (opt.cld == NULL) { rc = yyparse(); if (rc) exit (EXIT_FAILURE); } else { rc = build_design (&designs, opt.cld); if (rc) exit (EXIT_FAILURE); anz_designs = 1; } BFREE (opt.design); opt.design = designs; /* * If "-l" option was given, list styles and exit. */ if (opt.l) { rc = list_styles(); exit (rc); } /* * Adjust box size and indentmode to command line specification * Increase box width/height by width/height of empty sides in order * to match appearance of box with the user's expectations (if -s). */ if (opt.reqheight > (long) opt.design->minheight) opt.design->minheight = opt.reqheight; if (opt.reqwidth > (long) opt.design->minwidth) opt.design->minwidth = opt.reqwidth; if (opt.reqwidth) { if (empty_side (opt.design->shape, BRIG)) opt.design->minwidth += opt.design->shape[SE].width; if (empty_side (opt.design->shape, BLEF)) opt.design->minwidth += opt.design->shape[NW].width; } if (opt.reqheight) { if (empty_side (opt.design->shape, BTOP)) opt.design->minheight += opt.design->shape[NW].height; if (empty_side (opt.design->shape, BBOT)) opt.design->minheight += opt.design->shape[SE].height; } if (opt.indentmode) opt.design->indentmode = opt.indentmode; saved_designwidth = opt.design->minwidth; saved_designheight = opt.design->minheight; do { if (opt.mend == 1) /* Mending a box works in two phases: */ opt.r = 0; /* opt.mend == 2: remove box */ --opt.mend; /* opt.mend == 1: add it back */ opt.design->minwidth = saved_designwidth; opt.design->minheight = saved_designheight; /* * Read input lines */ #ifdef DEBUG fprintf (stderr, "Reading all input ...\n"); #endif rc = read_all_input (opt.mend); if (rc) exit (EXIT_FAILURE); if (input.anz_lines == 0) exit (EXIT_SUCCESS); /* * Adjust box size to fit requested padding value * Command line-specified box size takes precedence over padding. */ for (i=0; i -1) opt.design->padding[i] = opt.padding[i]; } pad = opt.design->padding[BTOP] + opt.design->padding[BBOT]; if (pad > 0) { pad += input.anz_lines; pad += opt.design->shape[NW].height + opt.design->shape[SW].height; if (pad > opt.design->minheight) { if (opt.reqheight) { for (i=0; i<(int)(pad-opt.design->minheight); ++i) { if (opt.design->padding[i%2?BBOT:BTOP]) opt.design->padding[i%2?BBOT:BTOP] -= 1; else if (opt.design->padding[i%2?BTOP:BBOT]) opt.design->padding[i%2?BTOP:BBOT] -= 1; else break; } } else { opt.design->minheight = pad; } } } pad = opt.design->padding[BLEF] + opt.design->padding[BRIG]; if (pad > 0) { pad += input.maxline; pad += opt.design->shape[NW].width + opt.design->shape[NE].width; if (pad > opt.design->minwidth) { if (opt.reqwidth) { for (i=0; i<(int)(pad-opt.design->minwidth); ++i) { if (opt.design->padding[i%2?BRIG:BLEF]) opt.design->padding[i%2?BRIG:BLEF] -= 1; else if (opt.design->padding[i%2?BLEF:BRIG]) opt.design->padding[i%2?BLEF:BRIG] -= 1; else break; } } else { opt.design->minwidth = pad; } } } if (opt.r) { /* * Remove box */ #ifdef DEBUG fprintf (stderr, "Removing Box ...\n"); #endif if (opt.killblank == -1) { if (empty_side (opt.design->shape, BTOP) && empty_side (opt.design->shape, BBOT)) opt.killblank = 0; else opt.killblank = 1; } rc = remove_box(); if (rc) exit (EXIT_FAILURE); rc = apply_substitutions (1); if (rc) exit (EXIT_FAILURE); output_input (opt.mend > 0); } else { /* * Generate box */ sentry_t *thebox; #ifdef DEBUG fprintf (stderr, "Generating Box ...\n"); #endif thebox = (sentry_t *) calloc (ANZ_SIDES, sizeof(sentry_t)); if (thebox == NULL) { perror (PROJECT); exit (EXIT_FAILURE); } rc = generate_box (thebox); if (rc) exit (EXIT_FAILURE); output_box (thebox); } } while (opt.mend > 0); return EXIT_SUCCESS; } /*EOF*/ /* vim: set sw=4: */ boxes-1.2/src/boxes.h.in000066400000000000000000000142001306272555200151650ustar00rootroot00000000000000/* * File: boxes.h * Date created: March 18, 1999 (Thursday, 15:09h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Project-wide globals and data structures * * License: o 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. * o 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. * o 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 BOXES_H #define BOXES_H /* #define DEBUG */ /* #define REGEXP_DEBUG */ /* #define PARSER_DEBUG */ /* #define LEXER_DEBUG */ #include "regexp.h" #define PROJECT "boxes" /* name of program */ #define VERSION "--BVERSION--" /* current release of project */ #define GLOBALCONF "--GLOBALCONF--" /* name of system-wide config file */ /* * default settings of all kinds (THIS PARAGRAPH MAY BE EDITED) */ #define DEF_TABSTOP 8 /* default tab stop distance (part of -t) */ #define DEF_INDENTMODE 'b' /* indent box, not text by default */ /* * max. allowed tab stop distance */ #define MAX_TABSTOP 16 /* * max. supported line length * This is how many characters of a line will be read. Anything beyond * will be discarded. The line feed character at the end does not count. * (This should have been done via sysconf(), but I didn't do it in order * to ease porting to non-unix platforms.) */ #if defined(LINE_MAX) && (LINE_MAX < 1024) #undef LINE_MAX #endif #ifndef LINE_MAX #define LINE_MAX 2048 #endif #ifdef DEBUG #define __TJ(s) fprintf (stderr, s); #else #define __TJ(s) /**/ #endif #define BTOP 0 /* for use with sides */ #define BRIG 1 #define BBOT 2 #define BLEF 3 typedef struct { char *search; char *repstr; regexp *prog; /* compiled search pattern */ int line; /* line of definition in config file */ char mode; /* 'g' or 'o' */ } reprule_t; typedef struct { char *name; char *author; /* creator of the configuration file entry */ char *designer; /* creator of the original ASCII artwork */ char *created; /* date created, free format */ char *revision; /* revision number of design */ char *revdate; /* date of current revision */ char *sample; char indentmode; /* 'b', 't', or 'n' */ sentry_t shape[ANZ_SHAPES]; size_t maxshapeheight; /* height of highest shape in design */ size_t minwidth; size_t minheight; int padding[ANZ_SIDES]; reprule_t *current_rule; reprule_t *reprules; /* applied when drawing a box */ size_t anz_reprules; reprule_t *revrules; /* applied upon removal of a box */ size_t anz_revrules; } design_t; extern design_t *designs; extern int anz_designs; extern int design_idx; extern int tjlineno; /* config file line counter */ extern char *yyfilename; /* name of config file */ typedef struct { /* Command line options: */ int l; /* list available designs */ int mend; /* 1 if -m is given, 2 in 2nd loop */ int r; /* remove box from input */ int tabstop; /* tab stop distance */ char tabexp; /* tab expansion mode (for leading tabs) */ int padding[ANZ_SIDES]; /* in spaces or lines resp. */ design_t *design; /* currently used box design */ int design_choice_by_user; /* true if design was chosen by user */ char *cld; /* commandline design definition, -c */ long reqwidth; /* requested box width (-s) */ long reqheight; /* requested box height (-s) */ char valign; /* text position inside box */ char halign; /* ( h[lcr]v[tcb] ) */ char indentmode; /* 'b', 't', 'n', or '\0' */ char justify; /* 'l', 'c', 'r', or '\0' */ int killblank; /* -1 if not set */ FILE *infile; /* where we get our input */ FILE *outfile; /* where we put our output */ } opt_t; extern opt_t opt; typedef struct { size_t len; /* length of text in characters */ char *text; /* line content, tabs expanded */ size_t *tabpos; /* tab positions in expanded work strings */ size_t tabpos_len; /* number of tabs in a line */ } line_t; #ifndef FILE_LEXER_L typedef struct { line_t *lines; size_t anz_lines; /* number of entries in input */ size_t maxline; /* length of longest input line */ size_t indent; /* number of leading spaces found */ } input_t; #define INPUT_INITIALIZER {NULL, 0, 0, LINE_MAX} extern input_t input; #endif /*!FILE_LEXER_L*/ #endif /* BOXES_H */ /*EOF*/ /* vim: set cindent sw=4 syntax=c: */ boxes-1.2/src/config.h000066400000000000000000000030311306272555200147050ustar00rootroot00000000000000/* * File: config.h * Project Main: boxes.c * Date created: July 4, 1999 (Sunday, 21:04h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Please compiler and ease porting * * License: o 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. * o 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. * o 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 CONFIG_H #define CONFIG_H #if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) #define _GNU_SOURCE #elif defined(__sun__) #define _POSIX_SOURCE #define __EXTENSIONS__ #elif defined(__FreeBSD__) /* do nothing */ #else #define _POSIX_SOURCE #endif #endif /*CONFIG_H*/ /*EOF*/ boxes-1.2/src/generate.c000066400000000000000000001100401306272555200152240ustar00rootroot00000000000000/* * File: generate.c * Project Main: boxes.c * Date created: June 23, 1999 (Wednesday, 20:10h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Box generation, i.e. the drawing of boxes * * License: o 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. * o 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. * o 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "config.h" #include #include #include #include "shape.h" #include "boxes.h" #include "tools.h" #include "generate.h" static const char rcsid_generate_c[] = "$Id: generate.c,v 1.11 2006/07/22 19:21:13 tsjensen Exp $"; static int horiz_precalc (const sentry_t *sarr, size_t *topiltf, size_t *botiltf, size_t *hspace) /* * Calculate data for horizontal box side generation. * * sarr Array of shapes from the current design * * topiltf RESULT: individual lines (columns) to fill by shapes 1, 2, and 3 * botiltf in top part of box (topiltf) and bottom part of box * hspace RESULT: number of columns excluding corners (sum over iltf) * * RETURNS: == 0 on success (result values are set) * != 0 on error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int tnumsh; /* number of existent shapes in top part */ int bnumsh; size_t twidth; /* current hspace for top side */ size_t bwidth; /* current hspace for bottom side */ int i; size_t target_width; /* assumed text width for minimum box size */ int btoggle, ttoggle; /* for case 3 w/ 2 elastics */ /* * Initialize future result values */ memset (topiltf, 0, (SHAPES_PER_SIDE-2) * sizeof(size_t)); memset (botiltf, 0, (SHAPES_PER_SIDE-2) * sizeof(size_t)); *hspace = 0; /* * Ensure minimum width for the insides of a box in order to ensure * minimum box size required by current design */ if (input.maxline >= (opt.design->minwidth - sarr[north_side[0]].width - sarr[north_side[SHAPES_PER_SIDE-1]].width)) { target_width = input.maxline; } else { target_width = opt.design->minwidth - sarr[north_side[0]].width - sarr[north_side[SHAPES_PER_SIDE-1]].width; } /* * Compute number of existent shapes in top and in bottom part */ tnumsh = 0; bnumsh = 0; for (i=1; iminwidth %d, input.maxline %d, target_width" " %d, tnumsh %d, bnumsh %d\n", opt.design->minwidth, input.maxline, target_width, tnumsh, bnumsh); #endif twidth = 0; bwidth = 0; btoggle = 1; /* can be 1 or 3 */ ttoggle = 1; do { shape_t *seite; /* ptr to north_side or south_side */ size_t *iltf; /* ptr to botiltf or topiltf */ size_t *res_hspace; /* ptr to bwidth or twidth */ int *stoggle; /* ptr to btoggle or ttoggle */ int numsh; /* either bnumsh or tnumsh */ /* * Set pointers to the side which is currently shorter, * so it will be advanced in this step. */ if (twidth > bwidth) { /* south (bottom) is behind */ seite = south_side; iltf = botiltf; res_hspace = &bwidth; numsh = bnumsh; stoggle = &btoggle; } else { /* north (top) is behind */ seite = north_side; iltf = topiltf; res_hspace = &twidth; numsh = tnumsh; stoggle = &ttoggle; } switch (numsh) { case 1: /* * only one shape -> it must be elastic */ for (i=1; i one must be elastic, the other must not */ for (i=1; i one or two of them must be elastic * If two are elastic, they are the two outer ones. */ for (i=1; i= (opt.design->minheight - sarr[west_side[0]].height - sarr[west_side[SHAPES_PER_SIDE-1]].height)) { target_height = input.anz_lines; } else { target_height = opt.design->minheight - sarr[west_side[0]].height - sarr[west_side[SHAPES_PER_SIDE-1]].height; } /* * Compute number of existent shapes in left and right part (1..3) */ lnumsh = 0; rnumsh = 0; for (i=1; i rheight) { /* east (right) is behind */ seite = east_side; iltf = rightiltf; res_vspace = &rheight; numsh = rnumsh; stoggle = &rtoggle; } else { /* west (left) is behind */ seite = west_side; iltf = leftiltf; res_vspace = &lheight; numsh = lnumsh; stoggle = <oggle; } switch (numsh) { case 1: /* * only one shape -> it must be elastic */ for (i=1; i one must be elastic, the other must not */ for (i=1; i one or two of them must be elastic * If two are elastic, they are the two outer ones. */ for (i=1; iheight; ++line) { result->chars[line] = (char *) calloc (1, result->width+1); if (result->chars[line] == NULL) { perror (PROJECT); if ((long)--line >= 0) do { BFREE (result->chars[line--]); } while ((long)line >= 0); return 1; /* out of memory */ } } cshape = (seite == north_side)? 0 : 2; for (j=0; jwidth; j+=sarr[seite[cshape+1]].width) { while (iltf[cshape] == 0) cshape += (seite == north_side)? 1 : -1; for (line=0; lineheight; ++line) strcat (result->chars[line], sarr[seite[cshape+1]].chars[line]); iltf[cshape] -= sarr[seite[cshape+1]].width; } return 0; /* all clear */ } static void horiz_assemble (const sentry_t *sarr, const shape_t *seite, size_t *iltf, sentry_t *result) { size_t j; size_t sc; /* index to shape chars (lines) */ int cshape; /* current shape (idx to iltf) */ shape_t ctop, cbottom; if (seite == east_side) { ctop = seite[0]; cbottom = seite[SHAPES_PER_SIDE-1]; cshape = 0; } else { ctop = seite[SHAPES_PER_SIDE-1]; cbottom = seite[0]; cshape = 2; } for (j=0; jchars[j] = sarr[ctop].chars[j]; for (j=0; jchars[result->height-sarr[cbottom].height+j] = sarr[cbottom].chars[j]; sc = 0; for (j=sarr[ctop].height; j < result->height-sarr[cbottom].height; ++j) { while (iltf[cshape] == 0) { if (seite == east_side) ++cshape; else --cshape; sc = 0; } if (sc == sarr[seite[cshape+1]].height) sc = 0; result->chars[j] = sarr[seite[cshape+1]].chars[sc]; ++sc; iltf[cshape] -= 1; } } static int horiz_generate (sentry_t *tresult, sentry_t *bresult) /* * Generate top and bottom parts of box (excluding corners). * * RETURNS: == 0 if successful (resulting char array is stored in [bt]result) * != 0 on error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t biltf[SHAPES_PER_SIDE-2]; /* individual lines to fill (bottom) */ size_t tiltf[SHAPES_PER_SIDE-2]; /* individual lines to fill (top) */ int rc; /* received return code */ tresult->height = highest (opt.design->shape, SHAPES_PER_SIDE, NW, NNW, N, NNE, NE); bresult->height = highest (opt.design->shape, SHAPES_PER_SIDE, SW, SSW, S, SSE, SE); rc = horiz_precalc (opt.design->shape, tiltf, biltf, &(tresult->width)); if (rc) return rc; bresult->width = tresult->width; #ifdef DEBUG fprintf (stderr, "Top side box rect width %d, height %d.\n", tresult->width, tresult->height); fprintf (stderr, "Top columns to fill: %s %d, %s %d, %s %d.\n", shape_name[north_side[1]], tiltf[0], shape_name[north_side[2]], tiltf[1], shape_name[north_side[3]], tiltf[2]); fprintf (stderr, "Bottom side box rect width %d, height %d.\n", bresult->width, bresult->height); fprintf (stderr, "Bottom columns to fill: %s %d, %s %d, %s %d.\n", shape_name[south_side[1]], biltf[0], shape_name[south_side[2]], biltf[1], shape_name[south_side[3]], biltf[2]); #endif tresult->chars = (char **) calloc (tresult->height, sizeof(char *)); bresult->chars = (char **) calloc (bresult->height, sizeof(char *)); if (tresult->chars == NULL || bresult->chars == NULL) return 1; rc = vert_assemble (opt.design->shape, north_side, tiltf, tresult); if (rc) return rc; rc = vert_assemble (opt.design->shape, south_side, biltf, bresult); if (rc) return rc; #if defined(DEBUG) && 1 { /* * Debugging code - Output horizontal sides of box */ size_t j; fprintf (stderr, "TOP SIDE:\n"); for (j=0; jheight; ++j) { fprintf (stderr, " %2d: \'%s\'\n", j, tresult->chars[j]? tresult->chars[j] : "(null)"); } fprintf (stderr, "BOTTOM SIDE:\n"); for (j=0; jheight; ++j) { fprintf (stderr, " %2d: \'%s\'\n", j, bresult->chars[j]? bresult->chars[j] : "(null)"); } } #endif return 0; /* all clear */ } static int vert_generate (sentry_t *lresult, sentry_t *rresult) /* * Generate vertical sides of box. * * RETURNS: == 0 on success (resulting char array is stored in [rl]result) * != 0 on error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t vspace = 0; size_t leftiltf[SHAPES_PER_SIDE-2]; /* individual lines to fill */ size_t rightiltf[SHAPES_PER_SIDE-2]; /* individual lines to fill */ int rc; /* received return code */ lresult->width = widest (opt.design->shape, SHAPES_PER_SIDE, SW, WSW, W, WNW, NW); rresult->width = widest (opt.design->shape, SHAPES_PER_SIDE, SE, ESE, E, ENE, NE); rc = vert_precalc (opt.design->shape, leftiltf, rightiltf, &vspace); if (rc) return rc; lresult->height = vspace + opt.design->shape[NW].height + opt.design->shape[SW].height; rresult->height = vspace + opt.design->shape[NE].height + opt.design->shape[SE].height; #ifdef DEBUG fprintf (stderr, "Left side box rect width %d, height %d, vspace %d.\n", lresult->width, lresult->height, vspace); fprintf (stderr, "Left lines to fill: %s %d, %s %d, %s %d.\n", shape_name[west_side[1]], leftiltf[0], shape_name[west_side[2]], leftiltf[1], shape_name[west_side[3]], leftiltf[2]); fprintf (stderr, "Right side box rect width %d, height %d, vspace %d.\n", rresult->width, rresult->height, vspace); fprintf (stderr, "Right lines to fill: %s %d, %s %d, %s %d.\n", shape_name[east_side[1]], rightiltf[0], shape_name[east_side[2]], rightiltf[1], shape_name[east_side[3]], rightiltf[2]); #endif lresult->chars = (char **) calloc (lresult->height, sizeof(char *)); if (lresult->chars == NULL) return 1; rresult->chars = (char **) calloc (rresult->height, sizeof(char *)); if (rresult->chars == NULL) return 1; horiz_assemble (opt.design->shape, west_side, leftiltf, lresult); horiz_assemble (opt.design->shape, east_side, rightiltf, rresult); #if defined(DEBUG) && 1 { /* * Debugging code - Output left and right side of box */ size_t j; fprintf (stderr, "LEFT SIDE:\n"); for (j=0; jheight; ++j) { fprintf (stderr, " %2d: \'%s\'\n", j, lresult->chars[j]? lresult->chars[j] : "(null)"); } fprintf (stderr, "RIGHT SIDE:\n"); for (j=0; jheight; ++j) { fprintf (stderr, " %2d: \'%s\'\n", j, rresult->chars[j]? rresult->chars[j] : "(null)"); } } #endif return 0; /* all clear */ } int generate_box (sentry_t *thebox) /* * * RETURNS: == 0 if successful (thebox is set) * != 0 on error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int rc; int i; rc = horiz_generate (&(thebox[0]), &(thebox[2])); if (rc) goto err; rc = vert_generate (&(thebox[3]), &(thebox[1])); if (rc) goto err; return 0; /* all clear */ err: for (i=0; ilen; if (opt.justify == '\0') return 0; if (empty_line(line)) return 0; for (p=line->text; *p==' ' || *p=='\t'; ++p); newlen = line->len - (p-line->text); switch (opt.justify) { case 'l': if (opt.design->indentmode == 't') { memmove (line->text+input.indent, p, newlen+1); line->len = newlen + input.indent; } else { memmove (line->text, p, newlen+1); line->len = newlen; } break; case 'c': if (opt.design->indentmode == 't') { shift = (input.maxline-input.indent-newlen) / 2 + input.indent; skew -= input.indent; if ((input.maxline-input.indent-newlen) % 2 && skew == 1) ++shift; } else { shift = (input.maxline - newlen) / 2; if ((input.maxline - newlen) % 2 && skew == 1) ++shift; } newtext = (char *) calloc (shift + newlen + 1, sizeof(char)); if (newtext == NULL) { perror (PROJECT); return 2; } spaces = (char *) malloc (shift+1); if (spaces == NULL) { perror (PROJECT); BFREE (newtext); return 3; } memset (spaces, ' ', shift); spaces[shift] = '\0'; #if defined(DEBUG) && 0 fprintf (stderr, "j(c): newlen=%d, shift=%d, spaces=\"%s\"\n", newlen, shift, spaces); #endif strncpy (newtext, spaces, shift); strncat (newtext, p, newlen); newtext[shift+newlen] = '\0'; BFREE (spaces); BFREE (line->text); line->text = newtext; line->len = shift + newlen; break; case 'r': shift = input.maxline - newlen; newtext = (char *) calloc (input.maxline+1, sizeof(char)); if (newtext == NULL) { perror (PROJECT); return 2; } spaces = (char *) malloc (shift+1); if (spaces == NULL) { perror (PROJECT); BFREE (newtext); return 3; } memset (spaces, ' ', shift); spaces[shift] = '\0'; strncpy (newtext, spaces, shift); strncat (newtext, p, newlen); newtext[input.maxline] = '\0'; BFREE (spaces); BFREE (line->text); line->text = newtext; line->len = input.maxline; break; default: fprintf (stderr, "%s: internal error\n", PROJECT); return 1; } /* * If we might have broken the maxline value, recalculate it. */ if (opt.justify != 'r' && oldlen == input.maxline) { size_t k; input.maxline = 0; for (k=0; k input.maxline) input.maxline = input.lines[k].len; } } return 0; } int output_box (const sentry_t *thebox) /* * Generate final output using the previously generated box parts. * * thebox Array of four shapes which contain the previously generated * box parts in the following order: BTOP, BRIG, BBOT, BLEF * * RETURNS: == 0 if successful * != 0 on error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t j; size_t nol = thebox[BRIG].height; /* number of output lines */ char trailspc[LINE_MAX+1]; char *indentspc; int indentspclen; size_t vfill, vfill1, vfill2; /* empty lines/columns in box */ size_t hfill; char *hfill1, *hfill2; /* space before/after text */ size_t hpl, hpr; size_t r; int rc; char obuf[LINE_MAX+1]; /* final output buffer */ size_t obuf_len; /* length of content of obuf */ size_t skip_start; /* lines to skip for box top */ size_t skip_end; /* lines to skip for box bottom */ size_t skip_left; /* true if left box part is to be skipped */ int ntabs, nspcs; /* needed for unexpand of tabs */ char *restored_indent; #ifdef DEBUG fprintf (stderr, "Padding used: left %d, top %d, right %d, bottom %d\n", opt.design->padding[BLEF], opt.design->padding[BTOP], opt.design->padding[BRIG], opt.design->padding[BBOT]); #endif /* * Create string of spaces for indentation */ indentspc = NULL; ntabs = nspcs = indentspclen = 0; if (opt.design->indentmode == 'b') { if (opt.tabexp == 'u') { ntabs = input.indent / opt.tabstop; nspcs = input.indent % opt.tabstop; indentspclen = ntabs + nspcs; } else { indentspclen = input.indent; } indentspc = (char *) malloc (indentspclen + 1); if (indentspc == NULL) { perror (PROJECT); return 1; } if (opt.tabexp == 'u') { memset (indentspc, (int)'\t', ntabs); memset (indentspc + ntabs, (int)' ', nspcs); } else { memset (indentspc, (int)' ', indentspclen); } indentspc[indentspclen] = '\0'; } else { indentspc = (char *) strdup (""); if (indentspc == NULL) { perror (PROJECT); return 1; } } /* * Provide string of spaces for filling of space between text and * right side of box */ memset (trailspc, (int)' ', LINE_MAX); trailspc[LINE_MAX] = '\0'; /* * Compute number of empty lines in box (vfill). */ vfill = nol - thebox[BTOP].height - thebox[BBOT].height - input.anz_lines; vfill -= opt.design->padding[BTOP] + opt.design->padding[BBOT]; if (opt.valign == 'c') { vfill1 = vfill / 2; vfill2 = vfill1 + (vfill % 2); } else if (opt.valign == 'b') { vfill1 = vfill; vfill2 = 0; } else { vfill1 = 0; vfill2 = vfill; } vfill1 += opt.design->padding[BTOP]; vfill2 += opt.design->padding[BBOT]; vfill += opt.design->padding[BTOP] + opt.design->padding[BBOT]; /* * Provide strings for horizontal text alignment. */ hfill = thebox[BTOP].width - input.maxline; hfill1 = (char *) malloc (hfill+1); hfill2 = (char *) malloc (hfill+1); if (!hfill1 || !hfill2) { perror (PROJECT); return 1; } memset (hfill1, (int)' ', hfill+1); memset (hfill2, (int)' ', hfill+1); hfill1[hfill] = '\0'; hfill2[hfill] = '\0'; hpl = 0; hpr = 0; if (hfill == 1) { if (opt.halign == 'r' || opt.design->padding[BLEF] > opt.design->padding[BRIG]) { hpl = 1; hpr = 0; } else { hpl = 0; hpr = 1; } } else { hfill -= opt.design->padding[BLEF] + opt.design->padding[BRIG]; if (opt.halign == 'c') { hpl = hfill/2 + opt.design->padding[BLEF]; hpr = hfill/2 + opt.design->padding[BRIG] + (hfill%2); } else if (opt.halign == 'r') { hpl = hfill + opt.design->padding[BLEF]; hpr = opt.design->padding[BRIG]; } else { hpl = opt.design->padding[BLEF]; hpr = hfill + opt.design->padding[BRIG]; } hfill += opt.design->padding[BLEF] + opt.design->padding[BRIG]; } hfill1[hpl] = '\0'; hfill2[hpr] = '\0'; #if defined(DEBUG) fprintf (stderr, "Alignment: hfill %d hpl %d hpr %d, vfill %d " "vfill1 %d vfill2 %d.\n", hfill, hpl, hpr, vfill, vfill1, vfill2); fprintf (stderr, " hfill1 = \"%s\"; hfill2 = \"%s\"; " "indentspc = \"%s\";\n", hfill1, hfill2, indentspc); #endif /* * Find out if and how many leading or trailing blank lines must be * skipped because the corresponding box side was defined empty. */ skip_start = 0; skip_end = 0; skip_left = 0; if (empty_side (opt.design->shape, BTOP)) skip_start = opt.design->shape[NW].height; if (empty_side (opt.design->shape, BBOT)) skip_end = opt.design->shape[SW].height; if (empty_side (opt.design->shape, BLEF)) skip_left = opt.design->shape[NW].width; /* could simply be 1, though */ #if defined(DEBUG) fprintf (stderr, "skip_start = %d; skip_end = %d; skip_left = %d; " "nol = %d;\n", skip_start, skip_end, skip_left, nol); #endif /* * Generate actual output */ for (j=skip_start; j= 0? input.lines[ti].text : "", hfill2, trailspc, thebox[BRIG].chars[j]); } else { /* bottom vfill */ r = thebox[BTOP].width; trailspc[r] = '\0'; restored_indent = tabbify_indent (input.anz_lines - 1, indentspc, indentspclen); concat_strings (obuf, LINE_MAX+1, 4, restored_indent, skip_left?"":thebox[BLEF].chars[j], trailspc, thebox[BRIG].chars[j]); } trailspc[r] = ' '; } else { /* box bottom */ restored_indent = tabbify_indent (input.anz_lines - 1, indentspc, indentspclen); concat_strings (obuf, LINE_MAX+1, 4, restored_indent, skip_left?"":thebox[BLEF].chars[j], thebox[BBOT].chars[j-(nol-thebox[BBOT].height)], thebox[BRIG].chars[j]); } obuf_len = strlen (obuf); if (obuf_len > LINE_MAX) { size_t newlen = LINE_MAX; btrim (obuf, &newlen); } else { btrim (obuf, &obuf_len); } if (opt.tabexp == 'k') { BFREE (restored_indent); } fprintf (opt.outfile, "%s\n", obuf); } BFREE (indentspc); BFREE (hfill1); BFREE (hfill2); return 0; /* all clear */ } /*EOF*/ /* vim: set sw=4: */ boxes-1.2/src/generate.h000066400000000000000000000027441306272555200152440ustar00rootroot00000000000000/* * File: generate.h * Project Main: boxes.c * Date created: June 23, 1999 (Wednesday, 20:12h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Box generation, i.e. the drawing of boxes * * License: o 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. * o 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. * o 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 GENERATE_H #define GENERATE_H int generate_box (sentry_t *thebox); int output_box (const sentry_t *thebox); #endif /*GENERATE_H*/ /*EOF*/ /* vim: set cindent sw=4: */ boxes-1.2/src/lexer.h000066400000000000000000000033701306272555200145650ustar00rootroot00000000000000/* * File: lexer.h * Project Main: boxes.c * Date created: July 01, 1999 (Thursday, 13:43h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Export symbols used by the parser files only * * License: o 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. * o 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. * o 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 LEXER_H #define LEXER_H /* * Valid characters to be used as string delimiters. Note that the * following list must correspond to the DELIM definition in lexer.l. */ #define LEX_SDELIM "\"~'`!@%&*=:;<>?/|.\\" int yylex(); /* defined in lex.yy.c */ void begin_speedmode(); void chg_strdelims (const char asdel, const char asesc); extern int speeding; #endif /*LEXER_H*/ /*EOF*/ /* vim: set sw=4: */ boxes-1.2/src/lexer.l000066400000000000000000000242301306272555200145670ustar00rootroot00000000000000%{ /* * File: lexer.l * Date created: March 15, 1999 (Monday, 17:16h) * Author: Copyright (C) 1999 Thomas Jensen * Language: lex (ANSI C) * Web Site: http://boxes.thomasjensen.com/ * Purpose: flex lexical analyzer for boxes configuration files * * License: o 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. * o 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. * o 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 * * Remarks: - We don't use the yylineno %option. It is not only inefficient, * but also doesn't work. :-| *doh* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "config.h" #include #include #include #include "shape.h" #define FILE_LEXER_L #include "boxes.h" #undef FILE_LEXER_L #include "tools.h" #include "parser.h" #include "lexer.h" #define LEX_MAX_WARN 3 /* number of lex errors per design */ static const char rcsid_lexer_l[] = "$Id: lexer.l,v 1.19 2006/07/22 19:31:25 tsjensen Exp $"; int tjlineno = 1; static int yyerrcnt = 0; static char sdel = '\"'; static char sesc = '\\'; /* * User-defined initializations for the lexer */ static void inflate_inbuf(); #define YY_USER_INIT inflate_inbuf() %} %option nounput %option noyywrap %option never-interactive %option caseless %option noyylineno %x SAMPLE %x SPEEDMODE %x DELWORD %s SHAPES %s ELASTIC PWORD [a-zA-ZäöüÄÖÜ][a-zA-Z0-9\-_üäöÜÄÖß]* PWHITE [\n \r\t] PBOX Box SDELIM [\"~\'`!@\%\&\*=:;<>\?/|\.\\] %% [ \r\t] /* ignore whitespace */ \n ++tjlineno; [^ \t\r\n]+ { /* * String delimiter spec - like WORD, but allow any character */ #ifdef LEXER_DEBUG fprintf (stderr, "\nYDELWOR: %s -- STATE INITIAL", yytext); #endif yylval.s = (char *) strdup (yytext); if (yylval.s == NULL) { perror (PROJECT); exit (EXIT_FAILURE); } BEGIN INITIAL; return YDELWORD; } {SDELIM}.*$ { /* * Strings -- first match everything starting from a potential * string delimiter until the end of the line. We will give back what * we don't need and also detect unterminated strings. */ char *p; int rest_len = yyleng - 1; /* length of string pointed to by p */ int qcnt = 0; /* esc char count in current string */ if (yytext[0] != sdel) { REJECT; /* that was not our delimiter */ } yylval.s = (char *) strdup (yytext + 1); if (yylval.s == NULL) { perror (PROJECT); exit (EXIT_FAILURE); } p = yylval.s; while (*p) { if (*p == sesc) { memmove (p, p+1, rest_len); /* incl. '\0' */ ++qcnt; --rest_len; if (*p == '\0') break; } else if (*p == sdel) { *p = '\0'; yyless ((p-yylval.s)+2+qcnt); /* string plus quotes */ #ifdef LEXER_DEBUG fprintf (stderr, "\n STRING: \"%s\"", yylval.s); #endif return STRING; } --rest_len; ++p; } if (yyerrcnt++ < 5) yyerror ("Unterminated String -- %s", yytext); return YUNREC; } Sample { #ifdef LEXER_DEBUG fprintf (stderr, "\nYSAMPLE: %s -- STATE SAMPLE", yytext); #endif BEGIN SAMPLE; return YSAMPLE; } \n { ++tjlineno; if (yyleng > 1) yymore(); } ^[ \t]*ends[ \t\r]*$ { char *p = yytext + yyleng -1; size_t len; /* length of sample */ while (*p == ' ' || *p == '\t' || *p == '\r') --p; /* skip trailing whitespace */ p -= 2; /* almost skip "ends" statement */ *p = '\0'; /* p now points to 'n' */ yylval.s = (char *) strdup (yytext); if (yylval.s == NULL) { perror (PROJECT); exit (EXIT_FAILURE); } *p-- = 'n'; len = p - yytext; /* yyless(n): push back all but the first n */ yyless (len); /* allow him to return YENDSAMPLE */ yylval.s[len] = '\n'; /* replace 'e' with newline */ btrim (yylval.s, &len); if (len > 0) { strcat (yylval.s, "\n"); /* memory was allocated with strdup */ #ifdef LEXER_DEBUG fprintf (stderr, "\n STRING: \"%s\" -- STATE INITIAL", yylval.s); #endif BEGIN INITIAL; return STRING; } else { if (yyerrcnt++ < 5) yyerror ("SAMPLE block must not be empty"); BFREE (yylval.s); return YUNREC; } } . yymore(); ends[ \t\r]*$ { #ifdef LEXER_DEBUG fprintf (stderr, "\nYENDSAM: %s", yytext); #endif return YENDSAMPLE; } Elastic { #ifdef LEXER_DEBUG fprintf (stderr, "\nYELASTC: %s -- STATE ELASTIC", yytext); #endif BEGIN ELASTIC; return YELASTIC; } Shapes { #ifdef LEXER_DEBUG fprintf (stderr, "\nYSHAPES: %s -- STATE SHAPES", yytext); #endif BEGIN SHAPES; return YSHAPES; } {PBOX} { #ifdef LEXER_DEBUG fprintf (stderr, "\n YBOX: %s", yytext); #endif yyerrcnt = 0; return YBOX; } Replace { return YREPLACE; } Reverse { return YREVERSE; } Padding { return YPADDING; } End { return YEND; } To { return YTO; } With { return YWITH; } Global { yylval.c = 'g'; return YRXPFLAG; } Once { yylval.c = 'o'; return YRXPFLAG; } nw { yylval.shape = NW; return SHAPE; } nnw { yylval.shape = NNW; return SHAPE; } n { yylval.shape = N; return SHAPE; } nne { yylval.shape = NNE; return SHAPE; } ne { yylval.shape = NE; return SHAPE; } ene { yylval.shape = ENE; return SHAPE; } e { yylval.shape = E; return SHAPE; } ese { yylval.shape = ESE; return SHAPE; } se { yylval.shape = SE; return SHAPE; } sse { yylval.shape = SSE; return SHAPE; } s { yylval.shape = S; return SHAPE; } ssw { yylval.shape = SSW; return SHAPE; } sw { yylval.shape = SW; return SHAPE; } wsw { yylval.shape = WSW; return SHAPE; } w { yylval.shape = W; return SHAPE; } wnw { yylval.shape = WNW; return SHAPE; } \) { #ifdef LEXER_DEBUG fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE INITIAL", yytext[0]); #endif BEGIN INITIAL; return yytext[0]; } \} { #ifdef LEXER_DEBUG fprintf (stderr, "\n SYMBOL: \'%c\' -- STATE INITIAL", yytext[0]); #endif BEGIN INITIAL; return yytext[0]; } author|designer|created|revision|revdate|indent { /* * general key words */ #ifdef LEXER_DEBUG fprintf (stderr, "\nKEYWORD: %s", yytext); #endif yylval.s = (char *) strdup (yytext); if (yylval.s == NULL) { perror (PROJECT); exit (EXIT_FAILURE); } return KEYWORD; } Delimiter|Delim { /* * Change string delimiting characters */ #ifdef LEXER_DEBUG fprintf (stderr, "\nYCHGDEL: %s -- STATE DELWORD", yytext); #endif BEGIN DELWORD; return YCHGDEL; } {PWORD} { #ifdef LEXER_DEBUG fprintf (stderr, "\n WORD: %s", yytext); #endif yylval.s = (char *) strdup (yytext); if (yylval.s == NULL) { perror (PROJECT); exit (EXIT_FAILURE); } return WORD; } [\+-]?[0-9]+ { #ifdef LEXER_DEBUG fprintf (stderr, "\nYNUMBER: %s", yytext); #endif yylval.num = atoi (yytext); return YNUMBER; } [,(){}] { #ifdef LEXER_DEBUG fprintf (stderr, "\n SYMBOL: \'%c\'", yytext[0]); #endif return yytext[0]; } #.*$ { /* ignore comments */ #ifdef LEXER_DEBUG fprintf (stderr, "\nCOMMENT: %s", yytext+1); #endif } . { if (yyerrcnt++ < LEX_MAX_WARN) yyerror ("Unrecognized input char \'%s\'", yytext); return YUNREC; } {PBOX}{PWHITE}+{PWORD} { #ifdef LEXER_DEBUG fprintf (stderr, "\n STATUS: %s -- STATE INITIAL", yytext); #endif yyless (0); speeding = 0; BEGIN INITIAL; } \n ++tjlineno; . /* ignore anything else */ %% static void inflate_inbuf() /* * User-defined initializations for the lexer. * * Since this scanner must use REJECT in order to be able to process the * string delimiter commands, it cannot dynamically enlarge its input * buffer to accomodate larger tokens. Thus, we simply set the buffer size * to the input file size plus 10 bytes margin-of-error. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { struct stat sinf; if (stat(yyfilename, &sinf)) { perror (PROJECT); exit (EXIT_FAILURE); } yy_delete_buffer (YY_CURRENT_BUFFER); yy_switch_to_buffer (yy_create_buffer (yyin, sinf.st_size+10)); } void begin_speedmode() { #ifdef LEXER_DEBUG fprintf (stderr, "\n STATUS: begin_speedmode() -- STATE SPEEDMODE"); #endif BEGIN SPEEDMODE; } void chg_strdelims (const char asesc, const char asdel) { #ifdef LEXER_DEBUG fprintf (stderr, "\n STATUS: chg_strdelims ('%c', '%c')", asesc, asdel); #endif sesc = asesc; sdel = asdel; } /*EOF*/ /* vim: set cindent sw=4: */ boxes-1.2/src/misc/000077500000000000000000000000001306272555200142255ustar00rootroot00000000000000boxes-1.2/src/misc/README.misc.md000066400000000000000000000002161306272555200164350ustar00rootroot00000000000000###getopt Library This is used only for the Win32 build. Used under the terms of the GPL. For license information, see source file headers. boxes-1.2/src/misc/getopt.c000066400000000000000000000726271306272555200157110ustar00rootroot00000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to drepper@gnu.org before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. 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. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO # define _NO_PROTO #endif #ifdef HAVE_CONFIG_H # include #endif #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 # include # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION # define ELIDE_CODE # endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ # include # include #endif /* GNU C library. */ #ifdef VMS # include # if HAVE_STRING_H - 0 # include # endif #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ # ifdef HAVE_LIBINTL_H # include # define _(msgid) gettext (msgid) # else # define _(msgid) (msgid) # endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char * optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ # include # define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ #ifndef getenv extern char *getenv (); #endif #ifndef strncmp extern int strncmp (); #endif static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ # if (!defined __STDC__ || !__STDC__) && !defined strlen /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); # endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void __attribute__ ((unused)) store_args_and_env (int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } # ifdef text_set_element text_set_element (__libc_subinit, store_args_and_env); # endif /* text_set_element */ # define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } #else /* !_LIBC */ # define SWAP_FLAGS(ch1, ch2) #endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined __STDC__ && __STDC__ static void exchange (char **); #endif static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ #ifdef _LIBC /* First make sure the handling of the `__getopt_nonoption_flags' string can work normally. Our top argument must be in the range of the string. */ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { /* We must extend the array. The user plays games with us and presents new arguments. */ char *new_str = malloc (top + 1); if (new_str == NULL) nonoption_flags_len = nonoption_flags_max_len = 0; else { memset (__mempcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len), '\0', top + 1 - nonoption_flags_max_len); nonoption_flags_max_len = top + 1; __getopt_nonoption_flags = new_str; } } #endif while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined __STDC__ && __STDC__ static const char *_getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { if (nonoption_flags_max_len == 0) { if (__getopt_nonoption_flags == NULL || __getopt_nonoption_flags[0] == '\0') nonoption_flags_max_len = -1; else { const char *orig_str = __getopt_nonoption_flags; int len = nonoption_flags_max_len = strlen (orig_str); if (nonoption_flags_max_len < argc) nonoption_flags_max_len = argc; __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); if (__getopt_nonoption_flags == NULL) nonoption_flags_max_len = -1; else memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), '\0', nonoption_flags_max_len - len); } } nonoption_flags_len = nonoption_flags_max_len; } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (optind == 0 || !__getopt_initialized) { if (optind == 0) optind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) { optarg = nameend + 1; } else { if (opterr) if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); nextchar += strlen (nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- '%c'\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) fprintf (stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, _("%s: option requires an argument -- '%c'\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ boxes-1.2/src/misc/getopt.h000066400000000000000000000075301306272555200157050ustar00rootroot00000000000000/* Declarations for getopt. Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@gnu.org. 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 _GETOPT_H #define _GETOPT_H 1 /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char * optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ int opterr; /* Set to an option character which was unrecognized. */ int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #endif /* getopt.h */ boxes-1.2/src/parser.y000066400000000000000000000672501306272555200147720ustar00rootroot00000000000000%{ /* * File: parser.y * Date created: March 16, 1999 (Tuesday, 17:17h) * Author: Copyright (C) 1999 Thomas Jensen * Language: GNU bison (ANSI C) * Web Site: http://boxes.thomasjensen.com/ * Purpose: Yacc parser for boxes configuration files * * License: o 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. * o 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. * o 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "config.h" #include #include #include #include #include "shape.h" #include "boxes.h" #include "tools.h" #include "lexer.h" const char rcsid_parser_y[] = "$Id: parser.y,v 1.25 2006/07/23 16:11:39 tsjensen Exp $"; static int pflicht = 0; static int time_for_se_check = 0; static int anz_shapespec = 0; /* number of user-specified shapes */ int speeding = 0; /* true if we're skipping designs, */ /* but no error */ static int skipping = 0; /* used to limit "skipping" msgs */ static int check_sizes() /* * For the author's convenience, it is required that shapes on one side * have equal width (vertical sides) and height (horizontal sides). * * RETURNS: == 0 no problem detected * != 0 on error (prints error message, too) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int i, j, k; #ifdef PARSER_DEBUG fprintf (stderr, "check_sizes()\n"); #endif for (i=0; i KEYWORD %token WORD %token STRING %token SHAPE %token YNUMBER %token YRXPFLAG %token YDELWORD %type shape_def %type shape_lines %type rflag %start first_rule %% first_rule: { /* * Initialize parser data structures */ designs = (design_t *) calloc (1, sizeof(design_t)); if (designs == NULL) { perror (PROJECT); YYABORT; } designs->indentmode = DEF_INDENTMODE; } config_file { /* * Clean up parser data structures */ design_t *tmp; if (design_idx == 0) { BFREE (designs); anz_designs = 0; if (opt.design_choice_by_user) { fprintf (stderr, "%s: unknown box design -- %s\n", PROJECT, (char *) opt.design); } else { yyerror ("no valid designs found"); } YYABORT; } --design_idx; anz_designs = design_idx + 1; tmp = (design_t *) realloc (designs, anz_designs*sizeof(design_t)); if (!tmp) { perror (PROJECT); YYABORT; } designs = tmp; } ; config_file: config_file design_or_error | design_or_error ; design_or_error: design | error { if (!speeding && !skipping) { recover(); yyerror ("skipping to next design"); skipping = 1; } } ; design: YBOX WORD { chg_strdelims ('\\', '\"'); skipping = 0; if (!design_needed ($2, design_idx)) { speeding = 1; begin_speedmode(); YYERROR; } } layout YEND WORD { design_t *tmp; int i; char *p; #ifdef PARSER_DEBUG fprintf (stderr, "--------- ADDING DESIGN \"%s\".\n", $2); #endif if (strcasecmp ($2, $6)) { yyerror ("box design name differs at BOX and END"); YYERROR; } if (pflicht < 3) { yyerror ("entries SAMPLE, SHAPES, and ELASTIC are mandatory"); YYERROR; } for (i=0; i 126) { yyerror ("box design name must consist of printable standard " "ASCII characters."); YYERROR; } ++p; } designs[design_idx].name = (char *) strdup ($2); if (designs[design_idx].name == NULL) { perror (PROJECT); YYABORT; } pflicht = 0; time_for_se_check = 0; anz_shapespec = 0; /* * Check if we need to continue parsing. If not, return. * The condition here must correspond to design_needed(). */ if (opt.design_choice_by_user || (!opt.r && !opt.l)) { anz_designs = design_idx + 1; YYACCEPT; } /* * Allocate space for next design */ ++design_idx; tmp = (design_t *) realloc (designs, (design_idx+1)*sizeof(design_t)); if (tmp == NULL) { perror (PROJECT); YYABORT; } designs = tmp; memset (&(designs[design_idx]), 0, sizeof(design_t)); designs[design_idx].indentmode = DEF_INDENTMODE; } ; layout: layout entry | layout block | entry | block ; entry: KEYWORD STRING { #ifdef PARSER_DEBUG fprintf (stderr, "entry rule fulfilled [%s = %s]\n", $1, $2); #endif if (strcasecmp ($1, "author") == 0) { designs[design_idx].author = (char *) strdup ($2); if (designs[design_idx].author == NULL) { perror (PROJECT); YYABORT; } } else if (strcasecmp ($1, "designer") == 0) { designs[design_idx].designer = (char *) strdup ($2); if (designs[design_idx].designer == NULL) { perror (PROJECT); YYABORT; } } else if (strcasecmp ($1, "revision") == 0) { designs[design_idx].revision = (char *) strdup ($2); if (designs[design_idx].revision == NULL) { perror (PROJECT); YYABORT; } } else if (strcasecmp ($1, "created") == 0) { designs[design_idx].created = (char *) strdup ($2); if (designs[design_idx].created == NULL) { perror (PROJECT); YYABORT; } } else if (strcasecmp ($1, "revdate") == 0) { designs[design_idx].revdate = (char *) strdup ($2); if (designs[design_idx].revdate == NULL) { perror (PROJECT); YYABORT; } } else if (strcasecmp ($1, "indent") == 0) { if (strcasecmp ($2, "text") == 0 || strcasecmp ($2, "box") == 0 || strcasecmp ($2, "none") == 0) { designs[design_idx].indentmode = $2[0]; } else { yyerror ("indent keyword must be followed by \"text\", " "\"box\", or \"none\""); YYERROR; } } else { yyerror ("internal parser error (unrecognized: %s) in line %d " "of %s.", $1, __LINE__, __FILE__); YYERROR; } } | YCHGDEL YDELWORD { if (strlen($2) != 2) { yyerror ("invalid string delimiter specification -- %s", $2); YYERROR; } if (($2)[0] == ($2)[1]) { yyerror ("string delimiter and escape char may not be the same"); YYERROR; } if (strchr (LEX_SDELIM, ($2)[1]) == NULL) { yyerror ("invalid string delimiter -- %c (try one of %s)", ($2)[1], LEX_SDELIM); YYERROR; } chg_strdelims ($2[0], $2[1]); } | WORD STRING { #ifdef PARSER_DEBUG fprintf (stderr, "%s: Discarding entry [%s = %s].\n", PROJECT, $1, $2); #endif } ; block: YSAMPLE STRING YENDSAMPLE { /* * SAMPLE block (STRING is non-empty if we get here) */ char *line; #ifdef PARSER_DEBUG fprintf (stderr, "SAMPLE block rule satisfied\n"); #endif if (designs[design_idx].sample) { yyerror ("duplicate SAMPLE block"); YYERROR; } line = (char *) strdup ($2); if (line == NULL) { perror (PROJECT); YYABORT; } designs[design_idx].sample = line; ++pflicht; } | YSHAPES '{' slist '}' { int i,j; shape_t fshape; /* found shape */ int fside; /* first side */ int sc; /* side counter */ int side; /* effective side */ int rc; /* received return code */ /* * At least one shape must be specified */ if (anz_shapespec < 1) { yyerror ("must specify at least one non-empty shape per design"); YYERROR; } /* * Ensure that all corners have been specified. Generate corners * as necessary, starting at any side which already includes at * least one shape in order to ensure correct measurements. */ fshape = findshape (designs[design_idx].shape, ANZ_SHAPES); if (fshape == ANZ_SHAPES) { yyerror ("internal error"); YYABORT; /* never happens ;-) */ } fside = on_side (fshape, 0); if (fside == ANZ_SIDES) { yyerror ("internal error"); YYABORT; /* never happens ;-) */ } for (sc=0,side=fside; scheight = 1; else c->height = c[nshape].height; c->width = designs[design_idx].shape[fshape].width; } else { if (nshape == SHAPES_PER_SIDE) c->width = 1; else c->width = c[nshape].width; c->height = designs[design_idx].shape[fshape].height; } c->elastic = 0; rc = genshape (c->width, c->height, &(c->chars)); if (rc) YYABORT; } fshape = sides[side][SHAPES_PER_SIDE-1]; } /* * For all sides whose side shapes have not been defined, generate * an elastic middle side shape. */ for (side=0; sidewidth = designs[design_idx].shape[sides[side][0]].width; c->height = 1; } else { c->width = 1; c->height = designs[design_idx].shape[sides[side][0]].height; } c->elastic = 1; rc = genshape (c->width, c->height, &(c->chars)); if (rc) YYABORT; } } if (check_sizes()) YYERROR; ++pflicht; if (++time_for_se_check > 1) { if (perform_se_check() != 0) YYERROR; } /* * Compute minimum height/width of a box of current design */ for (i=0; i designs[design_idx].minheight) designs[design_idx].minheight = c; } else { /* horizontal sides */ for (j=0; j designs[design_idx].minwidth) designs[design_idx].minwidth = c; } } /* * Compute height of highest shape in design */ for (i=0; i designs[design_idx].maxshapeheight) designs[design_idx].maxshapeheight = designs[design_idx].shape[i].height; } #ifdef PARSER_DEBUG fprintf (stderr, "Minimum box dimensions: width %d height %d\n", designs[design_idx].minwidth, designs[design_idx].minheight); fprintf (stderr, "Maximum shape height: %d\n", designs[design_idx].maxshapeheight); #endif } | YELASTIC '(' elist ')' { ++pflicht; if (++time_for_se_check > 1) { if (perform_se_check() != 0) YYERROR; } } | YREPLACE rflag STRING YWITH STRING { int a = designs[design_idx].anz_reprules; #ifdef PARSER_DEBUG fprintf (stderr, "Adding replacement rule: \"%s\" with \"%s\" (%c)\n", $3, $5, $2); #endif designs[design_idx].reprules = (reprule_t *) realloc (designs[design_idx].reprules, (a+1) * sizeof(reprule_t)); if (designs[design_idx].reprules == NULL) { perror (PROJECT); YYABORT; } memset (&(designs[design_idx].reprules[a]), 0, sizeof(reprule_t)); designs[design_idx].reprules[a].search = (char *) strdup ($3); designs[design_idx].reprules[a].repstr = (char *) strdup ($5); if (designs[design_idx].reprules[a].search == NULL || designs[design_idx].reprules[a].repstr == NULL) { perror (PROJECT); YYABORT; } designs[design_idx].reprules[a].line = tjlineno; designs[design_idx].reprules[a].mode = $2; designs[design_idx].anz_reprules = a + 1; } | YREVERSE rflag STRING YTO STRING { int a = designs[design_idx].anz_revrules; #ifdef PARSER_DEBUG fprintf (stderr, "Adding reversion rule: \"%s\" to \"%s\" (%c)\n", $3, $5, $2); #endif designs[design_idx].revrules = (reprule_t *) realloc (designs[design_idx].revrules, (a+1) * sizeof(reprule_t)); if (designs[design_idx].revrules == NULL) { perror (PROJECT); YYABORT; } memset (&(designs[design_idx].revrules[a]), 0, sizeof(reprule_t)); designs[design_idx].revrules[a].search = (char *) strdup ($3); designs[design_idx].revrules[a].repstr = (char *) strdup ($5); if (designs[design_idx].revrules[a].search == NULL || designs[design_idx].revrules[a].repstr == NULL) { perror (PROJECT); YYABORT; } designs[design_idx].revrules[a].line = tjlineno; designs[design_idx].revrules[a].mode = $2; designs[design_idx].anz_revrules = a + 1; } | YPADDING '{' wlist '}' { #ifdef PARSER_DEBUG fprintf (stderr, "Padding set to (l%d o%d r%d u%d)\n", designs[design_idx].padding[BLEF], designs[design_idx].padding[BTOP], designs[design_idx].padding[BRIG], designs[design_idx].padding[BBOT]); #endif } ; rflag: YRXPFLAG { $$ = $1; } | { $$ = 'g'; } ; elist: elist ',' elist_entry | elist_entry; elist_entry: SHAPE { #ifdef PARSER_DEBUG fprintf (stderr, "Marked \'%s\' shape as elastic\n", shape_name[(int)$1]); #endif designs[design_idx].shape[$1].elastic = 1; } ; slist: slist slist_entry | slist_entry ; slist_entry: SHAPE shape_def { #ifdef PARSER_DEBUG fprintf (stderr, "Adding shape spec for \'%s\' (width %d " "height %d)\n", shape_name[$1], $2.width, $2.height); #endif if (isempty (designs[design_idx].shape + $1)) { designs[design_idx].shape[$1] = $2; if (!isdeepempty(&($2))) ++anz_shapespec; } else { yyerror ("duplicate specification for %s shape", shape_name[$1]); YYERROR; } } ; shape_def: '(' shape_lines ')' { if ($2.width == 0 || $2.height == 0) { yyerror ("minimum shape dimension is 1x1 - clearing"); freeshape (&($2)); } $$ = $2; } | '(' ')' { $$ = SENTRY_INITIALIZER; } ; shape_lines: shape_lines ',' STRING { sentry_t rval = $1; size_t slen = strlen ($3); char **tmp; #ifdef PARSER_DEBUG fprintf (stderr, "Extending a shape entry\n"); #endif if (slen != rval.width) { yyerror ("all elements of a shape spec must be of equal length"); YYERROR; } rval.height++; tmp = (char **) realloc (rval.chars, rval.height*sizeof(char*)); if (tmp == NULL) { perror (PROJECT": shape_lines11"); YYABORT; } rval.chars = tmp; rval.chars[rval.height-1] = (char *) strdup ($3); if (rval.chars[rval.height-1] == NULL) { perror (PROJECT": shape_lines12"); YYABORT; } $$ = rval; } | STRING { sentry_t rval = SENTRY_INITIALIZER; #ifdef PARSER_DEBUG fprintf (stderr, "Initializing a shape entry with first line\n"); #endif rval.width = strlen ($1); rval.height = 1; rval.chars = (char **) malloc (sizeof(char*)); if (rval.chars == NULL) { perror (PROJECT": shape_lines21"); YYABORT; } rval.chars[0] = (char *) strdup ($1); if (rval.chars[0] == NULL) { perror (PROJECT": shape_lines22"); YYABORT; } $$ = rval; } ; wlist: wlist wlist_entry | wlist_entry; wlist_entry: WORD YNUMBER { if ($2 < 0) { yyerror ("padding must be a positive integer (%s %d) (ignored)", $1, $2); } else { size_t len1 = strlen ($1); if (len1 <= 3 && !strncasecmp ("all", $1, len1)) { designs[design_idx].padding[BTOP] = $2; designs[design_idx].padding[BBOT] = $2; designs[design_idx].padding[BLEF] = $2; designs[design_idx].padding[BRIG] = $2; } else if (len1 <= 10 && !strncasecmp ("horizontal", $1, len1)) { designs[design_idx].padding[BRIG] = $2; designs[design_idx].padding[BLEF] = $2; } else if (len1 <= 8 && !strncasecmp ("vertical", $1, len1)) { designs[design_idx].padding[BTOP] = $2; designs[design_idx].padding[BBOT] = $2; } else if (len1 <= 3 && !strncasecmp ("top", $1, len1)) { designs[design_idx].padding[BTOP] = $2; } else if (len1 <= 5 && !strncasecmp ("right", $1, len1)) { designs[design_idx].padding[BRIG] = $2; } else if (len1 <= 4 && !strncasecmp ("left", $1, len1)) { designs[design_idx].padding[BLEF] = $2; } else if (len1 <= 6 && !strncasecmp ("bottom", $1, len1)) { designs[design_idx].padding[BBOT] = $2; } else { yyerror ("invalid padding area %s (ignored)", $1); } } } ; %% /*EOF*/ /* vim: set sw=4 cindent: */ boxes-1.2/src/regexp/000077500000000000000000000000001306272555200145645ustar00rootroot00000000000000boxes-1.2/src/regexp/Makefile000066400000000000000000000034711306272555200162310ustar00rootroot00000000000000# # File: Makefile # Creation: August 13, 1999 (Friday, 22:13h) # Author: Copyright (C) 1999 Thomas Jensen # Format: GNU make # Web Site: http://boxes.thomasjensen.com/ # Purpose: Makefile for boxes, the box drawing program # generation of regexp handling library # # License: o 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. # o 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. # o 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 #____________________________________________________________________________ #============================================================================ CFLAGS = -O -I. $(CFLAGS_ADDTL) ALL_CL = regexp/regexp.c regexp/regsub.c C_SRC = $(notdir $(ALL_CL)) ALLFILES = Makefile $(C_SRC) regexp.h regmagic.h ALLOBJ = $(C_SRC:.c=.o) .PHONY: clean build debug build: libregexp.a debug: libregexp.a libregexp.a: $(ALLOBJ) ar cr libregexp.a $(ALLOBJ) regexp.o: regexp.c regmagic.h regexp.h ../config.h regsub.o: regsub.c regmagic.h regexp.h ../config.h .c.o: $(CC) $(CFLAGS) -c $< clean: rm -f $(ALLOBJ) libregexp.a core #EOF boxes-1.2/src/regexp/regexp.c000066400000000000000000000657771306272555200162500ustar00rootroot00000000000000/* * regcomp and regexec -- regsub and regerror are elsewhere * * Copyright (c) 1986 by University of Toronto. * Written by Henry Spencer. Not derived from licensed software. * * Permission is granted to anyone to use this software for any * purpose on any computer system, and to redistribute it freely, * subject to the following restrictions: * * 1. The author is not responsible for the consequences of use of * this software, no matter how awful, even if they arise * from defects in it. * * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * Beware that some of this code is subtly aware of the way operator * precedence is structured in regular expressions. Serious changes in * regular-expression syntax might require a total rethink. */ #include #include #include #include #include "regmagic.h" char rcsid_regexp_c[] = "$Id: regexp.c,v 1.5 2006/07/23 16:28:13 tsjensen Exp $"; /* * The "internal use only" fields in regexp.h are present to pass info from * compile to execute that permits the execute phase to run lots faster on * simple cases. They are: * * regstart char that must begin a match; '\0' if none obvious * reganch is the match anchored (at beginning-of-line only)? * regmust string (pointer into program) that match must include, or NULL * regmlen length of regmust string * * Regstart and reganch permit very fast decisions on suitable starting points * for a match, cutting down the work a lot. Regmust permits fast rejection * of lines that cannot possibly match. The regmust tests are costly enough * that regcomp() supplies a regmust only if the r.e. contains something * potentially expensive (at present, the only such thing detected is * or + * at the start of the r.e., which can involve a lot of backup). Regmlen is * supplied because the test in regexec() needs it and regcomp() is computing * it anyway. */ /* * Structure for regexp "program". This is essentially a linear encoding * of a nondeterministic finite-state machine (aka syntax charts or * "railroad normal form" in parsing technology). Each node is an opcode * plus a "next" pointer, possibly plus an operand. "Next" pointers of * all nodes except BRANCH implement concatenation; a "next" pointer with * a BRANCH on both ends of it is connecting two alternatives. (Here we * have one of the subtle syntax dependencies: an individual BRANCH (as * opposed to a collection of them) is never concatenated with anything * because of operator precedence.) The operand of some types of node is * a literal string; for others, it is a node leading into a sub-FSM. In * particular, the operand of a BRANCH node is the first node of the branch. * (NB this is *not* a tree structure: the tail of the branch connects * to the thing following the set of BRANCHes.) The opcodes are: */ /* definition number opnd? meaning */ #define END 0 /* no End of program. */ #define BOL 1 /* no Match "" at beginning of line. */ #define EOL 2 /* no Match "" at end of line. */ #define ANY 3 /* no Match any one character. */ #define ANYOF 4 /* str Match any character in this string. */ #define ANYBUT 5 /* str Match any character not in this string. */ #define BRANCH 6 /* node Match this alternative, or the next... */ #define BACK 7 /* no Match "", "next" ptr points backward. */ #define EXACTLY 8 /* str Match this string. */ #define NOTHING 9 /* no Match empty string. */ #define STAR 10 /* node Match this (simple) thing 0 or more times. */ #define PLUS 11 /* node Match this (simple) thing 1 or more times. */ #define OPEN 20 /* no Mark this point in input as start of #n. */ /* OPEN+1 is number 1, etc. */ #define CLOSE 30 /* no Analogous to OPEN. */ /* * Opcode notes: * * BRANCH The set of branches constituting a single choice are hooked * together with their "next" pointers, since precedence prevents * anything being concatenated to any individual branch. The * "next" pointer of the last BRANCH in a choice points to the * thing following the whole choice. This is also where the * final "next" pointer of each individual branch points; each * branch starts with the operand node of a BRANCH node. * * BACK Normal "next" pointers all implicitly point forward; BACK * exists to make loop structures possible. * * STAR,PLUS '?', and complex '*' and '+', are implemented as circular * BRANCH structures using BACK. Simple cases (one character * per match) are implemented with STAR and PLUS for speed * and to minimize recursive plunges. * * OPEN,CLOSE ...are numbered at compile time. */ /* * A node is one char of opcode followed by two chars of "next" pointer. * "Next" pointers are stored as two 8-bit pieces, high order first. The * value is a positive offset from the opcode of the node containing it. * An operand, if any, simply follows the node. (Note that much of the * code generation knows about this implicit relationship.) * * Using two bytes for the "next" pointer is vast overkill for most things, * but allows patterns to get big without disasters. */ #define OP(p) (*(p)) #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) #define OPERAND(p) ((p) + 3) /* * See regmagic.h for one further detail of program structure. */ /* * Utility definitions. */ #ifndef CHARBITS #define UCHARAT(p) ((int)*(unsigned char *)(p)) #else #define UCHARAT(p) ((int)*(p)&CHARBITS) #endif #define FAIL(m) { regerror(m); return(NULL); } #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') #define META "^$.[()|?+*\\" /* * Flags to be passed up and down. */ #define HASWIDTH 01 /* Known never to match null string. */ #define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ #define SPSTART 04 /* Starts with * or +. */ #define WORST 0 /* Worst case. */ /* * Global work variables for regcomp(). */ static char *regparse; /* Input-scan pointer. */ static int regnpar; /* () count. */ static char regdummy; static char *regcode; /* Code-emit pointer; ®dummy = don't. */ static long regsize; /* Code size. */ /* * Forward declarations for regcomp()'s friends. */ #ifndef STATIC #define STATIC static #endif STATIC char *reg(); STATIC char *regbranch(); STATIC char *regpiece(); STATIC char *regatom(); STATIC char *regnode(); STATIC char *regnext(); STATIC void regc(); STATIC void reginsert(); STATIC void regtail(); STATIC void regoptail(); #ifdef STRCSPN STATIC int strcspn(); #endif /* - regcomp - compile a regular expression into internal code * * We can't allocate space until we know how big the compiled form will be, * but we can't compile it (and thus know how big it is) until we've got a * place to put the code. So we cheat: we compile it twice, once with code * generation turned off and size counting turned on, and once "for real". * This also means that we don't allocate space until we are sure that the * thing really will compile successfully, and we never have to move the * code and thus invalidate pointers into it. (Note that it has to be in * one piece because free() must be able to free it all.) * * Beware that the optimization-preparation code in here knows about some * of the structure of the compiled regexp. */ regexp * regcomp(exp) char *exp; { register regexp *r; register char *scan; register char *longest; register int len; int flags; if (exp == NULL) FAIL("NULL argument"); /* First pass: determine size, legality. */ regparse = exp; regnpar = 1; regsize = 0L; regcode = ®dummy; regc(MAGIC); if (reg(0, &flags) == NULL) return(NULL); /* Small enough for pointer-storage convention? */ if (regsize >= 32767L) /* Probably could be 65535L. */ FAIL("regexp too big"); /* Allocate space. */ r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize); if (r == NULL) FAIL("out of space"); /* Second pass: emit code. */ regparse = exp; regnpar = 1; regcode = r->program; regc(MAGIC); if (reg(0, &flags) == NULL) return(NULL); /* Dig out information for optimizations. */ r->regstart = '\0'; /* Worst-case defaults. */ r->reganch = 0; r->regmust = NULL; r->regmlen = 0; scan = r->program+1; /* First BRANCH. */ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ scan = OPERAND(scan); /* Starting-point info. */ if (OP(scan) == EXACTLY) r->regstart = *OPERAND(scan); else if (OP(scan) == BOL) r->reganch++; /* * If there's something expensive in the r.e., find the * longest literal string that must appear and make it the * regmust. Resolve ties in favor of later strings, since * the regstart check works with the beginning of the r.e. * and avoiding duplication strengthens checking. Not a * strong reason, but sufficient in the absence of others. */ if (flags&SPSTART) { longest = NULL; len = 0; for (; scan != NULL; scan = regnext(scan)) if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { longest = OPERAND(scan); len = strlen(OPERAND(scan)); } r->regmust = longest; r->regmlen = len; } } return(r); } /* - reg - regular expression, i.e. main body or parenthesized thing * * Caller must absorb opening parenthesis. * * Combining parenthesis handling with the base level of regular expression * is a trifle forced, but the need to tie the tails of the branches to what * follows makes it hard to avoid. */ static char * reg(paren, flagp) int paren; /* Parenthesized? */ int *flagp; { register char *ret; register char *br; register char *ender; register int parno; int flags; *flagp = HASWIDTH; /* Tentatively. */ /* Make an OPEN node, if parenthesized. */ if (paren) { if (regnpar >= NSUBEXP) FAIL("too many ()"); parno = regnpar; regnpar++; ret = regnode(OPEN+parno); } else ret = NULL; /* Pick up the branches, linking them together. */ br = regbranch(&flags); if (br == NULL) return(NULL); if (ret != NULL) regtail(ret, br); /* OPEN -> first. */ else ret = br; if (!(flags&HASWIDTH)) *flagp &= ~HASWIDTH; *flagp |= flags&SPSTART; while (*regparse == '|') { regparse++; br = regbranch(&flags); if (br == NULL) return(NULL); regtail(ret, br); /* BRANCH -> BRANCH. */ if (!(flags&HASWIDTH)) *flagp &= ~HASWIDTH; *flagp |= flags&SPSTART; } /* Make a closing node, and hook it on the end. */ ender = regnode((paren) ? CLOSE+parno : END); regtail(ret, ender); /* Hook the tails of the branches to the closing node. */ for (br = ret; br != NULL; br = regnext(br)) regoptail(br, ender); /* Check for proper termination. */ if (paren && *regparse++ != ')') { FAIL("unmatched ()"); } else if (!paren && *regparse != '\0') { if (*regparse == ')') { FAIL("unmatched ()"); } else FAIL("junk on end"); /* "Can't happen". */ /* NOTREACHED */ } return(ret); } /* - regbranch - one alternative of an | operator * * Implements the concatenation operator. */ static char * regbranch(flagp) int *flagp; { register char *ret; register char *chain; register char *latest; int flags; *flagp = WORST; /* Tentatively. */ ret = regnode(BRANCH); chain = NULL; while (*regparse != '\0' && *regparse != '|' && *regparse != ')') { latest = regpiece(&flags); if (latest == NULL) return(NULL); *flagp |= flags&HASWIDTH; if (chain == NULL) /* First piece. */ *flagp |= flags&SPSTART; else regtail(chain, latest); chain = latest; } if (chain == NULL) /* Loop ran zero times. */ (void) regnode(NOTHING); return(ret); } /* - regpiece - something followed by possible [*+?] * * Note that the branching code sequences used for ? and the general cases * of * and + are somewhat optimized: they use the same NOTHING node as * both the endmarker for their branch list and the body of the last branch. * It might seem that this node could be dispensed with entirely, but the * endmarker role is not redundant. */ static char * regpiece(flagp) int *flagp; { register char *ret; register char op; register char *next; int flags; ret = regatom(&flags); if (ret == NULL) return(NULL); op = *regparse; if (!ISMULT(op)) { *flagp = flags; return(ret); } if (!(flags&HASWIDTH) && op != '?') FAIL("*+ operand could be empty"); *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); if (op == '*' && (flags&SIMPLE)) reginsert(STAR, ret); else if (op == '*') { /* Emit x* as (x&|), where & means "self". */ reginsert(BRANCH, ret); /* Either x */ regoptail(ret, regnode(BACK)); /* and loop */ regoptail(ret, ret); /* back */ regtail(ret, regnode(BRANCH)); /* or */ regtail(ret, regnode(NOTHING)); /* null. */ } else if (op == '+' && (flags&SIMPLE)) reginsert(PLUS, ret); else if (op == '+') { /* Emit x+ as x(&|), where & means "self". */ next = regnode(BRANCH); /* Either */ regtail(ret, next); regtail(regnode(BACK), ret); /* loop back */ regtail(next, regnode(BRANCH)); /* or */ regtail(ret, regnode(NOTHING)); /* null. */ } else if (op == '?') { /* Emit x? as (x|) */ reginsert(BRANCH, ret); /* Either x */ regtail(ret, regnode(BRANCH)); /* or */ next = regnode(NOTHING); /* null. */ regtail(ret, next); regoptail(ret, next); } regparse++; if (ISMULT(*regparse)) FAIL("nested *?+"); return(ret); } /* - regatom - the lowest level * * Optimization: gobbles an entire sequence of ordinary characters so that * it can turn them into a single node, which is smaller to store and * faster to run. Backslashed characters are exceptions, each becoming a * separate node; the code is simpler that way and it's not worth fixing. */ static char * regatom(flagp) int *flagp; { register char *ret; int flags; *flagp = WORST; /* Tentatively. */ switch (*regparse++) { case '^': ret = regnode(BOL); break; case '$': ret = regnode(EOL); break; case '.': ret = regnode(ANY); *flagp |= HASWIDTH|SIMPLE; break; case '[': { register int class; register int classend; if (*regparse == '^') { /* Complement of range. */ ret = regnode(ANYBUT); regparse++; } else ret = regnode(ANYOF); if (*regparse == ']' || *regparse == '-') regc(*regparse++); while (*regparse != '\0' && *regparse != ']') { if (*regparse == '-') { regparse++; if (*regparse == ']' || *regparse == '\0') regc('-'); else { class = UCHARAT(regparse-2)+1; classend = UCHARAT(regparse); if (class > classend+1) FAIL("invalid [] range"); for (; class <= classend; class++) regc(class); regparse++; } } else regc(*regparse++); } regc('\0'); if (*regparse != ']') FAIL("unmatched []"); regparse++; *flagp |= HASWIDTH|SIMPLE; } break; case '(': ret = reg(1, &flags); if (ret == NULL) return(NULL); *flagp |= flags&(HASWIDTH|SPSTART); break; case '\0': case '|': case ')': FAIL("internal urp"); /* Supposed to be caught earlier. */ break; case '?': case '+': case '*': FAIL("?+* follows nothing"); break; case '\\': if (*regparse == '\0') FAIL("trailing \\"); ret = regnode(EXACTLY); regc(*regparse++); regc('\0'); *flagp |= HASWIDTH|SIMPLE; break; default: { register int len; register char ender; regparse--; len = strcspn(regparse, META); if (len <= 0) FAIL("internal disaster"); ender = *(regparse+len); if (len > 1 && ISMULT(ender)) len--; /* Back off clear of ?+* operand. */ *flagp |= HASWIDTH; if (len == 1) *flagp |= SIMPLE; ret = regnode(EXACTLY); while (len > 0) { regc(*regparse++); len--; } regc('\0'); } break; } return(ret); } /* - regnode - emit a node */ static char * /* Location. */ regnode(op) char op; { register char *ret; register char *ptr; ret = regcode; if (ret == ®dummy) { regsize += 3; return(ret); } ptr = ret; *ptr++ = op; *ptr++ = '\0'; /* Null "next" pointer. */ *ptr++ = '\0'; regcode = ptr; return(ret); } /* - regc - emit (if appropriate) a byte of code */ static void regc(b) char b; { if (regcode != ®dummy) *regcode++ = b; else regsize++; } /* - reginsert - insert an operator in front of already-emitted operand * * Means relocating the operand. */ static void reginsert(op, opnd) char op; char *opnd; { register char *src; register char *dst; register char *place; if (regcode == ®dummy) { regsize += 3; return; } src = regcode; regcode += 3; dst = regcode; while (src > opnd) *--dst = *--src; place = opnd; /* Op node, where operand used to be. */ *place++ = op; *place++ = '\0'; *place++ = '\0'; } /* - regtail - set the next-pointer at the end of a node chain */ static void regtail(p, val) char *p; char *val; { register char *scan; register char *temp; register int offset; if (p == ®dummy) return; /* Find last node. */ scan = p; for (;;) { temp = regnext(scan); if (temp == NULL) break; scan = temp; } if (OP(scan) == BACK) offset = scan - val; else offset = val - scan; *(scan+1) = (offset>>8)&0377; *(scan+2) = offset&0377; } /* - regoptail - regtail on operand of first argument; nop if operandless */ static void regoptail(p, val) char *p; char *val; { /* "Operandless" and "op != BRANCH" are synonymous in practice. */ if (p == NULL || p == ®dummy || OP(p) != BRANCH) return; regtail(OPERAND(p), val); } /* * regexec and friends */ /* * Global work variables for regexec(). */ static char *reginput; /* String-input pointer. */ static char *regbol; /* Beginning of input, for ^ check. */ static char **regstartp; /* Pointer to startp array. */ static char **regendp; /* Ditto for endp. */ /* * Forwards. */ STATIC int regtry(); STATIC int regmatch(); STATIC int regrepeat(); #ifdef DEBUG int regnarrate = 0; void regdump(); STATIC char *regprop(); #endif /* - regexec - match a regexp against a string */ int regexec(prog, string) register regexp *prog; register char *string; { register char *s; /* Be paranoid... */ if (prog == NULL || string == NULL) { regerror("NULL parameter"); return(0); } /* Check validity of program. */ if (UCHARAT(prog->program) != MAGIC) { regerror("corrupted program"); return(0); } /* If there is a "must appear" string, look for it. */ if (prog->regmust != NULL) { s = string; while ((s = strchr(s, prog->regmust[0])) != NULL) { if (strncmp(s, prog->regmust, prog->regmlen) == 0) break; /* Found it. */ s++; } if (s == NULL) /* Not present. */ return(0); } /* Mark beginning of line for ^ . */ regbol = string; /* Simplest case: anchored match need be tried only once. */ if (prog->reganch) return(regtry(prog, string)); /* Messy cases: unanchored match. */ s = string; if (prog->regstart != '\0') /* We know what char it must start with. */ while ((s = strchr(s, prog->regstart)) != NULL) { if (regtry(prog, s)) return(1); s++; } else /* We don't -- general case. */ do { if (regtry(prog, s)) return(1); } while (*s++ != '\0'); /* Failure. */ return(0); } /* - regtry - try match at specific point */ static int /* 0 failure, 1 success */ regtry(prog, string) regexp *prog; char *string; { register int i; register char **sp; register char **ep; reginput = string; regstartp = prog->startp; regendp = prog->endp; sp = prog->startp; ep = prog->endp; for (i = NSUBEXP; i > 0; i--) { *sp++ = NULL; *ep++ = NULL; } if (regmatch(prog->program + 1)) { prog->startp[0] = string; prog->endp[0] = reginput; return(1); } else return(0); } /* - regmatch - main matching routine * * Conceptually the strategy is simple: check to see whether the current * node matches, call self recursively to see whether the rest matches, * and then act accordingly. In practice we make some effort to avoid * recursion, in particular by going through "ordinary" nodes (that don't * need to know whether the rest of the match failed) by a loop instead of * by recursion. */ static int /* 0 failure, 1 success */ regmatch(prog) char *prog; { register char *scan; /* Current node. */ char *next; /* Next node. */ scan = prog; #ifdef DEBUG if (scan != NULL && regnarrate) fprintf(stderr, "%s(\n", regprop(scan)); #endif while (scan != NULL) { #ifdef DEBUG if (regnarrate) fprintf(stderr, "%s...\n", regprop(scan)); #endif next = regnext(scan); switch (OP(scan)) { case BOL: if (reginput != regbol) return(0); break; case EOL: if (*reginput != '\0') return(0); break; case ANY: if (*reginput == '\0') return(0); reginput++; break; case EXACTLY: { register int len; register char *opnd; opnd = OPERAND(scan); /* Inline the first character, for speed. */ if (*opnd != *reginput) return(0); len = strlen(opnd); if (len > 1 && strncmp(opnd, reginput, len) != 0) return(0); reginput += len; } break; case ANYOF: if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) return(0); reginput++; break; case ANYBUT: if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) return(0); reginput++; break; case NOTHING: break; case BACK: break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: { register int no; register char *save; no = OP(scan) - OPEN; save = reginput; if (regmatch(next)) { /* * Don't set startp if some later * invocation of the same parentheses * already has. */ if (regstartp[no] == NULL) regstartp[no] = save; return(1); } else return(0); } break; case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: { register int no; register char *save; no = OP(scan) - CLOSE; save = reginput; if (regmatch(next)) { /* * Don't set endp if some later * invocation of the same parentheses * already has. */ if (regendp[no] == NULL) regendp[no] = save; return(1); } else return(0); } break; case BRANCH: { register char *save; if (OP(next) != BRANCH) /* No choice. */ next = OPERAND(scan); /* Avoid recursion. */ else { do { save = reginput; if (regmatch(OPERAND(scan))) return(1); reginput = save; scan = regnext(scan); } while (scan != NULL && OP(scan) == BRANCH); return(0); /* NOTREACHED */ } } break; case STAR: case PLUS: { register char nextch; register int no; register char *save; register int min; /* * Lookahead to avoid useless match attempts * when we know what character comes next. */ nextch = '\0'; if (OP(next) == EXACTLY) nextch = *OPERAND(next); min = (OP(scan) == STAR) ? 0 : 1; save = reginput; no = regrepeat(OPERAND(scan)); while (no >= min) { /* If it could work, try it. */ if (nextch == '\0' || *reginput == nextch) if (regmatch(next)) return(1); /* Couldn't or didn't -- back up. */ no--; reginput = save + no; } return(0); } break; case END: return(1); /* Success! */ break; default: regerror("memory corruption"); return(0); break; } scan = next; } /* * We get here only if there's trouble -- normally "case END" is * the terminating point. */ regerror("corrupted pointers"); return(0); } /* - regrepeat - repeatedly match something simple, report how many */ static int regrepeat(p) char *p; { register int count = 0; register char *scan; register char *opnd; scan = reginput; opnd = OPERAND(p); switch (OP(p)) { case ANY: count = strlen(scan); scan += count; break; case EXACTLY: while (*opnd == *scan) { count++; scan++; } break; case ANYOF: while (*scan != '\0' && strchr(opnd, *scan) != NULL) { count++; scan++; } break; case ANYBUT: while (*scan != '\0' && strchr(opnd, *scan) == NULL) { count++; scan++; } break; default: /* Oh dear. Called inappropriately. */ regerror("internal foulup"); count = 0; /* Best compromise. */ break; } reginput = scan; return(count); } /* - regnext - dig the "next" pointer out of a node */ static char * regnext(p) register char *p; { register int offset; if (p == ®dummy) return(NULL); offset = NEXT(p); if (offset == 0) return(NULL); if (OP(p) == BACK) return(p-offset); else return(p+offset); } #ifdef DEBUG STATIC char *regprop(); /* - regdump - dump a regexp onto stdout in vaguely comprehensible form */ void regdump(r) regexp *r; { register char *s; register char op = EXACTLY; /* Arbitrary non-END op. */ register char *next; s = r->program + 1; while (op != END) { /* While that wasn't END last time... */ op = OP(s); printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ next = regnext(s); if (next == NULL) /* Next ptr. */ printf("(0)"); else printf("(%d)", (s-r->program)+(next-s)); s += 3; if (op == ANYOF || op == ANYBUT || op == EXACTLY) { /* Literal string, where present. */ while (*s != '\0') { putchar(*s); s++; } s++; } putchar('\n'); } /* Header fields of interest. */ if (r->regstart != '\0') printf("start `%c' ", r->regstart); if (r->reganch) printf("anchored "); if (r->regmust != NULL) printf("must have \"%s\"", r->regmust); printf("\n"); } /* - regprop - printable representation of opcode */ static char * regprop(op) char *op; { register char *p; static char buf[50]; (void) strcpy(buf, ":"); switch (OP(op)) { case BOL: p = "BOL"; break; case EOL: p = "EOL"; break; case ANY: p = "ANY"; break; case ANYOF: p = "ANYOF"; break; case ANYBUT: p = "ANYBUT"; break; case BRANCH: p = "BRANCH"; break; case EXACTLY: p = "EXACTLY"; break; case NOTHING: p = "NOTHING"; break; case BACK: p = "BACK"; break; case END: p = "END"; break; case OPEN+1: case OPEN+2: case OPEN+3: case OPEN+4: case OPEN+5: case OPEN+6: case OPEN+7: case OPEN+8: case OPEN+9: sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); p = NULL; break; case CLOSE+1: case CLOSE+2: case CLOSE+3: case CLOSE+4: case CLOSE+5: case CLOSE+6: case CLOSE+7: case CLOSE+8: case CLOSE+9: sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); p = NULL; break; case STAR: p = "STAR"; break; case PLUS: p = "PLUS"; break; default: regerror("corrupted opcode"); break; } if (p != NULL) (void) strcat(buf, p); return(buf); } #endif /* * The following is provided for those people who do not have strcspn() in * their C libraries. They should get off their butts and do something * about it; at least one public-domain implementation of those (highly * useful) string routines has been published on Usenet. */ #ifdef STRCSPN /* * strcspn - find length of initial segment of s1 consisting entirely * of characters not from s2 */ static int strcspn(s1, s2) char *s1; char *s2; { register char *scan1; register char *scan2; register int count; count = 0; for (scan1 = s1; *scan1 != '\0'; scan1++) { for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ if (*scan1 == *scan2++) return(count); count++; } return(count); } #endif boxes-1.2/src/regexp/regexp.h000066400000000000000000000013611306272555200162300ustar00rootroot00000000000000/* * Definitions etc. for regexp(3) routines. * * Version: $Id: regexp.h,v 1.5 1999/06/25 18:53:51 tsjensen Exp $ * * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], * not the System V one. */ #ifndef REGEXP_H #define REGEXP_H #define NSUBEXP 10 typedef struct regexp { char *startp[NSUBEXP]; char *endp[NSUBEXP]; char regstart; /* Internal use only. */ char reganch; /* Internal use only. */ char *regmust; /* Internal use only. */ int regmlen; /* Internal use only. */ char program[1]; /* Unwarranted chumminess with compiler. */ } regexp; extern regexp *regcomp(); /* extern int regexec(); */ /* extern size_t regsub(); */ extern size_t myregsub(); /* extern void regerror(); */ #endif /* REGEXP_H */ boxes-1.2/src/regexp/regmagic.h000066400000000000000000000002311306272555200165070ustar00rootroot00000000000000/* * The first byte of the regexp internal "program" is actually this magic * number; the start node begins in the second byte. */ #define MAGIC 0234 boxes-1.2/src/regexp/regsub.c000066400000000000000000000137561306272555200162330ustar00rootroot00000000000000/* * File: regsub.c * Date created: Copyright (c) 1986 by University of Toronto. * Author: Henry Spencer. * Extensions and modifications by Thomas Jensen * Language: K&R C (traditional) * Web Site: http://boxes.thomasjensen.com/ * Purpose: Perform substitutions after a regexp match * License: - Not derived from licensed software. * - Permission is granted to anyone to use this * software for any purpose on any computer system, * and to redistribute it freely, subject to the * following restrictions: * 1. The author is not responsible for the * consequences of use of this software, no matter * how awful, even if they arise from defects in it. * 2. The origin of this software must not be * misrepresented, either by explicit claim or by * omission. * 3. Altered versions must be plainly marked as such, * and must not be misrepresented as being the * original software. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "regmagic.h" char rcsid_regsub_c[] = "$Id: regsub.c,v 1.7 2006/07/23 16:15:55 tsjensen Exp $"; #ifndef CHARBITS #define UCHARAT(p) ((int)*(unsigned char *)(p)) #else #define UCHARAT(p) ((int)*(p)&CHARBITS) #endif /* - regsub - perform substitutions after a regexp match */ size_t /* RETURNS length of dest str */ regsub (prog, source, dest, dest_size) regexp *prog; char *source; char *dest; size_t dest_size; /* size of destination buffer */ { register char *src; register char *dst; register char c; register int no; register int len; size_t fill; /* current number of chars in dest */ if (prog == NULL || source == NULL || dest == NULL) { regerror("NULL parm to regsub"); return 0; } if (UCHARAT(prog->program) != MAGIC) { regerror("damaged regexp fed to regsub"); return 0; } src = source; dst = dest; fill = 0; while ((c = *src++) != '\0') { if (c == '&') no = 0; else if (c == '\\' && '0' <= *src && *src <= '9') no = *src++ - '0'; else no = -1; if (no < 0) { /* Ordinary character. */ if (c == '\\' && (*src == '\\' || *src == '&')) c = *src++; *dst++ = c; ++fill; } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { len = prog->endp[no] - prog->startp[no]; if (len < dest_size-fill) { (void) strncpy(dst, prog->startp[no], len); dst += len; fill += len; if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */ regerror("damaged match string"); return fill; } } else { (void) strncpy (dst, prog->startp[no], dest_size-fill); dest[dest_size-1] = '\0'; return dest_size-1; } } if (fill >= dest_size) { dest[dest_size-1] = '\0'; return dest_size-1; } } *dst++ = '\0'; return fill; } size_t /* RETURNS length of str in destination buffer */ myregsub (prog, orig, orig_len, repstr, dest, dest_size, mode) regexp *prog; /* pointers for matched regexp to original text */ char *orig; /* original input line */ size_t orig_len; /* length of original input line */ char *repstr; /* source buffer for replaced parts */ char *dest; /* destination buffer */ size_t dest_size; /* size of destination buffer */ char mode; /* 'g' or 'o' */ { size_t fill; /* current number of chars in dest */ char *sp, *dp; /* source rover, destination rover */ int rc; /* received return codes */ size_t rest_size; /* remaining space in dest */ size_t partlen; /* temp length of a piece handled */ fill = 0; sp = orig; dp = dest; rest_size = dest_size; do { rc = regexec (prog, sp); if (!rc) break; partlen = prog->startp[0] - sp; if (partlen < rest_size) { strncpy (dp, sp, partlen); fill += partlen; sp = prog->startp[0]; dp += partlen; rest_size -= partlen; } else { strncpy (dp, sp, rest_size); dest[dest_size-1] = '\0'; return dest_size - 1; } /* fprintf (stderr, "regsub (%p, \"%s\", \"%s\", %d);\n", */ /* prog, repstr, dp, rest_size); */ fill += regsub (prog, repstr, dp, rest_size); dp = dest + fill; sp = prog->endp[0]; rest_size = dest_size - fill; if (fill >= dest_size) { dest[dest_size-1] = '\0'; return dest_size - 1; } /* fprintf (stderr, "dest = \"%s\";\n", dest); */ if (prog->startp[0] == prog->endp[0]) break; /* match "^" or "$" only once */ } while (mode == 'g'); partlen = orig + orig_len - sp; if (partlen < rest_size) { strncpy (dp, sp, partlen); fill += partlen; dp[partlen] = '\0'; } else { strncpy (dp, sp, rest_size); dest[dest_size-1] = '\0'; fill = dest_size - 1; } return fill; } /*EOF*/ /* vim: set sw=4: */ boxes-1.2/src/remove.c000066400000000000000000001126031306272555200147360ustar00rootroot00000000000000/* * File: remove.c * Project Main: boxes.c * Date created: June 23, 1999 (Wednesday, 20:59h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Box removal, i.e. the deletion of boxes * * License: o 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. * o 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. * o 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "config.h" #include #include #include #include "shape.h" #include "boxes.h" #include "tools.h" #include "remove.h" static const char rcsid_remove_c[] = "$Id: remove.c,v 1.8 2006/07/22 19:19:26 tsjensen Exp $"; static int best_match (const line_t *line, char **ws, char **we, char **es, char **ee) /* * Find positions of west and east box parts in line. * * line line to examine * ws etc. result parameters (west start, west end, east start, east end) * * RETURNS: > 0 a match was found (ws etc are set to indicate positions) * == 0 no match was found * < 0 internal error (out of memory) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t numw = 0; /* number of shape lines on west side */ size_t nume = 0; /* number of shape lines on east side */ size_t j; /* counts number of lines of all shapes tested */ size_t k; /* line counter within shape */ int w; /* shape counter */ sentry_t *cs; /* current shape */ char *s; /* duplicate of current shape part */ char *p; /* position found by strstr */ size_t cq; /* current quality */ char *q; /* space check rover */ line_t chkline; /* for calls to empty_line() */ size_t quality; *ws = *we = *es = *ee = NULL; numw = opt.design->shape[WNW].height; numw += opt.design->shape[ W ].height; numw += opt.design->shape[WSW].height; nume = opt.design->shape[ENE].height; nume += opt.design->shape[ E ].height; nume += opt.design->shape[ESE].height; #ifdef DEBUG fprintf (stderr, "Number of WEST side shape lines: %d\n", numw); fprintf (stderr, "Number of EAST side shape lines: %d\n", nume); #endif /* * Find match for WEST side */ if (!empty_side (opt.design->shape, BLEF)) { quality = 0; cs = opt.design->shape + WNW; for (j=0,k=0,w=3; jheight) { k = 0; cs = opt.design->shape + west_side[--w]; } chkline.text = cs->chars[k]; chkline.len = cs->width; if (empty_line (&chkline) && !(quality==0 && j==numw-1)) continue; s = (char *) strdup (cs->chars[k]); if (s == NULL) { perror (PROJECT); return -1; } cq = cs->width; do { p = strstr (line->text, s); if (p) { q = p-1; while (q >= line->text) { if (*q-- != ' ') { p = NULL; break; } } if (p) break; } if (!p && cq) { if (*s == ' ') memmove (s, s+1, cq--); else if (s[cq-1] == ' ') s[--cq] = '\0'; else { cq = 0; break; } } } while (cq && !p); if (cq == 0) { BFREE (s); continue; } /* * If the current match is the best yet, adjust result values */ if (cq > quality) { quality = cq; *ws = p; *we = p + cq; } BFREE (s); } } /* * Find match for EAST side */ if (!empty_side (opt.design->shape, BRIG)) { quality = 0; cs = opt.design->shape + ENE; for (j=0,k=0,w=1; jheight) { k = 0; cs = opt.design->shape + east_side[++w]; } #ifdef DEBUG fprintf (stderr, "\nj %d, k %d, w %d, cs->chars[k] = \"%s\"\n", j, k, w, cs->chars[k]?cs->chars[k]:"(null)"); #endif chkline.text = cs->chars[k]; chkline.len = cs->width; if (empty_line (&chkline)) continue; s = (char *) strdup (cs->chars[k]); if (s == NULL) { perror (PROJECT); return -1; } cq = cs->width; do { p = my_strnrstr (line->text, s, cq, 0); if (p) { q = p + cq; while (*q) { if (*q++ != ' ') { p = NULL; break; } } if (p) break; } if (!p && cq) { if (*s == ' ') memmove (s, s+1, cq--); else if (s[cq-1] == ' ') s[--cq] = '\0'; else { cq = 0; break; } } } while (cq && !p); if (cq == 0) { BFREE (s); continue; } /* * If the current match is the best yet, adjust result values */ if (cq > quality) { quality = cq; *es = p; *ee = p + cq; } BFREE (s); } } return *ws || *es ? 1:0; } static int hmm (const int aside, const size_t follow, const char *p, const char *ecs, const int cnt) /* * (horizontal middle match) * * aside box part to check (BTOP or BBOT) * follow index of line number in shape spec to check * p current check position * ecs pointer to first char of east corner shape * cnt current shape to check (0 == leftmost middle shape) * * Recursive helper function for detect_horiz(), uses backtracking * * RETURNS: == 0 success * != 0 error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int cmp; sentry_t *cs; shape_t sh; int rc; #ifdef DEBUG fprintf (stderr, "hmm (%s, %d, \'%c\', \'%c\', %d)\n", aside==BTOP?"BTOP":"BBOT", follow, p[0], *ecs, cnt); #endif if (p > ecs) /* last shape tried was too long */ return 2; sh = leftmost (aside, cnt); if (sh == ANZ_SHAPES) return 1; cs = opt.design->shape + sh; cmp = strncmp (p, cs->chars[follow], cs->width); if (cmp == 0) { if (p+cs->width == ecs) { if (leftmost (aside, cnt+1) == ANZ_SHAPES) return 0; /* good! all clear, it matched */ else return 3; /* didn't use all shapes to do it */ } if (cs->elastic) { rc = hmm (aside, follow, p+cs->width, ecs, cnt); #ifdef DEBUG fprintf (stderr, "hmm returned %d\n", rc); #endif if (rc) { rc = hmm (aside, follow, p+cs->width, ecs, cnt+1); #ifdef DEBUG fprintf (stderr, "hmm returned %d\n", rc); #endif } } else { rc = hmm (aside, follow, p+cs->width, ecs, cnt+1); #ifdef DEBUG fprintf (stderr, "hmm returned %d\n", rc); #endif } if (rc == 0) return 0; /* we're on the way back */ else return 4; /* can't continue on this path */ } else { return 5; /* no match */ } } static int detect_horiz (const int aside, size_t *hstart, size_t *hend) /* * Detect which part of the input belongs to the top/bottom of the box * * aside part of box to detect (BTOP or BBOT) * hstart index of first line of detected box part (result) * hend index of first line following detected box part (result) * * We assume the horizontal parts of the box to be in one piece, i.e. no * blank lines inserted. Lines may be missing, though. Lines may not be * duplicated. They may be shifted left and right by inserting whitespace, * but whitespace which is part of the box must not have been deleted * (unless it's because an entire box side is empty). Box part lines may * even differ in length as long as each line is in itself a valid * horizontal box line. * * RETURNS: == 0 success (hstart & hend are set) * != 0 error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t follow; /* possible box line */ sentry_t *cs; /* current shape */ line_t *line; /* currently processed input line */ size_t lcnt; /* line counter */ char *p = NULL; /* middle line part scanner */ char *q; /* space check rover */ char *wcs = NULL; /* west corner shape position */ char *ecs = NULL; /* east corner shape position */ int mmok = 0; /* true if middle match was ok */ size_t mheight; /* regular height of box part */ int result_init = 0; /* true if hstart etc. was init. */ int nowside; /* true if west side is empty */ int goeast; /* no. of finds to ignore on right */ int gowest; /* set to request search start incr. */ *hstart = *hend = 0; nowside = empty_side (opt.design->shape, BLEF); mheight = opt.design->shape[sides[aside][0]].height; if (aside == BTOP) { follow = 0; line=input.lines; } else { follow = mheight - 1; line = input.lines + input.anz_lines - 1; } for (lcnt=0; lcnt= input.lines; ++lcnt) { goeast = gowest = 0; #ifdef DEBUG fprintf (stderr, "----- Processing line index %2d ----------" "-------------------------------------\n", aside == BTOP? lcnt: input.anz_lines - lcnt - 1); #endif do { /* * Look for west corner shape */ if (!goeast) { if (nowside) { wcs = NULL; if (gowest) { gowest = 0; if (*p == ' ' || *p == '\t') ++p; else break; } else { p = line->text; } } else { cs = opt.design->shape + sides[aside][aside==BTOP?0:SHAPES_PER_SIDE-1]; if (gowest) { gowest = 0; wcs = strstr (wcs+1, cs->chars[follow]); } else { wcs = strstr (line->text, cs->chars[follow]); } if (wcs) { for (q=wcs-1; q>=line->text; --q) { if (*q != ' ' && *q != '\t') break; } if (q >= line->text) wcs = NULL; } if (!wcs) break; p = wcs + cs->width; } } /* Now, wcs is either NULL (if west side is empty) */ /* or not NULL (if west side is not empty). In any case, p */ /* points to where we start searching for the east corner. */ #ifdef DEBUG if (wcs) fprintf (stderr, "West corner shape matched at " "position %d.\n", wcs - line->text); else fprintf (stderr, "West box side is empty.\n"); #endif /* * Look for east corner shape */ cs = opt.design->shape + sides[aside][aside==BTOP?SHAPES_PER_SIDE-1:0]; ecs = my_strnrstr (p, cs->chars[follow], cs->width, goeast); if (ecs) { for (q=ecs+cs->width; *q; ++q) { if (*q != ' ' && *q != '\t') break; } if (*q) ecs = NULL; } if (!ecs) { if (goeast == 0) break; else { goeast = 0; gowest = 1; continue; } } #ifdef DEBUG fprintf (stderr, "East corner shape matched at position %d.\n", ecs-line->text); #endif /* * Check if text between corner shapes is valid */ mmok = !hmm (aside, follow, p, ecs, 0); if (!mmok) ++goeast; #ifdef DEBUG fprintf (stderr, "Text between corner shapes is %s.\n", mmok? "VALID": "NOT valid"); #endif } while (!mmok); /* * Proceed to next line */ if (mmok) { /* match found */ if (!result_init) { result_init = 1; if (aside == BTOP) *hstart = lcnt; else *hend = (input.anz_lines - lcnt - 1) + 1; } if (aside == BTOP) *hend = lcnt + 1; else *hstart = input.anz_lines - lcnt - 1; } else { if (result_init) break; } wcs = NULL; ecs = NULL; p = NULL; mmok = 0; if (aside == BTOP) { ++follow; ++line; } else { --follow; --line; } } return result_init? 0: 1; } static design_t *detect_design() /* * Autodetect design used by box in input. * * This requires knowledge about ALL designs, so the entire config file had * to be parsed at some earlier time. * * RETURNS: != NULL success, pointer to detected design * == NULL on error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { design_t *d = designs; /* ptr to currently tested design */ long hits; /* hit points of the current design */ long maxhits = 0; /* maximum no. of hits so far */ design_t *res = NULL; /* ptr to design with the most hits */ int dcnt; /* design loop counter */ shape_t scnt; /* shape loop counter */ size_t j, k; char *p; char *s; line_t shpln; /* a line which is part of a shape */ size_t a; int empty[ANZ_SIDES]; for (dcnt=0; dcntname); #endif hits = 0; for (j=0; jshape, j); #ifdef DEBUG fprintf (stderr, "Empty sides: TOP %d, LEFT %d, BOTTOM %d, RIGHT %d\n", empty[BTOP], empty[BLEF], empty[BBOT], empty[BRIG]); #endif for (scnt=0; scntshape[scnt].height; ++j) { shpln.text = d->shape[scnt].chars[j]; shpln.len = d->shape[scnt].width; if (empty_line (&shpln)) continue; for (s=shpln.text; *s==' ' || *s=='\t'; ++s); for (k=0; kshape[scnt].height; ++k) { a = k; if (scnt == SW) a += input.anz_lines - d->shape[scnt].height; if (a >= input.anz_lines) break; for (p=input.lines[a].text; *p==' '||*p=='\t'; ++p); if (strncmp (p, s, shpln.len-(s-shpln.text)) == 0) ++hits; } } #ifdef DEBUG fprintf (stderr, "After %s corner check:\t%ld hits.\n", shape_name[scnt], hits); #endif break; case NE: case SE: /* * Try and find east corner shapes. Every non-empty shape * line is searched for on every input line. A hit is * generated whenever a match is found. */ if (empty[BRIG] || (empty[BTOP] && scnt == NE) || (empty[BBOT] && scnt == SE)) break; for (j=0; jshape[scnt].height; ++j) { shpln.text = d->shape[scnt].chars[j]; shpln.len = d->shape[scnt].width; if (empty_line (&shpln)) continue; for (s = shpln.text + shpln.len -1; (*s==' ' || *s=='\t') && shpln.len; --s, --(shpln.len)); for (k=0; kshape[scnt].height; ++k) { a = k; if (scnt == SE) a += input.anz_lines - d->shape[scnt].height; if (a >= input.anz_lines) break; for (p=input.lines[a].text + input.lines[a].len -1; p>=input.lines[a].text && (*p==' ' || *p=='\t'); --p); p = p - shpln.len + 1; if (p < input.lines[a].text) continue; if (strncmp (p, shpln.text, shpln.len) == 0) ++hits; } } #ifdef DEBUG fprintf (stderr, "After %s corner check:\t%ld hits.\n", shape_name[scnt], hits); #endif break; default: if (isempty (d->shape+scnt)) continue; if ((scnt >= NNW && scnt <= NNE) || (scnt >= SSE && scnt <= SSW)) { /* * Try and find horizontal shapes between the box * corners. Every non-empty shape line is searched for * on every input line. Elastic shapes must occur * twice in an uninterrupted row to generate a hit. */ if ((scnt >= NNW && scnt <= NNE && empty[BTOP]) || (scnt >= SSE && scnt <= SSW && empty[BBOT])) { ++hits; break; /* horizontal box part is empty */ } for (j=0; jshape[scnt].height; ++j) { shpln.text = d->shape[scnt].chars[j]; shpln.len = d->shape[scnt].width; if (empty_line (&shpln)) continue; for (k=0; kshape[scnt].height; ++k) { a = k; if (scnt >= SSE && scnt <= SSW) a += input.anz_lines-d->shape[scnt].height; if (a >= input.anz_lines) break; for (p=input.lines[a].text; *p == ' ' || *p == '\t'; ++p); p += d->shape[NW].width; if (p-input.lines[a].text >= (long) input.lines[a].len) continue; p = strstr (p, shpln.text); if (p) { if (d->shape[scnt].elastic) { p += shpln.len; if (p-input.lines[a].text >= (long) input.lines[a].len) continue; if (!strncmp (p, shpln.text, shpln.len)) ++hits; } else { ++hits; } } } } } else if ((scnt >= ENE && scnt <= ESE) || (scnt >= WSW && scnt <= WNW)) { /* handle later */ break; } else { fprintf (stderr, "%s: internal error\n", PROJECT); return NULL; } #ifdef DEBUG fprintf (stderr, "After %s shape check:\t%ld hits.\n", shape_name[scnt], hits); #endif } } /* * Now iterate over all input lines except for potential top and * bottom box parts. Check if east and west line ends match a * non-empty shape line. If so, generate a hit. */ if (((empty[BTOP]? 0: d->shape[NW].height) + (empty[BBOT]? 0: d->shape[SW].height)) < input.anz_lines) { for (k = empty[BTOP]? 0: d->shape[NW].height; k < input.anz_lines -(empty[BBOT]? 0: d->shape[SW].height); ++k) { for (p=input.lines[k].text; *p==' ' || *p=='\t'; ++p); for (scnt=WSW; scnt<=WNW; ++scnt) { a = 0; if (isempty (d->shape + scnt)) continue; for (j=0; jshape[scnt].height; ++j) { shpln.text = d->shape[scnt].chars[j]; shpln.len = d->shape[scnt].width; if (empty_line (&shpln)) continue; for (s=shpln.text; *s==' ' || *s=='\t'; ++s); if (strncmp (p, s, shpln.len-(s-shpln.text)) == 0) { ++hits; a = 1; break; } } if (a) break; } for (scnt=ENE; scnt<=ESE; ++scnt) { a = 0; if (isempty (d->shape + scnt)) continue; for (j=0; jshape[scnt].height; ++j) { shpln.text = d->shape[scnt].chars[j]; shpln.len = d->shape[scnt].width; if (empty_line (&shpln)) continue; for (p=input.lines[k].text + input.lines[k].len -1; p>=input.lines[a].text && (*p==' ' || *p=='\t'); --p); for (s = shpln.text + shpln.len -1; (*s==' ' || *s=='\t') && shpln.len; --s, --(shpln.len)); p = p - shpln.len + 1; if (strncmp (p, shpln.text, shpln.len) == 0) { ++hits; a = 1; break; } } if (a) break; } } } #ifdef DEBUG fprintf (stderr, "After side checks:\t%ld hits.\n", hits); #endif if (hits > maxhits) { maxhits = hits; res = d; } } #ifdef DEBUG if (res) fprintf (stderr, "CHOOSING \"%s\" design (%ld hits).\n", res->name, maxhits); else fprintf (stderr, "NO DESIGN FOUND WITH EVEN ONE HIT!\n"); #endif return res; } int remove_box() /* * Remove box from input. * * RETURNS: == 0 success * != 0 error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t textstart = 0; /* index of 1st line of box body */ size_t textend = 0; /* index of 1st line of south side */ size_t boxstart = 0; /* index of 1st line of box */ size_t boxend = 0; /* index of 1st line trailing the box */ int m; /* true if a match was found */ size_t j; /* loop counter */ int did_something = 0; /* true if there was something to remove */ /* * If the user didn't specify a design to remove, autodetect it. * Since this requires knowledge of all available designs, the entire * config file had to be parsed (earlier). */ if (opt.design_choice_by_user == 0) { design_t *tmp = detect_design(); if (tmp) { opt.design = tmp; #ifdef DEBUG fprintf (stderr, "Design autodetection: Removing box of " "design \"%s\".\n", opt.design->name); #endif } else { fprintf (stderr, "%s: Box design autodetection failed. Use -d " "option.\n", PROJECT); return 1; } } /* * Make all lines the same length by adding trailing spaces (needed * for recognition). * Also append a number of spaces to ALL input lines. A greater number * takes more space and time, but enables the correct removal of boxes * whose east sides consist of lots of spaces (the given value). So we * add a number of spaces equal to the east side width. */ input.maxline += opt.design->shape[NE].width; for (j=0; jshape, BTOP)) { #ifdef DEBUG fprintf (stderr, "----> Top box side is empty: boxstart == textstart == 0.\n"); #endif } else { detect_horiz (BTOP, &boxstart, &textstart); #ifdef DEBUG fprintf (stderr, "----> First line of box is %d, ", boxstart); fprintf (stderr, "first line of box body (text) is %d.\n", textstart); #endif } /* * Phase 2: Find out how many lines belong to the bottom of the box */ if (empty_side (opt.design->shape, BBOT)) { textend = input.anz_lines; boxend = input.anz_lines; #ifdef DEBUG fprintf (stderr, "----> Bottom box side is empty: boxend == textend == %d.\n", input.anz_lines); #endif } else { textend = 0; boxend = 0; detect_horiz (BBOT, &textend, &boxend); if (textend == 0 && boxend == 0) { textend = input.anz_lines; boxend = input.anz_lines; } #ifdef DEBUG fprintf (stderr, "----> Last line of box body (text) is %d, ", textend-1); fprintf (stderr, "last line of box is %d.\n", boxend-1); #endif } /* * Phase 3: Iterate over body lines, removing box sides where applicable */ for (j=textstart; jshape[NW].width + opt.design->padding[BLEF]; for (c=0; c textstart) { #ifdef DEBUG fprintf (stderr, "Killing trailing blank line in box body.\n"); #endif --textend; } } if (textstart > boxstart) { for (j=boxstart; j textend) { for (j=textend; j input.maxline) input.maxline = input.lines[j].len; } memset (input.lines + input.anz_lines, 0, (BMAX (textstart - boxstart, 0) + BMAX (boxend - textend, 0)) * sizeof(line_t)); #ifdef DEBUG #if 0 for (j=0; j * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Box removal, i.e. the deletion of boxes * * License: o 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. * o 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. * o 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 REMOVE_H #define REMOVE_H int remove_box(); void output_input(); #endif /*REMOVE_H*/ /*EOF*/ /* vim: set cindent sw=4: */ boxes-1.2/src/shape.c000066400000000000000000000222531306272555200145420ustar00rootroot00000000000000/* * File: shape.c * Project Main: boxes.c * Date created: June 23, 1999 (Wednesday, 13:39h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Shape handling and information functions * * License: o 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. * o 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. * o 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "config.h" #include #include #include #include #include "shape.h" #include "boxes.h" #include "tools.h" static const char rcsid_shape_c[] = "$Id: shape.c,v 1.6 2006/07/12 05:27:29 tsjensen Exp $"; char *shape_name[] = { "NW", "NNW", "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW" }; shape_t north_side[SHAPES_PER_SIDE] = { NW, NNW, N, NNE, NE }; /* clockwise */ shape_t east_side[SHAPES_PER_SIDE] = { NE, ENE, E, ESE, SE }; shape_t south_side[SHAPES_PER_SIDE] = { SE, SSE, S, SSW, SW }; shape_t west_side[SHAPES_PER_SIDE] = { SW, WSW, W, WNW, NW }; shape_t corners[ANZ_CORNERS] = { NW, NE, SE, SW }; shape_t *sides[] = { north_side, east_side, south_side, west_side }; shape_t findshape (const sentry_t *sarr, const int num) /* * Find a non-empty shape and return its name * * sarr the shape array to check * num number of entries in sarr to be checked * * RETURNS: a shape_name on success * num on error (e.g. empty shape array) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int i; for (i=0; i LINE_MAX) { fprintf (stderr, "%s: internal error\n", PROJECT); return 1; } *chars = (char **) calloc (height, sizeof(char *)); if (*chars == NULL) { perror (PROJECT); return 2; } for (j=0; j0; --j) BFREE ((*chars)[j-1]); BFREE (*chars); return 3; } memset ((*chars)[j], ' ', width); } return 0; } void freeshape (sentry_t *shape) /* * Free all memory allocated by the shape and set the struct to * SENTRY_INITIALIZER. Do not free memory of the struct. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t j; for (j=0; jheight; ++j) BFREE (shape->chars[j]); BFREE (shape->chars); *shape = SENTRY_INITIALIZER; } int isempty (const sentry_t *shape) /* * Return true if shape is empty. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { if (shape == NULL) return 1; else if (shape->chars == NULL) return 1; else if (shape->width == 0 || shape->height == 0) return 1; else return 0; } int isdeepempty (const sentry_t *shape) /* * Return true if shape is empty, also checking if lines consist of spaces * only. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t j; if (isempty (shape)) return 1; for (j=0; jheight; ++j) { if (shape->chars[j]) { if (strspn (shape->chars[j], " ") != shape->width) return 0; } } return 1; } size_t highest (const sentry_t *sarr, const int n, ...) /* * Return height (vert.) of highest shape in given list. * * sarr array of shapes to examine * n number of shapes following * ... the shapes to consider * * RETURNS: height in lines (may be zero) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { va_list ap; int i; size_t max = 0; /* current maximum height */ #if defined(DEBUG) && 0 fprintf (stderr, "highest (%d, ...)\n", n); #endif va_start (ap, n); for (i=0; i max) max = sarr[r].height; } } va_end (ap); return max; } size_t widest (const sentry_t *sarr, const int n, ...) /* * Return width (horiz.) of widest shape in given list. * * sarr array of shapes to examine * n number of shapes following * ... the shapes to consider * * RETURNS: width in chars (may be zero) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { va_list ap; int i; size_t max = 0; /* current maximum width */ #if defined(DEBUG) && 0 fprintf (stderr, "widest (%d, ...)\n", n); #endif va_start (ap, n); for (i=0; i max) max = sarr[r].width; } } va_end (ap); return max; } shape_t leftmost (const int aside, const int cnt) /* * Return leftmost existing shape in specification for side aside * (BTOP or BBOT), skipping cnt shapes. Corners are not considered. * * RETURNS: shape if shape was found * ANZ_SHAPES on error (e.g. cnt too high) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int c = 0; int s; if (cnt < 0) return ANZ_SHAPES; if (aside == BTOP) { s = 0; do { ++s; while (s < SHAPES_PER_SIDE-1 && isempty(opt.design->shape + north_side[s])) ++s; if (s == SHAPES_PER_SIDE-1) return ANZ_SHAPES; } while (c++ < cnt); return north_side[s]; } else if (aside == BBOT) { s = SHAPES_PER_SIDE - 1; do { --s; while (s && isempty(opt.design->shape + south_side[s])) --s; if (!s) return ANZ_SHAPES; } while (c++ < cnt); return south_side[s]; } return ANZ_SHAPES; } int empty_side (sentry_t *sarr, const int aside) /* * Return true if the shapes on the given side consist entirely out of * spaces - and spaces only, tabs are considered non-empty. * * sarr pointer to shape list of design to check * aside the box side (one of BTOP etc.) * * RETURNS: == 0 side is not empty * != 0 side is empty * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int i; for (i=0; i * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Shape handling and information functions * * License: o 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. * o 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. * o 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 SHAPE_H #define SHAPE_H typedef enum { NW, NNW, N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW } shape_t; extern char *shape_name[]; #define ANZ_SHAPES 16 #define SHAPES_PER_SIDE 5 #define ANZ_SIDES 4 #define ANZ_CORNERS 4 extern shape_t north_side[SHAPES_PER_SIDE]; /* groups of shapes, clockwise */ extern shape_t east_side[SHAPES_PER_SIDE]; extern shape_t south_side[SHAPES_PER_SIDE]; extern shape_t west_side[SHAPES_PER_SIDE]; extern shape_t corners[ANZ_CORNERS]; extern shape_t *sides[ANZ_SIDES]; typedef struct { char **chars; size_t height; size_t width; int elastic; /* elastic is used only in orginial definition */ } sentry_t; #define SENTRY_INITIALIZER (sentry_t) {NULL, 0, 0, 0} int genshape (const size_t width, const size_t height, char ***chars); void freeshape (sentry_t *shape); shape_t findshape (const sentry_t *sarr, const int num); int on_side (const shape_t s, const int idx); int isempty (const sentry_t *shape); int isdeepempty (const sentry_t *shape); size_t highest (const sentry_t *sarr, const int n, ...); size_t widest (const sentry_t *sarr, const int n, ...); shape_t leftmost (const int aside, const int cnt); int empty_side (sentry_t *sarr, const int aside); #endif /*SHAPE_H*/ /*EOF*/ /* vim: set cindent sw=4: */ boxes-1.2/src/tools.c000066400000000000000000000255321306272555200146050ustar00rootroot00000000000000/* * File: tools.c * Project Main: boxes.c * Date created: June 20, 1999 (Sunday, 16:51h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Provide tool functions for error reporting and some * string handling * * License: o 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. * o 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. * o 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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "config.h" #include #include #include #include #include "shape.h" #include "boxes.h" #include "tools.h" static const char rcsid_tools_c[] = "$Id: tools.c,v 1.7 2006/07/22 19:27:15 tsjensen Exp $"; int yyerror (const char *fmt, ...) /* * Print configuration file parser errors. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { va_list ap; va_start (ap, fmt); fprintf (stderr, "%s: %s: line %d: ", PROJECT, yyfilename? yyfilename: "(null)", tjlineno); vfprintf (stderr, fmt, ap); fputc ('\n', stderr); va_end (ap); return 0; } void regerror (char *msg) /* * Print regular expression andling error messages * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { fprintf (stderr, "%s: %s: line %d: %s\n", PROJECT, yyfilename? yyfilename: "(null)", opt.design->current_rule? opt.design->current_rule->line: 0, msg); errno = EINVAL; } int strisyes (const char *s) /* * Determine if the string s has a contents indicating "yes". * * s string to examine * * RETURNS: == 0 string does NOT indicate yes (including errors) * != 0 string indicates yes * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { if (s == NULL) return 0; if (!strncasecmp ("on", s, 3)) return 1; else if (!strncasecmp ("yes", s, 4)) return 1; else if (!strncasecmp ("true", s, 5)) return 1; else if (!strncmp ("1", s, 2)) return 1; else if (!strncasecmp ("t", s, 2)) return 1; else return 0; } int strisno (const char *s) /* * Determine if the string s has a contents indicating "no". * * s string to examine * * RETURNS: == 0 string does NOT indicate no (including errors) * != 0 string indicates no * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { if (s == NULL) return 0; if (!strncasecmp ("off", s, 4)) return 1; else if (!strncasecmp ("no", s, 3)) return 1; else if (!strncasecmp ("false", s, 6)) return 1; else if (!strncmp ("0", s, 2)) return 1; else if (!strncasecmp ("f", s, 2)) return 1; else return 0; } void concat_strings (char *dst, int max_len, int count, ...) /* * Concatenate a variable number of strings into a fixed-length buffer. * * dst Destination array * max_len Maximum resulting string length (including terminating NULL). * count Number of source strings. * * The concatenation process terminates when either the destination * buffer is full or all 'count' strings are processed. Null string * pointers are treated as empty strings. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { va_list va; const char *src; va_start (va, count); /* * Sanity check. */ if (max_len < 1) return; if (max_len == 1 || count < 1) { *dst = '\0'; return; } /* * Loop over all input strings. */ while (count-->0 && max_len > 1) { /* * Grab an input string pointer. If it's NULL, skip it (eg. treat * it as empty. */ src = va_arg (va, const char *); if (src == NULL) continue; /* * Concatenate 'src' onto 'dst', as long as we have room. */ while (*src && max_len > 1) { *dst++ = *src++; max_len--; } } va_end (va); /* * Terminate the string with an ASCII NUL. */ *dst = '\0'; } int empty_line (const line_t *line) /* * Return true if line is empty. * * Empty lines either consist entirely of whitespace or don't exist. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { char *p; size_t j; if (!line) return 1; if (line->text == NULL || line->len <= 0) return 1; for (p=line->text, j=0; *p && jlen; ++j, ++p) { if (*p != ' ' && *p != '\t' && *p != '\r') return 0; } return 1; } size_t expand_tabs_into (const char *input_buffer, const size_t in_len, const int tabstop, char **text, size_t **tabpos, size_t *tabpos_len) /* * Expand tab chars in input_buffer and store result in text. * * input_buffer Line of text with tab chars * in_len length of the string in input_buffer * tabstop tab stop distance * text address of the pointer that will take the result * tabpos array of ints giving the positions of the first * space of an expanded tab in the text result buffer * tabpos_len number of tabs recorded in tabpos * * Memory will be allocated for text and tabpos. * Should only be called for lines of length > 0; * * RETURNS: Success: Length of the result line in characters (> 0) * Error: 0 (e.g. out of memory) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { static char temp [LINE_MAX*MAX_TABSTOP+1]; /* work string */ size_t ii; /* position in input string */ size_t io; /* position in work string */ size_t jp; /* tab expansion jump point */ size_t tabnum; /* number of tabs in input */ *text = NULL; for (ii=0, *tabpos_len=0; ii 0) { *tabpos = (size_t *) calloc ((*tabpos_len) + 1, sizeof(size_t)); if (*tabpos == NULL) { return 0; /* out of memory */ } } for (ii=0, io=0, tabnum=0; ii < in_len && ((int) io) < (LINE_MAX*tabstop-1); ++ii) { if (input_buffer[ii] == '\t') { if (*tabpos_len > 0) { (*tabpos)[tabnum++] = io; } for (jp=io+tabstop-(io%tabstop); io= 0 && (text[idx] == '\n' || text[idx] == '\r' || text[idx] == '\t' || text[idx] == ' ')) { text[idx--] = '\0'; } *len = idx + 1; } char *my_strnrstr (const char *s1, const char *s2, const size_t s2_len, int skip) /* * Return pointer to last occurrence of string s2 in string s1. * * s1 string to search * s2 string to search for in s1 * s2_len length in characters of s2 * skip number of finds to ignore before returning anything * * RETURNS: pointer to last occurrence of string s2 in string s1 * NULL if not found or error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { char *p; int comp; if (!s2 || *s2 == '\0') return (char *) s1; if (!s1 || *s1 == '\0') return NULL; if (skip < 0) skip = 0; p = strrchr (s1, s2[0]); if (!p) return NULL; while (p >= s1) { comp = strncmp (p, s2, s2_len); if (comp == 0) { if (skip--) --p; else return p; } else { --p; } } return NULL; } char *tabbify_indent (const size_t lineno, char *indentspc, const size_t indentspc_len) /* * Checks if tab expansion mode is "keep", and if so, calculates a new * indentation string based on the one given. The new string contains * tabs in their original positions. * * lineno index of the input line we are referring to * indentspc previously calculated "space-only" indentation string * (may be NULL). This is only used when opt.tabexp != 'k', * in which case it will be used as the function result. * indentspc_len desired result length, measured in spaces only * * RETURNS: if successful and opt.tabexp == 'k': new string * on error (invalid input or out of memory): NULL * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t i; char *result; size_t result_len; if (opt.tabexp != 'k') { return indentspc; } if (lineno >= input.anz_lines) { return NULL; } if (indentspc_len == 0) { return (char *) strdup (""); } result = (char *) malloc (indentspc_len + 1); if (result == NULL) { perror (PROJECT); return NULL; } memset (result, (int)' ', indentspc_len); result[indentspc_len] = '\0'; result_len = indentspc_len; for (i=0; i < input.lines[lineno].tabpos_len && input.lines[lineno].tabpos[i] < indentspc_len; ++i) { size_t tpos = input.lines[lineno].tabpos[i]; size_t nspc = opt.tabstop - (tpos % opt.tabstop); /* no of spcs covered by tab */ if (tpos + nspc > input.indent) { break; } result[tpos] = '\t'; result_len -= nspc - 1; result[result_len] = '\0'; } return result; } /*EOF*/ /* vim: set sw=4: */ boxes-1.2/src/tools.h000066400000000000000000000044551306272555200146130ustar00rootroot00000000000000/* * File: tools.h * Project Main: boxes.c * Date created: June 20, 1999 (Sunday, 16:57h) * Author: Copyright (C) 1999 Thomas Jensen * Language: ANSI C * Web Site: http://boxes.thomasjensen.com/ * Purpose: Tool functions for error reporting and some string * handling and other needful things * * License: o 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. * o 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. * o 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 TOOLS_H #define TOOLS_H #define BMAX(a,b) ((a)>(b)? (a):(b)) /* return the larger value */ #define BFREE(p) { /* free memory and clear pointer */ \ if (p) { \ free (p); \ (p) = NULL; \ } \ } int yyerror (const char *fmt, ...); void regerror (char *msg); int empty_line (const line_t *line); size_t expand_tabs_into (const char *input_buffer, const size_t in_len, const int tabstop, char **text, size_t **tabpos, size_t *tabpos_len); void btrim (char *text, size_t *len); char* my_strnrstr (const char *s1, const char *s2, const size_t s2_len, int skip); int strisyes (const char *s); int strisno (const char *s); void concat_strings (char *dst, int max_len, int count, ...); char *tabbify_indent (const size_t lineno, char *indentspc, const size_t indentspc_len); #endif /*EOF*/ /* vim: set cindent sw=4: */ boxes-1.2/test/000077500000000000000000000000001306272555200134625ustar00rootroot00000000000000boxes-1.2/test/001_trivial.txt000066400000000000000000000001141306272555200162510ustar00rootroot00000000000000:ARGS :INPUT foo :OUTPUT-FILTER :EXPECTED /*******/ /* foo */ /*******/ :EOFboxes-1.2/test/002_trivial_10x5.txt000066400000000000000000000001551306272555200170340ustar00rootroot00000000000000:ARGS -s 10x5 :INPUT foo :OUTPUT-FILTER :EXPECTED /********/ /* foo */ /* */ /* */ /********/ :EOFboxes-1.2/test/003_no_config_file.txt000066400000000000000000000001741306272555200175470ustar00rootroot00000000000000:ARGS -f nonexistent :INPUT :OUTPUT-FILTER :EXPECTED-ERROR 1 boxes: Couldn't open config file 'nonexistent' for input. :EOF boxes-1.2/test/004_missing_option_argument.txt000066400000000000000000000003231306272555200215470ustar00rootroot00000000000000:ARGS -s :INPUT :OUTPUT-FILTER 1s/^.\+: /boxes: / 1s/-- s$/-- 's'/ :EXPECTED-ERROR 1 boxes: option requires an argument -- 's' Usage: boxes [options] [infile [outfile]] Try `boxes -h' for more information. :EOF boxes-1.2/test/005_alignment_single_line_hlvt.txt000066400000000000000000000002161306272555200221710ustar00rootroot00000000000000:ARGS -s 15x5 -a hlvt :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* foo */ /* */ /* */ /*************/ :EOFboxes-1.2/test/006_alignment_single_line_hlvc.txt000066400000000000000000000002161306272555200221510ustar00rootroot00000000000000:ARGS -s 15x5 -a hlvc :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* foo */ /* */ /*************/ :EOFboxes-1.2/test/007_alignment_single_line_hlvb.txt000066400000000000000000000002161306272555200221510ustar00rootroot00000000000000:ARGS -s 15x5 -a hlvb :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* foo */ /*************/ :EOFboxes-1.2/test/008_alignment_single_line_hcvt.txt000066400000000000000000000002161306272555200221630ustar00rootroot00000000000000:ARGS -s 15x5 -a hcvt :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* foo */ /* */ /* */ /*************/ :EOFboxes-1.2/test/009_alignment_single_line_hcvc.txt000066400000000000000000000002161306272555200221430ustar00rootroot00000000000000:ARGS -s 15x5 -a hcvc :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* foo */ /* */ /*************/ :EOFboxes-1.2/test/010_alignment_single_line_hcvb.txt000066400000000000000000000002161306272555200221320ustar00rootroot00000000000000:ARGS -s 15x5 -a hcvb :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* foo */ /*************/ :EOFboxes-1.2/test/011_alignment_single_line_hrvt.txt000066400000000000000000000002161306272555200221740ustar00rootroot00000000000000:ARGS -s 15x5 -a hrvt :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* foo */ /* */ /* */ /*************/ :EOFboxes-1.2/test/012_alignment_single_line_hrvc.txt000066400000000000000000000002161306272555200221540ustar00rootroot00000000000000:ARGS -s 15x5 -a hrvc :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* foo */ /* */ /*************/ :EOFboxes-1.2/test/013_alignment_single_line_hrvb.txt000066400000000000000000000002161306272555200221540ustar00rootroot00000000000000:ARGS -s 15x5 -a hrvb :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* foo */ /*************/ :EOFboxes-1.2/test/014_alignment_single_line_l.txt000066400000000000000000000002131306272555200214440ustar00rootroot00000000000000:ARGS -s 15x5 -a l :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* foo */ /* */ /*************/ :EOFboxes-1.2/test/015_alignment_single_line_c.txt000066400000000000000000000002131306272555200214340ustar00rootroot00000000000000:ARGS -s 15x5 -a c :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* foo */ /* */ /*************/ :EOFboxes-1.2/test/016_alignment_single_line_r.txt000066400000000000000000000002131306272555200214540ustar00rootroot00000000000000:ARGS -s 15x5 -a r :INPUT foo :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* foo */ /* */ /*************/ :EOFboxes-1.2/test/017_alignment_multiline_hlvtjl.txt000066400000000000000000000002731306272555200222370ustar00rootroot00000000000000:ARGS -s 15x7 -a hlvtjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/018_alignment_multiline_hlvtjc.txt000066400000000000000000000003741306272555200222310ustar00rootroot00000000000000The row of 'b's shows how position is rounded down if necessary. :ARGS -s 15x7 -a hlvtjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/019_alignment_multiline_hlvtjr.txt000066400000000000000000000002731306272555200222470ustar00rootroot00000000000000:ARGS -s 15x7 -a hlvtjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/020_alignment_multiline_hlvcjl.txt000066400000000000000000000002731306272555200222100ustar00rootroot00000000000000:ARGS -s 15x7 -a hlvcjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/021_alignment_multiline_hlvcjc.txt000066400000000000000000000002731306272555200222000ustar00rootroot00000000000000:ARGS -s 15x7 -a hlvcjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/022_alignment_multiline_hlvcjr.txt000066400000000000000000000002731306272555200222200ustar00rootroot00000000000000:ARGS -s 15x7 -a hlvcjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/023_alignment_multiline_hlvbjl.txt000066400000000000000000000002731306272555200222120ustar00rootroot00000000000000:ARGS -s 15x7 -a hlvbjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/024_alignment_multiline_hlvbjc.txt000066400000000000000000000002731306272555200222020ustar00rootroot00000000000000:ARGS -s 15x7 -a hlvbjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/025_alignment_multiline_hlvbjr.txt000066400000000000000000000002731306272555200222220ustar00rootroot00000000000000:ARGS -s 15x7 -a hlvbjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/026_alignment_multiline_hcvtjl.txt000066400000000000000000000002731306272555200222260ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvtjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/027_alignment_multiline_hcvtjc.txt000066400000000000000000000002731306272555200222160ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvtjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/028_alignment_multiline_hcvtjr.txt000066400000000000000000000002731306272555200222360ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvtjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/029_alignment_multiline_hcvcjl.txt000066400000000000000000000002731306272555200222100ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvcjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/030_alignment_multiline_hcvcjc.txt000066400000000000000000000002731306272555200221670ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvcjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/031_alignment_multiline_hcvcjr.txt000066400000000000000000000002731306272555200222070ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvcjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/032_alignment_multiline_hcvbjl.txt000066400000000000000000000002731306272555200222010ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvbjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/033_alignment_multiline_hcvbjc.txt000066400000000000000000000002731306272555200221710ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvbjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/034_alignment_multiline_hcvbjr.txt000066400000000000000000000002731306272555200222110ustar00rootroot00000000000000:ARGS -s 15x7 -a hcvbjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/035_alignment_multiline_hrvtjl.txt000066400000000000000000000002731306272555200222450ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvtjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/036_alignment_multiline_hrvtjc.txt000066400000000000000000000002731306272555200222350ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvtjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/037_alignment_multiline_hrvtjr.txt000066400000000000000000000002731306272555200222550ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvtjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/038_alignment_multiline_hrvcjl.txt000066400000000000000000000002731306272555200222270ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvcjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/039_alignment_multiline_hrvcjc.txt000066400000000000000000000002731306272555200222170ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvcjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/040_alignment_multiline_hrvcjr.txt000066400000000000000000000002731306272555200222260ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvcjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/041_alignment_multiline_hrvbjl.txt000066400000000000000000000002731306272555200222200ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvbjl :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/042_alignment_multiline_hrvbjc.txt000066400000000000000000000002731306272555200222100ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvbjc :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/043_alignment_multiline_hrvbjr.txt000066400000000000000000000002731306272555200222300ustar00rootroot00000000000000:ARGS -s 15x7 -a hrvbjr :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* */ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/044_alignment_multiline_l.txt000066400000000000000000000002661306272555200211710ustar00rootroot00000000000000:ARGS -s 15x7 -a l :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/045_alignment_multiline_c.txt000066400000000000000000000002661306272555200211610ustar00rootroot00000000000000:ARGS -s 15x7 -a c :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/046_alignment_multiline_r.txt000066400000000000000000000002661306272555200212010ustar00rootroot00000000000000:ARGS -s 15x7 -a r :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* ccccc */ /* */ /*************/ :EOFboxes-1.2/test/047_alignment_multiline_none.txt000066400000000000000000000004071306272555200216750ustar00rootroot00000000000000If no alignment option is given, text is aligned left and put in the top left corner. :ARGS -s 15x7 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/048_alignment_multiline_vertical_round_down.txt000066400000000000000000000002601306272555200250030ustar00rootroot00000000000000:ARGS -s 15x7 -a c :INPUT aaa bbbb :OUTPUT-FILTER :EXPECTED /*************/ /* */ /* aaa */ /* bbbb */ /* */ /* */ /*************/ :EOFboxes-1.2/test/049_alignment_illegal_format.txt000066400000000000000000000001471306272555200216400ustar00rootroot00000000000000:ARGS -a mistake :INPUT foo :OUTPUT-FILTER :EXPECTED-ERROR 1 boxes: Illegal text format -- mistake :EOFboxes-1.2/test/050_alignment_multiline_nop1.txt000066400000000000000000000002051306272555200216010ustar00rootroot00000000000000:ARGS -s 11x5 -a c :INPUT XXXXX XXXXX XXXXX :OUTPUT-FILTER :EXPECTED /*********/ /* XXXXX */ /* XXXXX */ /* XXXXX */ /*********/ :EOFboxes-1.2/test/051_alignment_multiline_nop2.txt000066400000000000000000000002121306272555200216010ustar00rootroot00000000000000:ARGS -s 11x5 -a hrvbjr :INPUT XXXXX XXXXX XXXXX :OUTPUT-FILTER :EXPECTED /*********/ /* XXXXX */ /* XXXXX */ /* XXXXX */ /*********/ :EOFboxes-1.2/test/052_simple_line_comment.txt000066400000000000000000000001101306272555200206230ustar00rootroot00000000000000:ARGS -c # :INPUT a bbb :OUTPUT-FILTER :EXPECTED # a # # bbb # # :EOFboxes-1.2/test/053_size_25x10.txt000066400000000000000000000005061306272555200164240ustar00rootroot00000000000000:ARGS -s 25x10 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /***********************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /* */ /* */ /* */ /***********************/ :EOFboxes-1.2/test/054_size_vs_padding_1.txt000066400000000000000000000002711306272555200202030ustar00rootroot00000000000000Size takes precedence over padding, left padding is killed first :ARGS -s 10x5 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /********/ /*aaa */ /*bbbb */ /*ccccc */ /********/ :EOFboxes-1.2/test/055_size_vs_padding_2.txt000066400000000000000000000002251306272555200202040ustar00rootroot00000000000000Size takes precedence over padding :ARGS -s 9x5 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*******/ /*aaa */ /*bbbb */ /*ccccc*/ /*******/ :EOFboxes-1.2/test/056_input_vs_size.txt000066400000000000000000000002471306272555200175210ustar00rootroot00000000000000Input length takes precedence over size option :ARGS -s 2x2 -p a2 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*******/ /*aaa */ /*bbbb */ /*ccccc*/ /*******/ :EOFboxes-1.2/test/057_size_vs_padding_2.txt000066400000000000000000000004041306272555200202050ustar00rootroot00000000000000:ARGS -p v1h10 -s 30x6 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /****************************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /****************************/ :EOFboxes-1.2/test/058_size_minimum_by_design.txt000066400000000000000000000013011306272555200213420ustar00rootroot00000000000000:ARGS -d diamonds -s 15x7 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /\ /\ /\ /\//\\/\ /\//\\/\ /\//\\/\ /\//\\\///\\/\//\\\///\\/\//\\\///\\/\ //\\\//\/\\///\\\//\/\\///\\\//\/\\///\\ \\//\/aaa \/\\// \/ bbbb \/ /\ ccccc /\ //\\ //\\ \\// \\// \/ \/ /\ /\ //\\/\ /\//\\ \\///\\/\//\\\///\\/\//\\\///\\/\//\\\// \/\\///\\\//\/\\///\\\//\/\\///\\\//\/ \/\\//\/ \/\\//\/ \/\\//\/ \/ \/ \/ :EOFboxes-1.2/test/059_size_same_as_design.txt000066400000000000000000000013021306272555200206070ustar00rootroot00000000000000:ARGS -d diamonds -s 40x16 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /\ /\ /\ /\//\\/\ /\//\\/\ /\//\\/\ /\//\\\///\\/\//\\\///\\/\//\\\///\\/\ //\\\//\/\\///\\\//\/\\///\\\//\/\\///\\ \\//\/aaa \/\\// \/ bbbb \/ /\ ccccc /\ //\\ //\\ \\// \\// \/ \/ /\ /\ //\\/\ /\//\\ \\///\\/\//\\\///\\/\//\\\///\\/\//\\\// \/\\///\\\//\/\\///\\\//\/\\///\\\//\/ \/\\//\/ \/\\//\/ \/\\//\/ \/ \/ \/ :EOFboxes-1.2/test/060_size_1_extra_line.txt000066400000000000000000000015441306272555200202200ustar00rootroot00000000000000:ARGS -d diamonds -s 40x17 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /\ /\ /\ /\//\\/\ /\//\\/\ /\//\\/\ /\//\\\///\\/\//\\\///\\/\//\\\///\\/\ //\\\//\/\\///\\\//\/\\///\\\//\/\\///\\ \\//\/aaa \/\\// \/ bbbb \/ /\ ccccc /\ //\\ //\\ \\// \\// \/ \/ /\ /\ //\\ //\\ \\// \\// \/ \/ /\ /\ //\\/\ /\//\\ \\///\\/\//\\\///\\/\//\\\///\\/\//\\\// \/\\///\\\//\/\\///\\\//\/\\///\\\//\/ \/\\//\/ \/\\//\/ \/\\//\/ \/ \/ \/ :EOFboxes-1.2/test/061_size_1_extra_line_and_1_extra_column.txt000066400000000000000000000021241306272555200240360ustar00rootroot00000000000000:ARGS -d diamonds -s 41x17 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /\ /\ /\ /\ /\//\\/\ /\//\\/\ /\//\\/\ /\//\\/\ /\//\\\///\\/\//\\\///\\/\//\\\///\\/\//\\\///\\/\ //\\\//\/\\///\\\//\/\\///\\\//\/\\///\\\//\/\\///\\ \\//\/aaa \/\\// \/ bbbb \/ /\ ccccc /\ //\\ //\\ \\// \\// \/ \/ /\ /\ //\\ //\\ \\// \\// \/ \/ /\ /\ //\\/\ /\//\\ \\///\\/\//\\\///\\/\//\\\///\\/\//\\\///\\/\//\\\// \/\\///\\\//\/\\///\\\//\/\\///\\\//\/\\///\\\//\/ \/\\//\/ \/\\//\/ \/\\//\/ \/\\//\/ \/ \/ \/ \/ :EOFboxes-1.2/test/062_size_with_indent.txt000066400000000000000000000003311306272555200201550ustar00rootroot00000000000000:ARGS -s 15x7 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/063_size_with_indent_and_padding.txt000066400000000000000000000003371306272555200224740ustar00rootroot00000000000000:ARGS -s 15x7 -p l2 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*************/ :EOFboxes-1.2/test/064_size_with_indent_and_too_much_padding.txt000066400000000000000000000003401306272555200243640ustar00rootroot00000000000000:ARGS -s 15x7 -p l10 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc*/ /* */ /* */ /*************/ :EOFboxes-1.2/test/065_size_missing_argument.txt000066400000000000000000000003261306272555200212230ustar00rootroot00000000000000:ARGS -s :INPUT foo :OUTPUT-FILTER 1s/^.\+: /boxes: / 1s/-- s$/-- 's'/ :EXPECTED-ERROR 1 boxes: option requires an argument -- 's' Usage: boxes [options] [infile [outfile]] Try `boxes -h' for more information. :EOFboxes-1.2/test/066_size_invalid_spec.txt000066400000000000000000000001541306272555200203100ustar00rootroot00000000000000:ARGS -s -2x3 :INPUT foo :OUTPUT-FILTER :EXPECTED-ERROR 1 boxes: invalid box size specification -- -2x3 :EOFboxes-1.2/test/067_size_as_small_as_possible_vertical.txt000066400000000000000000000001741306272555200237220ustar00rootroot00000000000000:ARGS -s 0x1 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*********/ /* aaa */ /* bbbb */ /* ccccc */ /*********/ :EOFboxes-1.2/test/068_size_single_argument.txt000066400000000000000000000002171306272555200210350ustar00rootroot00000000000000:ARGS -s 15 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*************/ /* aaa */ /* bbbb */ /* ccccc */ /*************/ :EOFboxes-1.2/test/069_size_single_argument_x.txt000066400000000000000000000002231306272555200213620ustar00rootroot00000000000000:ARGS -s x7 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*********/ /* aaa */ /* bbbb */ /* ccccc */ /* */ /* */ /*********/ :EOFboxes-1.2/test/070_size_as_small_as_possible_horiz.txt000066400000000000000000000001621306272555200232330ustar00rootroot00000000000000:ARGS -s 1x0 :INPUT aaa bbbb ccccc :OUTPUT-FILTER :EXPECTED /*******/ /*aaa */ /*bbbb */ /*ccccc*/ /*******/ :EOFboxes-1.2/test/071_size_invalid_spec_0x0.txt000066400000000000000000000001521306272555200207710ustar00rootroot00000000000000:ARGS -s 0x0 :INPUT foo :OUTPUT-FILTER :EXPECTED-ERROR 1 boxes: invalid box size specification -- 0x0 :EOFboxes-1.2/test/072_tab_expanded_split.txt000066400000000000000000000002611306272555200204430ustar00rootroot00000000000000:ARGS :INPUT XXXXXX XXXXXX XXXXXX :OUTPUT-FILTER :EXPECTED /**************/ /* XXXXXX */ /* XXXXXX */ /* XXXXXX */ /**************/ :EOFboxes-1.2/test/073_tab_expanded_size4.txt000066400000000000000000000002421306272555200203460ustar00rootroot00000000000000:ARGS -t 4 :INPUT XXXXXX XXXXXX XXXXXX :OUTPUT-FILTER :EXPECTED /**********/ /* XXXXXX */ /* XXXXXX */ /* XXXXXX */ /**********/ :EOFboxes-1.2/test/074_tab_keep_size4.txt000066400000000000000000000002401306272555200175010ustar00rootroot00000000000000:ARGS -t 4k :INPUT XXXXXX XXXXXX XXXXXX :OUTPUT-FILTER :EXPECTED /**********/ /* XXXXXX */ /* XXXXXX */ /* XXXXXX */ /**********/ :EOFboxes-1.2/test/075_tab_unexpand.txt000066400000000000000000000002241306272555200172640ustar00rootroot00000000000000:ARGS -t 4u :INPUT XXXXXX XXXXXX XXXXXX :OUTPUT-FILTER :EXPECTED /**********/ /* XXXXXX */ /* XXXXXX */ /* XXXXXX */ /**********/ :EOFboxes-1.2/test/076_tab_keep_size4_withContent.txt000066400000000000000000000002461306272555200220770ustar00rootroot00000000000000:ARGS -t 4k :INPUT XXXXXX XXX XXX XXXXXX :OUTPUT-FILTER :EXPECTED /***********/ /* XXXXXX */ /* XXX XXX */ /* XXXXXX */ /***********/ :EOFboxes-1.2/test/077_tab_unexpand_size8_withContent.txt000066400000000000000000000004331306272555200230000ustar00rootroot00000000000000Because input lines 1 and 3 are only 4 spaces, no tabs can be unexpanded! :ARGS -t 8u :INPUT XXXXXX XXX XXX XXXXXX :OUTPUT-FILTER :EXPECTED /*******************/ /* XXXXXX */ /* XXX XXX */ /* XXXXXX */ /*******************/ :EOFboxes-1.2/test/078_tab_unexpand_size8_withContent2.txt000066400000000000000000000002661306272555200230670ustar00rootroot00000000000000:ARGS -t 8u :INPUT XXXXXX XXX XXX XXXXXX :OUTPUT-FILTER :EXPECTED /***************/ /* XXXXXX */ /* XXX XXX */ /* XXXXXX */ /***************/ :EOFboxes-1.2/test/079_tab_keep_size8.txt000066400000000000000000000003221306272555200175130ustar00rootroot00000000000000:ARGS -t 8k :INPUT XXXXXX XXX XXX XXXXXX :OUTPUT-FILTER :EXPECTED /***************/ /* XXXXXX */ /* XXX XXX */ /* XXXXXX */ /***************/ :EOFboxes-1.2/test/080_tab_expand_size4.txt000066400000000000000000000002341306272555200200340ustar00rootroot00000000000000:ARGS -t 4 :INPUT XXXXXX XXXXXX XXXXXX :OUTPUT-FILTER :EXPECTED /**********/ /* XXXXXX */ /* XXXXXX */ /* XXXXXX */ /**********/ :EOFboxes-1.2/test/081_tab_unexpand_size4_fromNone.txt000066400000000000000000000002271306272555200222450ustar00rootroot00000000000000:ARGS -t 4u :INPUT XXXXXX XXXXXX XXXXXX :OUTPUT-FILTER :EXPECTED /**********/ /* XXXXXX */ /* XXXXXX */ /* XXXXXX */ /**********/ :EOFboxes-1.2/test/082_tab_unexpand_size4_split.txt000066400000000000000000000002471306272555200216200ustar00rootroot00000000000000:ARGS -t 4u :INPUT XXXXXX XXXXXX XXXXXX :OUTPUT-FILTER :EXPECTED /**********/ /* XXXXXX */ /* XXXXXX */ /* XXXXXX */ /**********/ :EOFboxes-1.2/test/083_list_design_info.txt000066400000000000000000000014061306272555200201350ustar00rootroot00000000000000:ARGS -l -d c :INPUT :OUTPUT-FILTER :EXPECTED Complete Design Information for "c": ------------------------------------ Author: Thomas Jensen Original Designer: (public domain) Creation Date: March 18, 1999 (Thursday, 15:25h) Current Revision: 1.0 as of March 18, 1999 (Thursday, 15:25h) Indentation Mode: box (indent box) Replacement Rules: 1. (glob) "\*/" WITH "*\/" Reversion Rules: 1. (glob) "\*\\/" TO "*/" Minimum Box Dimensions: 5 x 3 (width x height) Default Padding: left 1, right 1 Default Killblank: yes Elastic Shapes: N, E, S, W Defined Shapes: NW: "/*" N: "*" NE: "*/" E: "*/" SE: "*/" S: "*" SW: "/*" W: "/*" :EOF boxes-1.2/test/084_list_design_info_for_cmdline_definition.txt000066400000000000000000000012311306272555200247030ustar00rootroot00000000000000:ARGS -c # -l :INPUT :OUTPUT-FILTER :EXPECTED Complete Design Information for "": ------------------------------------------------------------ Author: (unknown author) Original Designer: (unknown artist) Creation Date: now Current Revision: 1.0 Indentation Mode: box (indent box) Replacement Rules: none Reversion Rules: none Minimum Box Dimensions: 3 x 3 (width x height) Default Padding: left 1 Default Killblank: no Elastic Shapes: N, E, S, W Defined Shapes: NW: " " N: " " NE: " " E: " " SE: " " S: " " SW: " " W: "#" :EOF boxes-1.2/test/testrunner.sh000077500000000000000000000060131306272555200162320ustar00rootroot00000000000000#!/usr/bin/env bash # # Low-tech test runner for boxes. # # File: testrunner.sh # Date created: September 23, 2014 (Tuesday, 20:06h) # Author: Thomas Jensen # _____________________________________________________________________ if [ $# -ne 1 ]; then echo 'Usage: testrunner.sh {-suite | }' echo ' Returns 0 for success, else non-zero' exit 2 fi if [ ${PWD##*/} != "test" ]; then >&2 echo "Please run this script from the test folder." exit 2 fi # Execute the entire test suite if [ "$1" == "-suite" ]; then declare -i overallResult=0 declare -i countExecuted=0 declare -i countFailed=0 declare tc for tc in *.txt; do $0 $tc if [ $? -ne 0 ]; then overallResult=1 ((countFailed++)) fi ((countExecuted++)) done echo "$countExecuted tests executed, $(($countExecuted-$countFailed)) successful, $countFailed failed." exit $overallResult fi # Execute only a single test declare -r testCaseFile="$1" if [ ! -f $testCaseFile ]; then >&2 echo "Test Case '$testCaseFile' not found." exit 3 fi echo "Running test case: $testCaseFile" declare sectionName for sectionName in :ARGS :INPUT :OUTPUT-FILTER :EXPECTED :EOF; do if [ $(grep -c ^$sectionName $testCaseFile) -ne 1 ]; then >&2 echo "Missing section $sectionName in test case '$testCaseFile'." exit 4 fi done declare -i expectedReturnCode=0 if [ $(grep -c "^:EXPECTED-ERROR " $testCaseFile) -eq 1 ]; then expectedReturnCode=$(grep "^:EXPECTED-ERROR " $testCaseFile | sed -e 's/:EXPECTED-ERROR //') fi declare -r testInputFile=${testCaseFile/%.txt/.input.tmp} declare -r testExpectationFile=${testCaseFile/%.txt/.expected.tmp} declare -r testFilterFile=${testCaseFile/%.txt/.sed.tmp} declare -r testOutputFile=${testCaseFile/%.txt/.out.tmp} declare -r boxesArgs=$(cat $testCaseFile | sed -n '/^:ARGS/,+1p' | grep -v ^:INPUT | sed '1d') cat $testCaseFile | sed -n '/^:INPUT/,/^:OUTPUT-FILTER/p;' | sed '1d;$d' | tr -d '\r' > $testInputFile cat $testCaseFile | sed -n '/^:OUTPUT-FILTER/,/^:EXPECTED\b.*$/p;' | sed '1d;$d' | tr -d '\r' > $testFilterFile cat $testCaseFile | sed -n '/^:EXPECTED/,/^:EOF/p;' | sed '1d;$d' | tr -d '\r' > $testExpectationFile declare boxesBinary=../src/boxes.exe if [ ! -x $boxesBinary ]; then boxesBinary=../src/boxes fi echo " Invoking: $(basename $boxesBinary) $boxesArgs" export BOXES=../boxes-config cat $testInputFile | $boxesBinary $boxesArgs >$testOutputFile 2>&1 declare -ir actualReturnCode=$? cat $testOutputFile | tr -d '\r' | sed -f $testFilterFile | diff - $testExpectationFile if [ $? -ne 0 ]; then >&2 echo "Error in test case: $testCaseFile (top: actual; bottom: expected)" exit 5 fi if [ $actualReturnCode -ne $expectedReturnCode ]; then >&2 echo "Error in test case: $testCaseFile (error code was $actualReturnCode, but expected $expectedReturnCode)" exit 5 fi rm $testInputFile rm $testFilterFile rm $testExpectationFile rm $testOutputFile echo " OK" exit 0 #EOF boxes-1.2/versions.txt000066400000000000000000000001121306272555200151060ustar00rootroot00000000000000gcc version 3.3.3 (SuSE Linux) bison (GNU Bison) 1.875 flex version 2.5.4