pax_global_header 0000666 0000000 0000000 00000000064 13062725552 0014521 g ustar 00root root 0000000 0000000 52 comment=4ca282b327bd929587a8f5e3b76bfdfbf8083a55
boxes-1.2/ 0000775 0000000 0000000 00000000000 13062725552 0012503 5 ustar 00root root 0000000 0000000 boxes-1.2/.gitignore 0000664 0000000 0000000 00000000276 13062725552 0014500 0 ustar 00root root 0000000 0000000 .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.yml 0000664 0000000 0000000 00000000267 13062725552 0014621 0 ustar 00root root 0000000 0000000 # 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/LICENSE 0000664 0000000 0000000 00000043152 13062725552 0013515 0 ustar 00root root 0000000 0000000 GNU 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/Makefile 0000664 0000000 0000000 00000005642 13062725552 0014152 0 ustar 00root root 0000000 0000000 #
# 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.txt 0000664 0000000 0000000 00000002460 13062725552 0015104 0 ustar 00root root 0000000 0000000 boxes 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.md 0000664 0000000 0000000 00000005072 13062725552 0013766 0 ustar 00root root 0000000 0000000 [](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.lsm 0000664 0000000 0000000 00000002022 13062725552 0014632 0 ustar 00root root 0000000 0000000 Begin4
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-config 0000664 0000000 0000000 00000165165 13062725552 0015027 0 ustar 00root root 0000000 0000000 #
# 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 (" ", "<\/", "\")
ne (" ", "> ", "> ")
wnw (" <\/>", " \>")
w ("<\/> ", "\> ")
wsw (" <\/>", " \>")
sw (" <", " <", " ")
ssw ("\/>", "/\>", " ")
s (" ", "<\/>", "\>")
sse ("<\/", "\", " ")
se ("> ", "> ", " ")
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.openwrt 0000664 0000000 0000000 00000003511 13062725552 0016022 0 ustar 00root root 0000000 0000000 # 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.spec 0000664 0000000 0000000 00000004270 13062725552 0014502 0 ustar 00root root 0000000 0000000 %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.vim 0000664 0000000 0000000 00000007457 13062725552 0014355 0 ustar 00root root 0000000 0000000 " 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/ 0000775 0000000 0000000 00000000000 13062725552 0013250 5 ustar 00root root 0000000 0000000 boxes-1.2/doc/boxes.1.in 0000664 0000000 0000000 00000026104 13062725552 0015062 0 ustar 00root root 0000000 0000000 .\" @(#)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.el 0000664 0000000 0000000 00000010715 13062725552 0014716 0 ustar 00root root 0000000 0000000 ;;; 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/makehtmlman 0000664 0000000 0000000 00000001000 13062725552 0015460 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13062725552 0013272 5 ustar 00root root 0000000 0000000 boxes-1.2/src/Makefile 0000664 0000000 0000000 00000010221 13062725552 0014726 0 ustar 00root root 0000000 0000000 #
# 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.c 0000664 0000000 0000000 00000156643 13062725552 0014575 0 ustar 00root root 0000000 0000000 /*
* 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.in 0000664 0000000 0000000 00000014200 13062725552 0015165 0 ustar 00root root 0000000 0000000 /*
* 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.h 0000664 0000000 0000000 00000003031 13062725552 0014705 0 ustar 00root root 0000000 0000000 /*
* 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.c 0000664 0000000 0000000 00000110040 13062725552 0015224 0 ustar 00root root 0000000 0000000 /*
* 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.h 0000664 0000000 0000000 00000002744 13062725552 0015244 0 ustar 00root root 0000000 0000000 /*
* 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.h 0000664 0000000 0000000 00000003370 13062725552 0014565 0 ustar 00root root 0000000 0000000 /*
* 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.l 0000664 0000000 0000000 00000024230 13062725552 0014567 0 ustar 00root root 0000000 0000000 %{
/*
* 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/ 0000775 0000000 0000000 00000000000 13062725552 0014225 5 ustar 00root root 0000000 0000000 boxes-1.2/src/misc/README.misc.md 0000664 0000000 0000000 00000000216 13062725552 0016435 0 ustar 00root root 0000000 0000000 ###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.c 0000664 0000000 0000000 00000072627 13062725552 0015711 0 ustar 00root root 0000000 0000000 /* 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.h 0000664 0000000 0000000 00000007530 13062725552 0015705 0 ustar 00root root 0000000 0000000 /* 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.y 0000664 0000000 0000000 00000067250 13062725552 0014772 0 ustar 00root root 0000000 0000000 %{
/*
* 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/ 0000775 0000000 0000000 00000000000 13062725552 0014564 5 ustar 00root root 0000000 0000000 boxes-1.2/src/regexp/Makefile 0000664 0000000 0000000 00000003471 13062725552 0016231 0 ustar 00root root 0000000 0000000 #
# 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.c 0000664 0000000 0000000 00000065777 13062725552 0016250 0 ustar 00root root 0000000 0000000 /*
* 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.h 0000664 0000000 0000000 00000001361 13062725552 0016230 0 ustar 00root root 0000000 0000000 /*
* 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.h 0000664 0000000 0000000 00000000231 13062725552 0016507 0 ustar 00root root 0000000 0000000 /*
* 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.c 0000664 0000000 0000000 00000013756 13062725552 0016233 0 ustar 00root root 0000000 0000000 /*
* 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.c 0000664 0000000 0000000 00000112603 13062725552 0014736 0 ustar 00root root 0000000 0000000 /*
* 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