mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Initial import of svn+ssh:://svn.icir.org/bro/trunk/bro as of r7088
This commit is contained in:
commit
61757ac78b
1383 changed files with 380824 additions and 0 deletions
0
AUTHORS
Normal file
0
AUTHORS
Normal file
49
COPYING
Normal file
49
COPYING
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
Copyright (c) 1995-2008, The Regents of the University of California,
|
||||||
|
through Lawrence Berkeley National Laboratory. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
(1) Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
(2) Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
(3) Neither the name of the University of California, Lawrence Berkeley
|
||||||
|
National Laboratory, U.S. Dept. of Energy, International Computer
|
||||||
|
Science Institute, nor the names of contributors may be used to endorse
|
||||||
|
or promote products derived from this software without specific prior
|
||||||
|
written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Note that some files in the Bro distribution carry their own copyright
|
||||||
|
notices. The above applies to the Bro scripts in policy/ (other than as
|
||||||
|
noted below) and the source files in src/ , other than:
|
||||||
|
|
||||||
|
policy/sigs/p0fsyn.osf
|
||||||
|
src/H3.h
|
||||||
|
src/OSFinger.cc
|
||||||
|
src/OSFinger.h
|
||||||
|
src/bsd-getopt-long.c
|
||||||
|
src/bsd-getopt-long.h
|
||||||
|
src/md5.c
|
||||||
|
src/md5.h
|
||||||
|
src/patricia.c
|
||||||
|
src/patricia.h
|
||||||
|
|
||||||
|
In addition, the build components such as Makefile.in, acinclude.m4, and
|
||||||
|
others have separate copyrights, as do a number of the elements in the
|
||||||
|
aux/ subdirectory and in scripts/s2b/snort_rules2.2/ .
|
0
ChangeLog
Normal file
0
ChangeLog
Normal file
42
Checklist-for-Release
Normal file
42
Checklist-for-Release
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
- Make sure BroV6 works.
|
||||||
|
|
||||||
|
- Make sure --enable-int64 builds w/o warnings.
|
||||||
|
|
||||||
|
- Update TODO-For-Next-Release.
|
||||||
|
|
||||||
|
- Build distribution on a system with an up-to-date yacc (MacOS suffices).
|
||||||
|
|
||||||
|
- make distcheck
|
||||||
|
|
||||||
|
- Edit CHANGES to final version.
|
||||||
|
|
||||||
|
- Fix VERSION to final value.
|
||||||
|
|
||||||
|
- Update version info (and perhaps other stuff) in README.
|
||||||
|
|
||||||
|
- Check everything in.
|
||||||
|
|
||||||
|
- Make an SVN branch for the release:
|
||||||
|
|
||||||
|
svn cp svn+ssh://svn.icir.org/bro/trunk \
|
||||||
|
svn+ssh://svn.icir.org/bro/releases/release_1_X
|
||||||
|
|
||||||
|
- scp bro-XXX.tar.gz crd.lbl.gov:/ftp/BROIDS/
|
||||||
|
scp CHANGES crd.lbl.gov:/ftp/BROIDS/bro-change-log.txt
|
||||||
|
|
||||||
|
- Fix symlinks on crd:
|
||||||
|
|
||||||
|
bro-1.X-release.tar.gz
|
||||||
|
bro-1.X-current.tar.gz
|
||||||
|
bro-1.<n>-release.tar.gz
|
||||||
|
|
||||||
|
- Update crd:/www/BROIDS/download.html to reflect new version. This page
|
||||||
|
is generated from trunk/bro-web/download.xml. Edit this file, and also
|
||||||
|
update the (web page) version in build.xml, the copyright year in
|
||||||
|
navigation.xml, and create a news entry in news.xml.
|
||||||
|
|
||||||
|
Type 'ant style' on a machine with 'ant' installed, and copy
|
||||||
|
html/*.html to crd.lbl.gov:/www/BROIDS/ .
|
||||||
|
|
||||||
|
- Send email to bro@bro-ids.org. Look for "release now available" in
|
||||||
|
previous messages as a template.
|
3
FILES.bin
Normal file
3
FILES.bin
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
README
|
||||||
|
VERSION
|
||||||
|
bro
|
104
INSTALL
Normal file
104
INSTALL
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
Prerequisites
|
||||||
|
=============
|
||||||
|
|
||||||
|
Bro relies on the following libraries and tools, which need to be installed
|
||||||
|
before you begin with the installation:
|
||||||
|
|
||||||
|
* Libpcap
|
||||||
|
If libpcap is already installed on the system, by default Bro
|
||||||
|
will use that one. Otherwise, it falls back to a version shipped
|
||||||
|
with the Bro distribution.
|
||||||
|
|
||||||
|
* Flex
|
||||||
|
Flex is already installed on most systems, so with luck you can
|
||||||
|
skip having to install it yourself.
|
||||||
|
|
||||||
|
* Bison or byacc
|
||||||
|
These come with many systems, but if you get errors compiling
|
||||||
|
parse.y, you will need to install them. bison is available
|
||||||
|
from GNU sites such as ftp.gnu.org.
|
||||||
|
|
||||||
|
* BIND8 headers and libraries
|
||||||
|
These are usually already installed as well.
|
||||||
|
|
||||||
|
* Autotools
|
||||||
|
If you have checked the source out from Bro's Subversion
|
||||||
|
repository, you need the autotools suite installed. In this
|
||||||
|
case, run "./autogen.sh" first right after the check out.
|
||||||
|
Otherwise the installation steps below will fail.
|
||||||
|
|
||||||
|
Bro can also make uses of some optional libraries if they are found at
|
||||||
|
installation time:
|
||||||
|
|
||||||
|
* OpenSSL
|
||||||
|
For analysis of SSL certificates by the HTTP analyzer, and
|
||||||
|
for encrypted Bro-to-Bro communication.
|
||||||
|
|
||||||
|
* Libmagic
|
||||||
|
For identifying file types (e.g., in FTP transfers).
|
||||||
|
|
||||||
|
* LibGeoIP
|
||||||
|
For geo-locating IP addresses.
|
||||||
|
|
||||||
|
* Libz
|
||||||
|
For decompressing HTTP bodies by the HTTP analyzer, and for
|
||||||
|
compressed Bro-to-Bro communication.
|
||||||
|
|
||||||
|
* Endace's DAG tools:
|
||||||
|
For native support of Endace DAG cards.
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
To build and install into /usr/local:
|
||||||
|
|
||||||
|
> ./configure
|
||||||
|
> make
|
||||||
|
> make install
|
||||||
|
|
||||||
|
This will install the Bro binary into /usr/local/bin/bro and the policy
|
||||||
|
files into /usr/local/share/bro.
|
||||||
|
|
||||||
|
As usual you can specify a different installation directory with
|
||||||
|
|
||||||
|
> ./configure --prefix=<dir>".
|
||||||
|
|
||||||
|
Run "./configure --help" for more options.
|
||||||
|
|
||||||
|
|
||||||
|
Running Bro
|
||||||
|
===========
|
||||||
|
|
||||||
|
Bro is a complex program and it takes a bit of time to get familiar
|
||||||
|
with it. In the following we give a few simple examples. See
|
||||||
|
http://www.bro-ids.org/wiki for more information.
|
||||||
|
|
||||||
|
To run a policy file from /usr/local/share/bro, such as mt.bro, on a
|
||||||
|
previously captured tcpdump save file named foo:
|
||||||
|
|
||||||
|
bro -r foo mt.bro
|
||||||
|
|
||||||
|
To run from interface le0:
|
||||||
|
|
||||||
|
bro -i le0 mt
|
||||||
|
|
||||||
|
You can alternatively specify interface and scripts to load in your own
|
||||||
|
policy file:
|
||||||
|
|
||||||
|
@load mt
|
||||||
|
redef interfaces = "le0";
|
||||||
|
|
||||||
|
and then run
|
||||||
|
|
||||||
|
bro ./my-policy.bro
|
||||||
|
|
||||||
|
You can see the BPF filter Bro will use (if not overridden) by executing
|
||||||
|
|
||||||
|
bro mt print-filter
|
||||||
|
|
||||||
|
To run interactively (e.g., for playing with expression evaluation):
|
||||||
|
|
||||||
|
bro
|
||||||
|
|
||||||
|
"bro -h" lists the various options.
|
64
Makefile.am
Normal file
64
Makefile.am
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
# snag the whole linux-include directory
|
||||||
|
EXTRA_DIST = CHANGES README VERSION shtool linux-include \
|
||||||
|
autogen.sh depcomp ylwrap
|
||||||
|
|
||||||
|
# When running distcheck, make sure we skip building GtkDoc-based
|
||||||
|
# documentation. This applies to Broccoli only, and needs to be
|
||||||
|
# duplicated here because DISTCHECK_CONFIGURE_FLAGS isn't otherwise
|
||||||
|
# noticed.
|
||||||
|
#
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS = --disable-gtk-doc
|
||||||
|
|
||||||
|
chown = @CHOWN@
|
||||||
|
|
||||||
|
# aux before src so we compile the libpcap
|
||||||
|
SUBDIRS = aux src scripts policy doc
|
||||||
|
|
||||||
|
test:
|
||||||
|
( cd ../testing && $(MAKE) test )
|
||||||
|
|
||||||
|
install-broctl:
|
||||||
|
$(MAKE) install
|
||||||
|
( cd aux/broctl && $(MAKE) install-broctl )
|
||||||
|
|
||||||
|
# Deprecated. Don't use.
|
||||||
|
install-brolite:
|
||||||
|
$(MAKE) install
|
||||||
|
$(INSTALL) -d $(prefix)/logs
|
||||||
|
$(INSTALL) -d $(prefix)/archive
|
||||||
|
$(INSTALL) -d $(prefix)/var
|
||||||
|
( cd scripts && $(MAKE) install-brolite )
|
||||||
|
( cd aux && $(MAKE) install-brolite )
|
||||||
|
- @CHOWN@ -R `cat scripts/bro_user_id` ${prefix}/
|
||||||
|
@echo "*********************************************************"
|
||||||
|
@echo "Please run \"${prefix}/etc/bro.rc --start\" to start bro"
|
||||||
|
@echo "*********************************************************"
|
||||||
|
|
||||||
|
docs:
|
||||||
|
( cd doc && $(MAKE) doc )
|
||||||
|
|
||||||
|
doc-install:
|
||||||
|
( cd doc && $(MAKE) doc-install )
|
||||||
|
|
||||||
|
update:
|
||||||
|
( cd scripts && $(MAKE) update )
|
||||||
|
( cd policy && $(MAKE) install )
|
||||||
|
|
||||||
|
update-sigs:
|
||||||
|
(cd scripts && $(MAKE) update-sigs )
|
||||||
|
|
||||||
|
reports:
|
||||||
|
( cd scripts && $(MAKE) reports )
|
||||||
|
|
||||||
|
# make sure we don't leak CVS/SVN or private policy files
|
||||||
|
dist-hook:
|
||||||
|
rm -rf `find $(distdir) -name CVS`
|
||||||
|
rm -rf `find $(distdir) -name .svn`
|
||||||
|
rm -rf $(distdir)/policy/local
|
||||||
|
|
||||||
|
release:
|
||||||
|
./autogen.sh
|
||||||
|
./configure
|
||||||
|
$(MAKE) distcheck
|
0
NEWS
Normal file
0
NEWS
Normal file
36
README
Normal file
36
README
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
This is release 1.5 of Bro, a system for detecting network intruders in
|
||||||
|
real-time using passive network monitoring.
|
||||||
|
|
||||||
|
Please see the file INSTALL for installation instructions and some examples
|
||||||
|
on how to run Bro. For more documentation, see the Bro Wiki:
|
||||||
|
|
||||||
|
http://www.bro-ids.org/wiki/index.php/User_Manual
|
||||||
|
|
||||||
|
Please note that this documentation is preliminary and still missing pieces.
|
||||||
|
PDF and HTML versions of older versions of the manuals are also available
|
||||||
|
in the doc/ directory.
|
||||||
|
|
||||||
|
There's also in doc/misc/conn-logs/ a brief summary of the connection logs
|
||||||
|
generated by the sample policy scripts (which are in policy/).
|
||||||
|
|
||||||
|
Numerous other Bro-related publications, including a paper describing the
|
||||||
|
system, can be found at
|
||||||
|
|
||||||
|
http://www.bro-ids.org/publications.html
|
||||||
|
|
||||||
|
Some auxiliary scripts and utilities are available in the aux/ directory.
|
||||||
|
Note that these are not installed by default.
|
||||||
|
|
||||||
|
Send comments, etc., to the Bro mailing list, bro@bro-ids.org. However,
|
||||||
|
please note that you must first subscribe to the list in order to be able
|
||||||
|
to post to it.
|
||||||
|
|
||||||
|
- Vern Paxson & Robin Sommer, on behalf of the Bro development team
|
||||||
|
|
||||||
|
Lawrence Berkeley National Laboratory
|
||||||
|
University of California, Berkeley USA
|
||||||
|
|
||||||
|
ICSI Center for Internet Research (ICIR)
|
||||||
|
International Computer Science Institute
|
||||||
|
Berkeley, CA USA
|
||||||
|
vern@icir.org / robin@icir.org
|
9
TODO-For-Next-Release
Normal file
9
TODO-For-Next-Release
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
Plan for 1.6:
|
||||||
|
Originally, with 1.5 we were going to start working with --use-binpac
|
||||||
|
as the default. However, this has been deferred pending development
|
||||||
|
of BinPAC++. We might however turn on BinPAC for the SSL analyzer,
|
||||||
|
for which the BinPAC version is more robust. It, though, doesn't
|
||||||
|
support storing certs to disk, which some folks use operationally.
|
||||||
|
|
||||||
|
Given DPD means we might not filter traffic anyway, we no longer
|
||||||
|
have such a good excuse for not dealing with IPv6 options.
|
1
VERSION
Normal file
1
VERSION
Normal file
|
@ -0,0 +1 @@
|
||||||
|
1.5.2.7
|
1007
acinclude.m4
Normal file
1007
acinclude.m4
Normal file
File diff suppressed because it is too large
Load diff
143
autogen.sh
Executable file
143
autogen.sh
Executable file
|
@ -0,0 +1,143 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Initialization script to set up the initial configuration files etc.
|
||||||
|
# shtool usage inspired by the autogen script of the ferite scripting
|
||||||
|
# language -- cheers Chris :)
|
||||||
|
#
|
||||||
|
# This is 'borrowed' from netdude, with minor changes for bro
|
||||||
|
|
||||||
|
BLD_ON=`./shtool echo -n -e %B`
|
||||||
|
BLD_OFF=`./shtool echo -n -e %b`
|
||||||
|
|
||||||
|
srcdir=`dirname $0`
|
||||||
|
NAME=bro
|
||||||
|
|
||||||
|
DIE=0
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo " "${BLD_ON}"BRO Build Tools Setup"${BLD_OFF}
|
||||||
|
echo "===================================================="
|
||||||
|
echo
|
||||||
|
echo "Checking whether we have all tools available ..."
|
||||||
|
|
||||||
|
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
|
echo
|
||||||
|
echo ${BLD_ON}"Error"${BLD_OFF}": You must have \`autoconf' installed to."
|
||||||
|
echo "Download the appropriate package for your distribution,"
|
||||||
|
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||||
|
DIE=1
|
||||||
|
}
|
||||||
|
|
||||||
|
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
|
echo
|
||||||
|
echo ${BLD_ON}"Error"${BLD_OFF}": You must have \`automake' installed."
|
||||||
|
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||||
|
echo "(or a newer version if it is available)"
|
||||||
|
DIE=1
|
||||||
|
NO_AUTOMAKE=yes
|
||||||
|
}
|
||||||
|
|
||||||
|
# if no automake, don't bother testing for aclocal
|
||||||
|
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
|
echo
|
||||||
|
echo ${BLD_ON}"Error"${BLD_OFF}": Missing \`aclocal'. The version of \`automake'"
|
||||||
|
echo "installed doesn't appear recent enough."
|
||||||
|
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||||
|
echo "(or a newer version if it is available)"
|
||||||
|
DIE=1
|
||||||
|
}
|
||||||
|
|
||||||
|
if test "$DIE" -eq 1; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "All necessary tools found."
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [ -d autom4te.cache ] ; then
|
||||||
|
echo "Removing autom4te.cache ..."
|
||||||
|
rm -rf autom4te.cache
|
||||||
|
#echo
|
||||||
|
#echo ${BLD_ON}"Error"${BLD_OFF}": autom4te.cache directory exists"
|
||||||
|
#echo "please remove it, and rerun this script"
|
||||||
|
#echo
|
||||||
|
#exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "running "${BLD_ON}"aclocal"${BLD_OFF}
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
aclocal -I . $ACLOCAL_FLAGS
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "running "${BLD_ON}"autoheader"${BLD_OFF}
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
autoheader
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "running "${BLD_ON}"automake"${BLD_OFF}
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
automake -a -c
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "running "${BLD_ON}"autoconf"${BLD_OFF}
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
autoconf
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "Running aux/binpac/autogen.sh"
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
(cd aux/binpac/ && BROBUILD=yes ./autogen.sh)
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "Running aux/broccoli/autogen.sh"
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
(cd aux/broccoli/ && BROBUILD=yes ./autogen.sh)
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "Running aux/broctl/aux/capstats/autogen.sh"
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
(cd aux/broctl/aux/capstats && ./autogen.sh)
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "Setup finished. Now run:"
|
||||||
|
echo
|
||||||
|
echo " $ "${BLD_ON}"./configure"${BLD_OFF}" (with options as needed, try --help)"
|
||||||
|
echo
|
||||||
|
echo "and then"
|
||||||
|
echo
|
||||||
|
echo " $ "${BLD_ON}"make"${BLD_OFF}
|
||||||
|
echo " # "${BLD_ON}"make install"${BLD_OFF}
|
||||||
|
echo
|
77
aux/Makefile.am
Normal file
77
aux/Makefile.am
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
LIBPCAP_VER = libpcap-0.9.8
|
||||||
|
LIBPCAP_LIB = $(LIBPCAP_VER)/libpcap.a
|
||||||
|
|
||||||
|
EXTRA_DIST = README $(LIBPCAP_VER).tar.gz
|
||||||
|
|
||||||
|
# if we don't have ssl, can't build bdcat
|
||||||
|
if USE_SSL
|
||||||
|
bdcat_dir = bdcat
|
||||||
|
else
|
||||||
|
bdcat_dir =
|
||||||
|
endif
|
||||||
|
|
||||||
|
# don't compile libpcap if they did a '--disable-localpcap' to configure
|
||||||
|
if USE_LOCALPCAP
|
||||||
|
built_srcs = $(LIBPCAP_LIB)
|
||||||
|
LARGE_FILE = "-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE"
|
||||||
|
else
|
||||||
|
built_srcs =
|
||||||
|
endif
|
||||||
|
|
||||||
|
if USEV6
|
||||||
|
PCAPARGS = --enable-ipv6
|
||||||
|
else
|
||||||
|
PCAPARGS =
|
||||||
|
endif
|
||||||
|
|
||||||
|
if USE_BROCCOLI
|
||||||
|
broccoli = broccoli
|
||||||
|
else
|
||||||
|
broccoli =
|
||||||
|
endif
|
||||||
|
|
||||||
|
if USE_BROCTL
|
||||||
|
broctl = broctl
|
||||||
|
else
|
||||||
|
broctl =
|
||||||
|
endif
|
||||||
|
|
||||||
|
BUILT_SOURCES = $(built_srcs)
|
||||||
|
|
||||||
|
SUBDIRS = adtrace binpac cf hf nftools rst scripts \
|
||||||
|
$(bdcat_dir) $(broccoli) $(broctl)
|
||||||
|
|
||||||
|
DIST_SUBDIRS = adtrace binpac cf hf nftools rst scripts \
|
||||||
|
$(bdcat_dir) $(broccoli) $(broctl)
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -rf $(LIBPCAP_VER)
|
||||||
|
|
||||||
|
|
||||||
|
$(LIBPCAP_LIB): $(top_srcdir)/aux/$(LIBPCAP_VER).tar.gz
|
||||||
|
@echo "Unpacking libpcap sources"
|
||||||
|
@gzip -d < $(top_srcdir)/aux/$(LIBPCAP_VER).tar.gz | tar xf -
|
||||||
|
@echo "Building libpcap"
|
||||||
|
( cd $(LIBPCAP_VER) && ./configure --prefix=$(prefix) $(PCAPARGS) CFLAGS=$(LARGE_FILE) && $(MAKE) )
|
||||||
|
@chmod -R 755 $(LIBPCAP_VER)
|
||||||
|
|
||||||
|
|
||||||
|
# This is a hack. These are hardcoded here to mimic the previous
|
||||||
|
# brolite installation. While these should better go into the
|
||||||
|
# subdirs' Makefile.am, it's not really worth the effort as
|
||||||
|
# we will get rid of all this at some point anyway.
|
||||||
|
install-brolite:
|
||||||
|
$(INSTALL) ./hf/hf ${bindir}
|
||||||
|
$(INSTALL) ./hf/nf ${bindir}
|
||||||
|
$(INSTALL) ./hf/pf ${bindir}
|
||||||
|
$(INSTALL) ./cf/cf ${bindir}
|
||||||
|
$(INSTALL) ./rst/rst ${bindir}
|
||||||
|
- install -d $(prefix)/scripts/
|
||||||
|
$(INSTALL) ./scripts/host-to-addrs $(prefix)/scripts
|
||||||
|
$(INSTALL) ./scripts/bro-logchk.pl $(prefix)/scripts
|
||||||
|
$(INSTALL) ./scripts/host-grep $(prefix)/scripts
|
||||||
|
$(INSTALL) ./scripts/mvlog $(prefix)/scripts
|
||||||
|
|
||||||
|
|
61
aux/README
Normal file
61
aux/README
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
This directory contains handy auxiliary programs:
|
||||||
|
|
||||||
|
adtrace/
|
||||||
|
Makefile and source for the adtrace utility. This program is used
|
||||||
|
in conjunction with the localnetMAC.pl perl script to compute the
|
||||||
|
network address that compose the internal and extern nets that bro
|
||||||
|
is monitoring. This program when run by itself just reads a pcap
|
||||||
|
(tcpcump) file and writes out the src MAC, dst MAC, src IP, dst
|
||||||
|
IP for each packet seen in the file. This output is processed by
|
||||||
|
the localnetMAC.pl script during 'make install'.
|
||||||
|
|
||||||
|
bdcat/
|
||||||
|
A utility for decrypting encrypted Bro log files.
|
||||||
|
|
||||||
|
binpac/
|
||||||
|
A compiler for generating protocol analyzers from high-level,
|
||||||
|
declarative specifications. Used extensively for constructing
|
||||||
|
Bro's protocol analyzers, but capable of stand-alone use for
|
||||||
|
building analyzers outside of the Bro system.
|
||||||
|
|
||||||
|
broccoli/
|
||||||
|
A C client library for interfacing programs with the Bro system.
|
||||||
|
Enables sending and receiving of Bro values and events.
|
||||||
|
|
||||||
|
cf/
|
||||||
|
Makefile and source for the "cf" utility. cf reads lines from
|
||||||
|
stdin and if the line begins with a number, then it assumes that
|
||||||
|
the number corresponds to a Unix timestamp and replaces it with
|
||||||
|
the corresponding local time in a readable format. Useful for
|
||||||
|
running on log files. See cf/cf.man.txt for documentation.
|
||||||
|
|
||||||
|
contrib/
|
||||||
|
Unsupported contributions to Bro.
|
||||||
|
|
||||||
|
hf/
|
||||||
|
The main utility in this subdirectory is hf, which translates
|
||||||
|
any dotted-quad (in text) appearing on stdin to the corresponding
|
||||||
|
DNS hostname (via a PTR lookup) on stdout.
|
||||||
|
|
||||||
|
nftools/
|
||||||
|
Utilities for dealing with Bro's custom file format for storing
|
||||||
|
NetFlow records. nfcollector reads NetFlow data from a socket
|
||||||
|
and writes it in Bro's format. ftwire2bro reads NetFlow "wire"
|
||||||
|
format (e.g., as generated by a 'flow-export' directive) and writes
|
||||||
|
it in Bro's format.
|
||||||
|
|
||||||
|
rst/
|
||||||
|
Makefile and source for the rst utility. "rst" can be invoked by
|
||||||
|
a Bro script to terminate an established TCP connection by forging
|
||||||
|
RST tear-down packets. See terminate_connection() in conn.bro.
|
||||||
|
|
||||||
|
scripts/
|
||||||
|
A set of utility scripts for munching on Bro connection summaries.
|
||||||
|
|
||||||
|
bro_logchk: orders and scans through FTP and HTTP logs
|
||||||
|
host-grep: greps a summary file for a particular host's activities
|
||||||
|
host-to-addrs: converts a hostname to a list of IP addresses
|
||||||
|
hot-report: formats a summary file in a readable fashion
|
||||||
|
ip-grep: returns a grep pattern for a given IP address
|
||||||
|
mon-report: summarizes a particular host's activity
|
||||||
|
mvlog: compresses and archives log files
|
10
aux/adtrace/Makefile.am
Normal file
10
aux/adtrace/Makefile.am
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
AM_CFLAGS=@V_INCLS@
|
||||||
|
|
||||||
|
# Should use AM_ vars, but automake 1.5 errors out.
|
||||||
|
#AM_LDFLAGS = @LDFLAGS@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
|
||||||
|
noinst_PROGRAMS = adtrace
|
||||||
|
adtrace_SOURCES = adtrace.c ether.h ethertype.h ip.h
|
92
aux/adtrace/adtrace.c
Normal file
92
aux/adtrace/adtrace.c
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <pcap.h>
|
||||||
|
|
||||||
|
#include "../../config.h"
|
||||||
|
#include "ip.h"
|
||||||
|
#include "ether.h"
|
||||||
|
#include "ethertype.h"
|
||||||
|
|
||||||
|
pcap_t *p;
|
||||||
|
|
||||||
|
const u_char* printEAddr(const u_char* pkt, u_char* endp){
|
||||||
|
const struct ether_header *ep;
|
||||||
|
int i=0;
|
||||||
|
ep = (const struct ether_header*) pkt;
|
||||||
|
|
||||||
|
if (pkt+ETHER_HDRLEN > endp ||
|
||||||
|
ntohs(ep->ether_type) != ETHERTYPE_IP){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i<ETHER_ADDR_LEN; i++){
|
||||||
|
if (i>0) putchar(':');
|
||||||
|
printf("%02x", ep->ether_shost[i]);
|
||||||
|
}
|
||||||
|
putchar (' ');
|
||||||
|
for (i = 0; i<ETHER_ADDR_LEN; i++){
|
||||||
|
if (i>0) putchar(':');
|
||||||
|
printf("%02x", ep->ether_dhost[i]);
|
||||||
|
}
|
||||||
|
putchar(' ');
|
||||||
|
return (pkt+ETHER_HDRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printIPAddr(const u_char* pkt, u_char* endp){
|
||||||
|
const struct ip* iph;
|
||||||
|
if (pkt+sizeof(struct ip) > endp) return;
|
||||||
|
iph = (const struct ip*) pkt;
|
||||||
|
fputs ((char*) inet_ntoa(iph->ip_src), stdout);
|
||||||
|
putchar(' ');
|
||||||
|
puts ((char*) inet_ntoa(iph->ip_dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
void handler(u_char *user, const struct pcap_pkthdr *head, const u_char *packet){
|
||||||
|
u_char* endp;
|
||||||
|
|
||||||
|
endp =(u_char*) packet + head->caplen;
|
||||||
|
packet = printEAddr(packet, endp);
|
||||||
|
if (packet)
|
||||||
|
printIPAddr(packet, endp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usage(char *av[])
|
||||||
|
{
|
||||||
|
fprintf(stderr,"usage: %s filename \n", av[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *file;
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
u_char* pkt, endp;
|
||||||
|
struct pcap_pkthdr *head;
|
||||||
|
|
||||||
|
if ( argc != 2 )
|
||||||
|
usage(argv);
|
||||||
|
|
||||||
|
file = argv[1];
|
||||||
|
|
||||||
|
p = pcap_open_offline(file, errbuf);
|
||||||
|
if(p==NULL){
|
||||||
|
fprintf (stderr, "cannot open %s: %s\n", file, errbuf);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pcap_datalink(p) != DLT_EN10MB){
|
||||||
|
fputs ("sorry, currently only ethernet links supported\n", stderr);
|
||||||
|
exit(1); //if it is not ethernet we are watching we won't have MACs
|
||||||
|
}
|
||||||
|
|
||||||
|
pcap_loop(p, -1, handler, NULL);
|
||||||
|
pcap_close(p);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
59
aux/adtrace/ether.h
Normal file
59
aux/adtrace/ether.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* @(#) $Header$ (LBL) */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1982, 1986, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)if_ether.h 8.3 (Berkeley) 5/2/95
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ETHERMTU 1500
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of bytes in an ethernet (MAC) address.
|
||||||
|
*/
|
||||||
|
#define ETHER_ADDR_LEN 6
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure of a DEC/Intel/Xerox or 802.3 Ethernet header.
|
||||||
|
*/
|
||||||
|
struct ether_header {
|
||||||
|
u_int8_t ether_dhost[ETHER_ADDR_LEN];
|
||||||
|
u_int8_t ether_shost[ETHER_ADDR_LEN];
|
||||||
|
u_int16_t ether_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Length of a DEC/Intel/Xerox or 802.3 Ethernet header; note that some
|
||||||
|
* compilers may pad "struct ether_header" to a multiple of 4 bytes,
|
||||||
|
* for example, so "sizeof (struct ether_header)" may not give the right
|
||||||
|
* answer.
|
||||||
|
*/
|
||||||
|
#define ETHER_HDRLEN 14
|
122
aux/adtrace/ethertype.h
Normal file
122
aux/adtrace/ethertype.h
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1993, 1994, 1996
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that: (1) source code distributions
|
||||||
|
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||||
|
* distributions including binary code include the above copyright notice and
|
||||||
|
* this paragraph in its entirety in the documentation or other materials
|
||||||
|
* provided with the distribution, and (3) all advertising materials mentioning
|
||||||
|
* features or use of this software display the following acknowledgement:
|
||||||
|
* ``This product includes software developed by the University of California,
|
||||||
|
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
|
||||||
|
* the University nor the names of its contributors may be used to endorse
|
||||||
|
* or promote products derived from this software without specific prior
|
||||||
|
* written permission.
|
||||||
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* @(#) $Header$ (LBL)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ethernet types.
|
||||||
|
*
|
||||||
|
* We wrap the declarations with #ifdef, so that if a file includes
|
||||||
|
* <netinet/if_ether.h>, which may declare some of these, we don't
|
||||||
|
* get a bunch of complaints from the C compiler about redefinitions
|
||||||
|
* of these values.
|
||||||
|
*
|
||||||
|
* We declare all of them here so that no file has to include
|
||||||
|
* <netinet/if_ether.h> if all it needs are ETHERTYPE_ values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ETHERTYPE_PUP
|
||||||
|
#define ETHERTYPE_PUP 0x0200 /* PUP protocol */
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_IP
|
||||||
|
#define ETHERTYPE_IP 0x0800 /* IP protocol */
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_ARP
|
||||||
|
#define ETHERTYPE_ARP 0x0806 /* Addr. resolution protocol */
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_REVARP
|
||||||
|
#define ETHERTYPE_REVARP 0x8035 /* reverse Addr. resolution protocol */
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_NS
|
||||||
|
#define ETHERTYPE_NS 0x0600
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_SPRITE
|
||||||
|
#define ETHERTYPE_SPRITE 0x0500
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_TRAIL
|
||||||
|
#define ETHERTYPE_TRAIL 0x1000
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_MOPDL
|
||||||
|
#define ETHERTYPE_MOPDL 0x6001
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_MOPRC
|
||||||
|
#define ETHERTYPE_MOPRC 0x6002
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_DN
|
||||||
|
#define ETHERTYPE_DN 0x6003
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_LAT
|
||||||
|
#define ETHERTYPE_LAT 0x6004
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_SCA
|
||||||
|
#define ETHERTYPE_SCA 0x6007
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_REVARP
|
||||||
|
#define ETHERTYPE_REVARP 0x8035
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_LANBRIDGE
|
||||||
|
#define ETHERTYPE_LANBRIDGE 0x8038
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_DECDNS
|
||||||
|
#define ETHERTYPE_DECDNS 0x803c
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_DECDTS
|
||||||
|
#define ETHERTYPE_DECDTS 0x803e
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_VEXP
|
||||||
|
#define ETHERTYPE_VEXP 0x805b
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_VPROD
|
||||||
|
#define ETHERTYPE_VPROD 0x805c
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_ATALK
|
||||||
|
#define ETHERTYPE_ATALK 0x809b
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_AARP
|
||||||
|
#define ETHERTYPE_AARP 0x80f3
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_8021Q
|
||||||
|
#define ETHERTYPE_8021Q 0x8100
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_IPX
|
||||||
|
#define ETHERTYPE_IPX 0x8137
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_IPV6
|
||||||
|
#define ETHERTYPE_IPV6 0x86dd
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_PPP
|
||||||
|
#define ETHERTYPE_PPP 0x880b
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_MPLS
|
||||||
|
#define ETHERTYPE_MPLS 0x8847
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_MPLS_MULTI
|
||||||
|
#define ETHERTYPE_MPLS_MULTI 0x8848
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_PPPOED
|
||||||
|
#define ETHERTYPE_PPPOED 0x8863
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_PPPOES
|
||||||
|
#define ETHERTYPE_PPPOES 0x8864
|
||||||
|
#endif
|
||||||
|
#ifndef ETHERTYPE_LOOPBACK
|
||||||
|
#define ETHERTYPE_LOOPBACK 0x9000
|
||||||
|
#endif
|
159
aux/adtrace/ip.h
Normal file
159
aux/adtrace/ip.h
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/* @(#) $Header$ (LBL) */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1982, 1986, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)ip.h 8.2 (Berkeley) 6/1/94
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for internet protocol version 4.
|
||||||
|
* Per RFC 791, September 1981.
|
||||||
|
*/
|
||||||
|
#define IPVERSION 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure of an internet header, naked of options.
|
||||||
|
*
|
||||||
|
* We declare ip_len and ip_off to be short, rather than u_short
|
||||||
|
* pragmatically since otherwise unsigned comparisons can result
|
||||||
|
* against negative integers quite easily, and fail in subtle ways.
|
||||||
|
*/
|
||||||
|
struct ip {
|
||||||
|
u_int8_t ip_vhl; /* header length, version */
|
||||||
|
#define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4)
|
||||||
|
#define IP_HL(ip) ((ip)->ip_vhl & 0x0f)
|
||||||
|
u_int8_t ip_tos; /* type of service */
|
||||||
|
u_int16_t ip_len; /* total length */
|
||||||
|
u_int16_t ip_id; /* identification */
|
||||||
|
u_int16_t ip_off; /* fragment offset field */
|
||||||
|
#define IP_DF 0x4000 /* dont fragment flag */
|
||||||
|
#define IP_MF 0x2000 /* more fragments flag */
|
||||||
|
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||||
|
u_int8_t ip_ttl; /* time to live */
|
||||||
|
u_int8_t ip_p; /* protocol */
|
||||||
|
u_int16_t ip_sum; /* checksum */
|
||||||
|
struct in_addr ip_src,ip_dst; /* source and dest address */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IP_MAXPACKET 65535 /* maximum packet size */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for IP type of service (ip_tos)
|
||||||
|
*/
|
||||||
|
#define IPTOS_LOWDELAY 0x10
|
||||||
|
#define IPTOS_THROUGHPUT 0x08
|
||||||
|
#define IPTOS_RELIABILITY 0x04
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for IP precedence (also in ip_tos) (hopefully unused)
|
||||||
|
*/
|
||||||
|
#define IPTOS_PREC_NETCONTROL 0xe0
|
||||||
|
#define IPTOS_PREC_INTERNETCONTROL 0xc0
|
||||||
|
#define IPTOS_PREC_CRITIC_ECP 0xa0
|
||||||
|
#define IPTOS_PREC_FLASHOVERRIDE 0x80
|
||||||
|
#define IPTOS_PREC_FLASH 0x60
|
||||||
|
#define IPTOS_PREC_IMMEDIATE 0x40
|
||||||
|
#define IPTOS_PREC_PRIORITY 0x20
|
||||||
|
#define IPTOS_PREC_ROUTINE 0x00
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Definitions for options.
|
||||||
|
*/
|
||||||
|
#define IPOPT_COPIED(o) ((o)&0x80)
|
||||||
|
#define IPOPT_CLASS(o) ((o)&0x60)
|
||||||
|
#define IPOPT_NUMBER(o) ((o)&0x1f)
|
||||||
|
|
||||||
|
#define IPOPT_CONTROL 0x00
|
||||||
|
#define IPOPT_RESERVED1 0x20
|
||||||
|
#define IPOPT_DEBMEAS 0x40
|
||||||
|
#define IPOPT_RESERVED2 0x60
|
||||||
|
|
||||||
|
#define IPOPT_EOL 0 /* end of option list */
|
||||||
|
#define IPOPT_NOP 1 /* no operation */
|
||||||
|
|
||||||
|
#define IPOPT_RR 7 /* record packet route */
|
||||||
|
#define IPOPT_TS 68 /* timestamp */
|
||||||
|
#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
|
||||||
|
#define IPOPT_LSRR 131 /* loose source route */
|
||||||
|
#define IPOPT_SATID 136 /* satnet id */
|
||||||
|
#define IPOPT_SSRR 137 /* strict source route */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Offsets to fields in options other than EOL and NOP.
|
||||||
|
*/
|
||||||
|
#define IPOPT_OPTVAL 0 /* option ID */
|
||||||
|
#define IPOPT_OLEN 1 /* option length */
|
||||||
|
#define IPOPT_OFFSET 2 /* offset within option */
|
||||||
|
#define IPOPT_MINOFF 4 /* min value of above */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Time stamp option structure.
|
||||||
|
*/
|
||||||
|
struct ip_timestamp {
|
||||||
|
u_int8_t ipt_code; /* IPOPT_TS */
|
||||||
|
u_int8_t ipt_len; /* size of structure (variable) */
|
||||||
|
u_int8_t ipt_ptr; /* index of current entry */
|
||||||
|
u_int8_t ipt_oflwflg; /* flags, overflow counter */
|
||||||
|
#define IPTS_OFLW(ip) (((ipt)->ipt_oflwflg & 0xf0) >> 4)
|
||||||
|
#define IPTS_FLG(ip) ((ipt)->ipt_oflwflg & 0x0f)
|
||||||
|
union ipt_timestamp {
|
||||||
|
u_int32_t ipt_time[1];
|
||||||
|
struct ipt_ta {
|
||||||
|
struct in_addr ipt_addr;
|
||||||
|
u_int32_t ipt_time;
|
||||||
|
} ipt_ta[1];
|
||||||
|
} ipt_timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flag bits for ipt_flg */
|
||||||
|
#define IPOPT_TS_TSONLY 0 /* timestamps only */
|
||||||
|
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
|
||||||
|
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
|
||||||
|
|
||||||
|
/* bits for security (not byte swapped) */
|
||||||
|
#define IPOPT_SECUR_UNCLASS 0x0000
|
||||||
|
#define IPOPT_SECUR_CONFID 0xf135
|
||||||
|
#define IPOPT_SECUR_EFTO 0x789a
|
||||||
|
#define IPOPT_SECUR_MMMM 0xbc4d
|
||||||
|
#define IPOPT_SECUR_RESTR 0xaf13
|
||||||
|
#define IPOPT_SECUR_SECRET 0xd788
|
||||||
|
#define IPOPT_SECUR_TOPSECRET 0x6bc5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internet implementation parameters.
|
||||||
|
*/
|
||||||
|
#define MAXTTL 255 /* maximum time to live (seconds) */
|
||||||
|
#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
|
||||||
|
#define IPFRAGTTL 60 /* time to live for frags, slowhz */
|
||||||
|
#define IPTTLDEC 1 /* subtracted when forwarding */
|
||||||
|
|
||||||
|
#define IP_MSS 576 /* default maximum segment size */
|
4
aux/bdcat/Makefile.am
Normal file
4
aux/bdcat/Makefile.am
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
noinst_PROGRAMS = bdcat
|
||||||
|
bdcat_SOURCES = bdcat.cc
|
175
aux/bdcat/bdcat.cc
Normal file
175
aux/bdcat/bdcat.cc
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
// $Id: bdcat.cc 6 2004-04-30 00:31:26Z jason $
|
||||||
|
//
|
||||||
|
// Decrypts Bro's log files.
|
||||||
|
//
|
||||||
|
// Usage: bdcat [-k file-with-secret-rsa-key] [files...]
|
||||||
|
//
|
||||||
|
// The key file may be alternatively set via the env variable BDCAT_KEY.
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include "openssl/evp.h"
|
||||||
|
#include "openssl/pem.h"
|
||||||
|
#include "openssl/err.h"
|
||||||
|
|
||||||
|
EVP_PKEY* SecKey = 0;
|
||||||
|
EVP_CIPHER* CipherType = 0;
|
||||||
|
|
||||||
|
void cryptcat(FILE* f)
|
||||||
|
{
|
||||||
|
unsigned char magic[7];
|
||||||
|
unsigned long secret_len;
|
||||||
|
|
||||||
|
// Read file header.
|
||||||
|
if ( ! (fread(&magic, 7, 1, f) &&
|
||||||
|
fread(&secret_len, sizeof(secret_len), 1, f)) )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "can't read file header: %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( memcmp("BROENC1", (const char*) magic, 7) != 0 )
|
||||||
|
{
|
||||||
|
fputs("not a Bro encrypted file\n", stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
secret_len = ntohl(secret_len);
|
||||||
|
int iv_len = EVP_CIPHER_iv_length(CipherType);
|
||||||
|
unsigned char secret[secret_len];
|
||||||
|
unsigned char iv[iv_len];
|
||||||
|
|
||||||
|
if ( ! (fread(&secret, secret_len, 1, f) &&
|
||||||
|
fread(&iv, iv_len, 1, f)) )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "can't read file header: %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt data.
|
||||||
|
EVP_CIPHER_CTX cipher_ctx;
|
||||||
|
if ( ! EVP_OpenInit(&cipher_ctx, CipherType,
|
||||||
|
secret, secret_len, iv, SecKey) )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "can't init decryption: %s\n",
|
||||||
|
ERR_error_string(ERR_get_error(), 0));
|
||||||
|
exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int block_size = EVP_CIPHER_block_size(CipherType);
|
||||||
|
unsigned char buffer_in[block_size];
|
||||||
|
unsigned char buffer_out[block_size];
|
||||||
|
|
||||||
|
int inl, outl;
|
||||||
|
while ( (inl = fread(buffer_in, 1, block_size, f)) )
|
||||||
|
{
|
||||||
|
if ( ! EVP_OpenUpdate(&cipher_ctx, buffer_out,
|
||||||
|
&outl, buffer_in, inl) )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "can't decrypt: %s\n",
|
||||||
|
ERR_error_string(ERR_get_error(), 0));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( outl && ! fwrite(buffer_out, outl, 1, stdout) )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "can't write to stdout: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! EVP_OpenFinal(&cipher_ctx, buffer_out, &outl) )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "can't decrypt: %s\n",
|
||||||
|
ERR_error_string(ERR_get_error(), 0));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( outl && ! fwrite(buffer_out, outl, 1, stdout) )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "can't write to stdout: %s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "bdcat [-k <sec-key-file>] [files]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
char* keyfile = getenv("BDCAT_KEY");
|
||||||
|
|
||||||
|
// Read options.
|
||||||
|
char op;
|
||||||
|
while ( (op = getopt(argc, argv, "k:")) >= 0 )
|
||||||
|
{
|
||||||
|
if ( op == 'k' )
|
||||||
|
keyfile = optarg;
|
||||||
|
else
|
||||||
|
Usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! keyfile )
|
||||||
|
{
|
||||||
|
fputs("no keyfile given\n", stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init crypto.
|
||||||
|
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
|
||||||
|
FILE* f = fopen(keyfile, "r");
|
||||||
|
if ( ! f )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "can't open key file %s: %s\n",
|
||||||
|
keyfile, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SecKey = PEM_read_PrivateKey(f, 0, 0, 0);
|
||||||
|
if ( ! SecKey )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "can't read key from %s: %s\n", keyfile,
|
||||||
|
ERR_error_string(ERR_get_error(), 0));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
// Depending on the OpenSSL version, EVP_*_cbc()
|
||||||
|
// returns a const or a non-const.
|
||||||
|
CipherType = (EVP_CIPHER*) EVP_bf_cbc();
|
||||||
|
|
||||||
|
// Decrypt the files.
|
||||||
|
if ( optind == argc )
|
||||||
|
cryptcat(stdin);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while ( optind < argc )
|
||||||
|
{
|
||||||
|
FILE* f = fopen(argv[optind], "r");
|
||||||
|
if ( ! f )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "can't open %s: %s\n",
|
||||||
|
argv[optind], strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
cryptcat(f);
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
0
aux/binpac/AUTHORS
Normal file
0
aux/binpac/AUTHORS
Normal file
0
aux/binpac/CHANGES
Normal file
0
aux/binpac/CHANGES
Normal file
18
aux/binpac/COPYING
Normal file
18
aux/binpac/COPYING
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright (c) 1995-2007
|
||||||
|
// The Regents of the University of California. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that: (1) source code distributions
|
||||||
|
// retain the above copyright notice and this paragraph in its entirety, (2)
|
||||||
|
// distributions including binary code include the above copyright notice and
|
||||||
|
// this paragraph in its entirety in the documentation or other materials
|
||||||
|
// provided with the distribution, and (3) all advertising materials mentioning
|
||||||
|
// features or use of this software display the following acknowledgement:
|
||||||
|
// ``This product includes software developed by the University of California,
|
||||||
|
// Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
|
||||||
|
// the University nor the names of its contributors may be used to endorse
|
||||||
|
// or promote products derived from this software without specific prior
|
||||||
|
// written permission.
|
||||||
|
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
0
aux/binpac/ChangeLog
Normal file
0
aux/binpac/ChangeLog
Normal file
231
aux/binpac/INSTALL
Normal file
231
aux/binpac/INSTALL
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
Installation Instructions
|
||||||
|
*************************
|
||||||
|
|
||||||
|
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
|
||||||
|
Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is free documentation; the Free Software Foundation gives
|
||||||
|
unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
|
Basic Installation
|
||||||
|
==================
|
||||||
|
|
||||||
|
These are generic installation instructions.
|
||||||
|
|
||||||
|
The `configure' shell script attempts to guess correct values for
|
||||||
|
various system-dependent variables used during compilation. It uses
|
||||||
|
those values to create a `Makefile' in each directory of the package.
|
||||||
|
It may also create one or more `.h' files containing system-dependent
|
||||||
|
definitions. Finally, it creates a shell script `config.status' that
|
||||||
|
you can run in the future to recreate the current configuration, and a
|
||||||
|
file `config.log' containing compiler output (useful mainly for
|
||||||
|
debugging `configure').
|
||||||
|
|
||||||
|
It can also use an optional file (typically called `config.cache'
|
||||||
|
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||||
|
the results of its tests to speed up reconfiguring. (Caching is
|
||||||
|
disabled by default to prevent problems with accidental use of stale
|
||||||
|
cache files.)
|
||||||
|
|
||||||
|
If you need to do unusual things to compile the package, please try
|
||||||
|
to figure out how `configure' could check whether to do them, and mail
|
||||||
|
diffs or instructions to the address given in the `README' so they can
|
||||||
|
be considered for the next release. If you are using the cache, and at
|
||||||
|
some point `config.cache' contains results you don't want to keep, you
|
||||||
|
may remove or edit it.
|
||||||
|
|
||||||
|
The file `configure.ac' (or `configure.in') is used to create
|
||||||
|
`configure' by a program called `autoconf'. You only need
|
||||||
|
`configure.ac' if you want to change it or regenerate `configure' using
|
||||||
|
a newer version of `autoconf'.
|
||||||
|
|
||||||
|
The simplest way to compile this package is:
|
||||||
|
|
||||||
|
1. `cd' to the directory containing the package's source code and type
|
||||||
|
`./configure' to configure the package for your system. If you're
|
||||||
|
using `csh' on an old version of System V, you might need to type
|
||||||
|
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||||
|
`configure' itself.
|
||||||
|
|
||||||
|
Running `configure' takes awhile. While running, it prints some
|
||||||
|
messages telling which features it is checking for.
|
||||||
|
|
||||||
|
2. Type `make' to compile the package.
|
||||||
|
|
||||||
|
3. Optionally, type `make check' to run any self-tests that come with
|
||||||
|
the package.
|
||||||
|
|
||||||
|
4. Type `make install' to install the programs and any data files and
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
5. You can remove the program binaries and object files from the
|
||||||
|
source code directory by typing `make clean'. To also remove the
|
||||||
|
files that `configure' created (so you can compile the package for
|
||||||
|
a different kind of computer), type `make distclean'. There is
|
||||||
|
also a `make maintainer-clean' target, but that is intended mainly
|
||||||
|
for the package's developers. If you use it, you may have to get
|
||||||
|
all sorts of other programs in order to regenerate files that came
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
Compilers and Options
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Some systems require unusual options for compilation or linking that the
|
||||||
|
`configure' script does not know about. Run `./configure --help' for
|
||||||
|
details on some of the pertinent environment variables.
|
||||||
|
|
||||||
|
You can give `configure' initial values for configuration parameters
|
||||||
|
by setting variables in the command line or in the environment. Here
|
||||||
|
is an example:
|
||||||
|
|
||||||
|
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||||
|
|
||||||
|
*Note Defining Variables::, for more details.
|
||||||
|
|
||||||
|
Compiling For Multiple Architectures
|
||||||
|
====================================
|
||||||
|
|
||||||
|
You can compile the package for more than one kind of computer at the
|
||||||
|
same time, by placing the object files for each architecture in their
|
||||||
|
own directory. To do this, you must use a version of `make' that
|
||||||
|
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||||
|
directory where you want the object files and executables to go and run
|
||||||
|
the `configure' script. `configure' automatically checks for the
|
||||||
|
source code in the directory that `configure' is in and in `..'.
|
||||||
|
|
||||||
|
If you have to use a `make' that does not support the `VPATH'
|
||||||
|
variable, you have to compile the package for one architecture at a
|
||||||
|
time in the source code directory. After you have installed the
|
||||||
|
package for one architecture, use `make distclean' before reconfiguring
|
||||||
|
for another architecture.
|
||||||
|
|
||||||
|
Installation Names
|
||||||
|
==================
|
||||||
|
|
||||||
|
By default, `make install' will install the package's files in
|
||||||
|
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||||
|
installation prefix other than `/usr/local' by giving `configure' the
|
||||||
|
option `--prefix=PREFIX'.
|
||||||
|
|
||||||
|
You can specify separate installation prefixes for
|
||||||
|
architecture-specific files and architecture-independent files. If you
|
||||||
|
give `configure' the option `--exec-prefix=PREFIX', the package will
|
||||||
|
use PREFIX as the prefix for installing programs and libraries.
|
||||||
|
Documentation and other data files will still use the regular prefix.
|
||||||
|
|
||||||
|
In addition, if you use an unusual directory layout you can give
|
||||||
|
options like `--bindir=DIR' to specify different values for particular
|
||||||
|
kinds of files. Run `configure --help' for a list of the directories
|
||||||
|
you can set and what kinds of files go in them.
|
||||||
|
|
||||||
|
If the package supports it, you can cause programs to be installed
|
||||||
|
with an extra prefix or suffix on their names by giving `configure' the
|
||||||
|
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||||
|
|
||||||
|
Optional Features
|
||||||
|
=================
|
||||||
|
|
||||||
|
Some packages pay attention to `--enable-FEATURE' options to
|
||||||
|
`configure', where FEATURE indicates an optional part of the package.
|
||||||
|
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||||
|
is something like `gnu-as' or `x' (for the X Window System). The
|
||||||
|
`README' should mention any `--enable-' and `--with-' options that the
|
||||||
|
package recognizes.
|
||||||
|
|
||||||
|
For packages that use the X Window System, `configure' can usually
|
||||||
|
find the X include and library files automatically, but if it doesn't,
|
||||||
|
you can use the `configure' options `--x-includes=DIR' and
|
||||||
|
`--x-libraries=DIR' to specify their locations.
|
||||||
|
|
||||||
|
Specifying the System Type
|
||||||
|
==========================
|
||||||
|
|
||||||
|
There may be some features `configure' cannot figure out automatically,
|
||||||
|
but needs to determine by the type of machine the package will run on.
|
||||||
|
Usually, assuming the package is built to be run on the _same_
|
||||||
|
architectures, `configure' can figure that out, but if it prints a
|
||||||
|
message saying it cannot guess the machine type, give it the
|
||||||
|
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||||
|
type, such as `sun4', or a canonical name which has the form:
|
||||||
|
|
||||||
|
CPU-COMPANY-SYSTEM
|
||||||
|
|
||||||
|
where SYSTEM can have one of these forms:
|
||||||
|
|
||||||
|
OS KERNEL-OS
|
||||||
|
|
||||||
|
See the file `config.sub' for the possible values of each field. If
|
||||||
|
`config.sub' isn't included in this package, then this package doesn't
|
||||||
|
need to know the machine type.
|
||||||
|
|
||||||
|
If you are _building_ compiler tools for cross-compiling, you should
|
||||||
|
use the `--target=TYPE' option to select the type of system they will
|
||||||
|
produce code for.
|
||||||
|
|
||||||
|
If you want to _use_ a cross compiler, that generates code for a
|
||||||
|
platform different from the build platform, you should specify the
|
||||||
|
"host" platform (i.e., that on which the generated programs will
|
||||||
|
eventually be run) with `--host=TYPE'.
|
||||||
|
|
||||||
|
Sharing Defaults
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to set default values for `configure' scripts to share, you
|
||||||
|
can create a site shell script called `config.site' that gives default
|
||||||
|
values for variables like `CC', `cache_file', and `prefix'.
|
||||||
|
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||||
|
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||||
|
`CONFIG_SITE' environment variable to the location of the site script.
|
||||||
|
A warning: not all `configure' scripts look for a site script.
|
||||||
|
|
||||||
|
Defining Variables
|
||||||
|
==================
|
||||||
|
|
||||||
|
Variables not defined in a site shell script can be set in the
|
||||||
|
environment passed to `configure'. However, some packages may run
|
||||||
|
configure again during the build, and the customized values of these
|
||||||
|
variables may be lost. In order to avoid this problem, you should set
|
||||||
|
them in the `configure' command line, using `VAR=value'. For example:
|
||||||
|
|
||||||
|
./configure CC=/usr/local2/bin/gcc
|
||||||
|
|
||||||
|
will cause the specified gcc to be used as the C compiler (unless it is
|
||||||
|
overridden in the site shell script).
|
||||||
|
|
||||||
|
`configure' Invocation
|
||||||
|
======================
|
||||||
|
|
||||||
|
`configure' recognizes the following options to control how it operates.
|
||||||
|
|
||||||
|
`--help'
|
||||||
|
`-h'
|
||||||
|
Print a summary of the options to `configure', and exit.
|
||||||
|
|
||||||
|
`--version'
|
||||||
|
`-V'
|
||||||
|
Print the version of Autoconf used to generate the `configure'
|
||||||
|
script, and exit.
|
||||||
|
|
||||||
|
`--cache-file=FILE'
|
||||||
|
Enable the cache: use and save the results of the tests in FILE,
|
||||||
|
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||||
|
disable caching.
|
||||||
|
|
||||||
|
`--config-cache'
|
||||||
|
`-C'
|
||||||
|
Alias for `--cache-file=config.cache'.
|
||||||
|
|
||||||
|
`--quiet'
|
||||||
|
`--silent'
|
||||||
|
`-q'
|
||||||
|
Do not print messages saying which checks are being made. To
|
||||||
|
suppress all normal output, redirect it to `/dev/null' (any error
|
||||||
|
messages will still be shown).
|
||||||
|
|
||||||
|
`--srcdir=DIR'
|
||||||
|
Look for the package's source code in directory DIR. Usually
|
||||||
|
`configure' can determine that directory automatically.
|
||||||
|
|
||||||
|
`configure' also accepts some other, not widely useful, options. Run
|
||||||
|
`configure --help' for more details.
|
||||||
|
|
4
aux/binpac/Makefile.am
Normal file
4
aux/binpac/Makefile.am
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
EXTRA_DIST = README VERSION CHANGES TODO depcomp shtool autogen.sh
|
||||||
|
SUBDIRS = lib src
|
0
aux/binpac/NEWS
Normal file
0
aux/binpac/NEWS
Normal file
0
aux/binpac/README
Normal file
0
aux/binpac/README
Normal file
34
aux/binpac/TODO
Normal file
34
aux/binpac/TODO
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
Big features
|
||||||
|
* Variable context (xid, call in RPC)? -- no variable context
|
||||||
|
* Helpers
|
||||||
|
* Connection states and actions
|
||||||
|
* Case and analyzer redef
|
||||||
|
* &also withinput
|
||||||
|
* Explicit analyzer context (interface + instantiation) "withcontext"
|
||||||
|
+ Interface with C++ and Bro (events, extern, weird)
|
||||||
|
+ Incremental input
|
||||||
|
+ ASCII protocols
|
||||||
|
+ Reassembly
|
||||||
|
- Dealing with exceptions
|
||||||
|
- Dependency analysis to save parsing time on unused fields
|
||||||
|
- Performance measurement
|
||||||
|
|
||||||
|
Small features
|
||||||
|
* Restructure the code: break up pac.{h,cc}
|
||||||
|
* ref counting (to keep certain structures)
|
||||||
|
* analyzer context as a parameter of class
|
||||||
|
* &autolength
|
||||||
|
* find a better name for "analyzer_context" ("analcxt", "context", "analyzer") $context
|
||||||
|
* &if
|
||||||
|
* &autolength (now &restofdata)
|
||||||
|
* Use vector<> instead of array<>?
|
||||||
|
* set end_of_data when &length = ...
|
||||||
|
- make the `default' case mandatory?
|
||||||
|
- &inline
|
||||||
|
- &warn and &check? (follow &if)
|
||||||
|
- typedef?
|
||||||
|
|
||||||
|
Binpac 1
|
||||||
|
- create a namespace for each .pac file
|
||||||
|
- type equivalence
|
||||||
|
- byteorder() for every type?
|
1
aux/binpac/VERSION
Normal file
1
aux/binpac/VERSION
Normal file
|
@ -0,0 +1 @@
|
||||||
|
0.1
|
114
aux/binpac/autogen.sh
Executable file
114
aux/binpac/autogen.sh
Executable file
|
@ -0,0 +1,114 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Initialization script to set up the initial configuration files etc.
|
||||||
|
# shtool usage inspired by the autogen script of the ferite scripting
|
||||||
|
# language -- cheers Chris :)
|
||||||
|
#
|
||||||
|
# This is 'borrowed' from netdude, with minor changes for bro
|
||||||
|
|
||||||
|
BLD_ON=`./shtool echo -n -e %B`
|
||||||
|
BLD_OFF=`./shtool echo -n -e %b`
|
||||||
|
|
||||||
|
srcdir=`dirname $0`
|
||||||
|
NAME=binpac
|
||||||
|
|
||||||
|
DIE=0
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo " "${BLD_ON}"Binpac Build Tools Setup"${BLD_OFF}
|
||||||
|
echo "===================================================="
|
||||||
|
echo
|
||||||
|
echo "Checking whether we have all tools available ..."
|
||||||
|
|
||||||
|
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
|
echo
|
||||||
|
echo ${BLD_ON}"Error"${BLD_OFF}": You must have \`autoconf' installed to."
|
||||||
|
echo "Download the appropriate package for your distribution,"
|
||||||
|
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||||
|
DIE=1
|
||||||
|
}
|
||||||
|
|
||||||
|
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
|
echo
|
||||||
|
echo ${BLD_ON}"Error"${BLD_OFF}": You must have \`automake' installed."
|
||||||
|
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||||
|
echo "(or a newer version if it is available)"
|
||||||
|
DIE=1
|
||||||
|
NO_AUTOMAKE=yes
|
||||||
|
}
|
||||||
|
|
||||||
|
# if no automake, don't bother testing for aclocal
|
||||||
|
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
|
echo
|
||||||
|
echo ${BLD_ON}"Error"${BLD_OFF}": Missing \`aclocal'. The version of \`automake'"
|
||||||
|
echo "installed doesn't appear recent enough."
|
||||||
|
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||||
|
echo "(or a newer version if it is available)"
|
||||||
|
DIE=1
|
||||||
|
}
|
||||||
|
|
||||||
|
if test "$DIE" -eq 1; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "All necessary tools found."
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [ -d autom4te.cache ] ; then
|
||||||
|
echo "Removing autom4te.cache ..."
|
||||||
|
rm -rf autom4te.cache
|
||||||
|
#echo
|
||||||
|
#echo ${BLD_ON}"Error"${BLD_OFF}": autom4te.cache directory exists"
|
||||||
|
#echo "please remove it, and rerun this script"
|
||||||
|
#echo
|
||||||
|
#exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "running "${BLD_ON}"aclocal"${BLD_OFF}
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
aclocal -I . $ACLOCAL_FLAGS
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "running "${BLD_ON}"autoheader"${BLD_OFF}
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
autoheader
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "running "${BLD_ON}"automake"${BLD_OFF}
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
automake -a -c
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "running "${BLD_ON}"autoconf"${BLD_OFF}
|
||||||
|
echo "----------------------------------------------------"
|
||||||
|
autoconf
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "*** ERROR($NAME), aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! test "x$BROBUILD" = xyes; then
|
||||||
|
echo
|
||||||
|
echo "Setup finished. Now run:"
|
||||||
|
echo
|
||||||
|
echo " $ "${BLD_ON}"./configure"${BLD_OFF}" (with options as needed, try --help)"
|
||||||
|
echo
|
||||||
|
echo "and then"
|
||||||
|
echo
|
||||||
|
echo " $ "${BLD_ON}"make"${BLD_OFF}
|
||||||
|
echo " # "${BLD_ON}"make install"${BLD_OFF}
|
||||||
|
echo
|
||||||
|
fi
|
55
aux/binpac/configure.in
Normal file
55
aux/binpac/configure.in
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
AC_INIT
|
||||||
|
AC_CONFIG_SRCDIR([src/pac_main.cc])
|
||||||
|
|
||||||
|
AC_CANONICAL_SYSTEM
|
||||||
|
|
||||||
|
AC_CONFIG_AUX_DIR(.)
|
||||||
|
AM_CONFIG_HEADER(config.h)
|
||||||
|
AM_INIT_AUTOMAKE(binpac, esyscmd([tr -d '\n' < VERSION]))
|
||||||
|
|
||||||
|
dnl Commands for funkier shell output:
|
||||||
|
BLD_ON=`./shtool echo -n -e %B`
|
||||||
|
BLD_OFF=`./shtool echo -n -e %b`
|
||||||
|
|
||||||
|
dnl ################################################
|
||||||
|
dnl # Checks for programs
|
||||||
|
dnl ################################################
|
||||||
|
AM_PROG_LEX
|
||||||
|
AC_PROG_YACC
|
||||||
|
AC_PROG_CXX
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
|
||||||
|
m4_ifdef([AC_COMPUTE_INT], [], [AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])])])
|
||||||
|
|
||||||
|
AC_COMPUTE_INT([SIZEOF_UNSIGNED_INT], [sizeof(unsigned int)])
|
||||||
|
AC_SUBST(SIZEOF_UNSIGNED_INT)
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(debug,
|
||||||
|
[ --enable-debug no compiler optimizations],
|
||||||
|
debug="yes"
|
||||||
|
CFLAGS="-DDEBUG `echo $CFLAGS | sed -e 's/-O2//'`"
|
||||||
|
CXXFLAGS="-DDEBUG `echo $CXXFLAGS | sed -e 's/-O2//'`",
|
||||||
|
debug="no")
|
||||||
|
|
||||||
|
AC_C_BIGENDIAN(
|
||||||
|
AC_DEFINE(WORDS_BIGENDIAN,1,[whether words are stored with the most significant byte first])
|
||||||
|
dnl This is intentionally named differently so as to not collide with WORDS_BIGENDIAN
|
||||||
|
HOST_BIGENDIAN="#define HOST_BIGENDIAN 1"
|
||||||
|
AC_SUBST(HOST_BIGENDIAN))
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([
|
||||||
|
Makefile
|
||||||
|
src/Makefile
|
||||||
|
lib/Makefile
|
||||||
|
lib/binpac.h
|
||||||
|
])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo " "${BLD_ON}"Binpac Configuration Summary"${BLD_OFF}
|
||||||
|
echo "=========================================================="
|
||||||
|
echo
|
||||||
|
echo " - Debugging enabled: "${BLD_ON}$debug${BLD_OFF}
|
||||||
|
echo
|
||||||
|
exit 0
|
8
aux/binpac/lib/Makefile.am
Normal file
8
aux/binpac/lib/Makefile.am
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
noinst_LIBRARIES = libbinpac.a
|
||||||
|
|
||||||
|
libbinpac_a_SOURCES = \
|
||||||
|
binpac_buffer.cc binpac_bytestring.cc \
|
||||||
|
binpac.h binpac_analyzer.h binpac_buffer.h \
|
||||||
|
binpac_bytestring.h binpac_exception.h binpac_regex.h
|
3
aux/binpac/lib/README
Normal file
3
aux/binpac/lib/README
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
This directory contains a library needed by generated C++ code from
|
||||||
|
binpac. Note that the library is not needed by the binpac compiler
|
||||||
|
itself.
|
142
aux/binpac/lib/binpac.h.in
Normal file
142
aux/binpac/lib/binpac.h.in
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
// $Id: binpac.h,v 1.1.4.2 2006/06/02 15:13:13 rpang Exp $
|
||||||
|
// Do not edit binpac.h, edit binpac.h.in instead!
|
||||||
|
|
||||||
|
#ifndef binpac_h
|
||||||
|
#define binpac_h
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
@HOST_BIGENDIAN@
|
||||||
|
#ifdef HOST_BIGENDIAN
|
||||||
|
# define HOST_BYTEORDER bigendian
|
||||||
|
#else
|
||||||
|
# define HOST_BYTEORDER littleendian
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#define BINPAC_ASSERT(x) assert(x)
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace binpac {
|
||||||
|
|
||||||
|
const int bigendian = 0;
|
||||||
|
const int littleendian = 1;
|
||||||
|
const int unspecified_byteorder = -1;
|
||||||
|
|
||||||
|
#ifndef pac_type_defs
|
||||||
|
#define pac_type_defs
|
||||||
|
|
||||||
|
typedef char int8;
|
||||||
|
typedef short int16;
|
||||||
|
typedef long int32;
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef void *nullptr;
|
||||||
|
typedef void *voidptr;
|
||||||
|
typedef uint8 *byteptr;
|
||||||
|
typedef const uint8 *const_byteptr;
|
||||||
|
typedef const char *const_charptr;
|
||||||
|
|
||||||
|
#if @SIZEOF_UNSIGNED_INT@ != 4
|
||||||
|
#error "unexpected size of unsigned int"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* pac_type_defs */
|
||||||
|
|
||||||
|
/* Handling byte order */
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
inline int16 pac_swap(int16 x)
|
||||||
|
{
|
||||||
|
return (x >> 8) | ((x & 0xff) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16 pac_swap(uint16 x)
|
||||||
|
{
|
||||||
|
return (x >> 8) | ((x & 0xff) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32 pac_swap(int32 x)
|
||||||
|
{
|
||||||
|
return (x >> 24) |
|
||||||
|
((x & 0xff0000) >> 8) |
|
||||||
|
((x & 0xff00) << 8) |
|
||||||
|
((x & 0xff) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32 pac_swap(uint32 x)
|
||||||
|
{
|
||||||
|
return (x >> 24) |
|
||||||
|
((x & 0xff0000) >> 8) |
|
||||||
|
((x & 0xff00) << 8) |
|
||||||
|
((x & 0xff) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FixByteOrder(byteorder, x) (byteorder == HOST_BYTEORDER ? (x) : pac_swap(x))
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline T UnMarshall(const u_char *data, int byteorder)
|
||||||
|
{
|
||||||
|
T result = 0;
|
||||||
|
for ( int i = 0; i < (int) sizeof(T); ++i )
|
||||||
|
result = ( result << 8 ) |
|
||||||
|
data[byteorder == bigendian ? i : sizeof(T) - 1 - i];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char* do_fmt(const char* format, va_list ap)
|
||||||
|
{
|
||||||
|
static char buf[1024];
|
||||||
|
vsnprintf(buf, sizeof(buf), format, ap);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string strfmt(const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
const char* r = do_fmt(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return string(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
#define binpac_fmt(x...) strfmt(x).c_str()
|
||||||
|
|
||||||
|
class RefCount
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RefCount() { count = 1; }
|
||||||
|
void Ref() { ++count; }
|
||||||
|
int Unref() { BINPAC_ASSERT(count > 0); return --count; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
inline void Unref(RefCount *x)
|
||||||
|
{
|
||||||
|
if ( x && x->Unref() <= 0 )
|
||||||
|
delete x;
|
||||||
|
}
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
} // namespace binpac
|
||||||
|
|
||||||
|
#include "binpac_analyzer.h"
|
||||||
|
#include "binpac_buffer.h"
|
||||||
|
#include "binpac_bytestring.h"
|
||||||
|
#include "binpac_exception.h"
|
||||||
|
#include "binpac_regex.h"
|
||||||
|
|
||||||
|
#endif /* binpac_h */
|
27
aux/binpac/lib/binpac_analyzer.h
Normal file
27
aux/binpac/lib/binpac_analyzer.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef binpac_an_h
|
||||||
|
#define binpac_an_h
|
||||||
|
|
||||||
|
namespace binpac {
|
||||||
|
|
||||||
|
// TODO: Add the Done() function
|
||||||
|
|
||||||
|
// The interface for a connection analyzer
|
||||||
|
class ConnectionAnalyzer {
|
||||||
|
public:
|
||||||
|
virtual ~ConnectionAnalyzer() {}
|
||||||
|
virtual void NewData(bool is_orig,
|
||||||
|
const u_char *begin_of_data,
|
||||||
|
const u_char *end_of_data) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The interface for a flow analyzer
|
||||||
|
class FlowAnalyzer {
|
||||||
|
public:
|
||||||
|
virtual ~FlowAnalyzer() {}
|
||||||
|
virtual void NewData(const u_char *begin_of_data,
|
||||||
|
const u_char *end_of_data) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace binpac
|
||||||
|
|
||||||
|
#endif // binpac_an_h
|
465
aux/binpac/lib/binpac_buffer.cc
Normal file
465
aux/binpac/lib/binpac_buffer.cc
Normal file
|
@ -0,0 +1,465 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h> // for memcpy
|
||||||
|
|
||||||
|
#define binpac_regex_h
|
||||||
|
|
||||||
|
#include "binpac.h"
|
||||||
|
#include "binpac_buffer.h"
|
||||||
|
|
||||||
|
namespace binpac {
|
||||||
|
|
||||||
|
extern double network_time();
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const u_char CR = '\r';
|
||||||
|
const u_char LF = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style)
|
||||||
|
{
|
||||||
|
buffer_length_ = 0;
|
||||||
|
buffer_ = 0;
|
||||||
|
|
||||||
|
orig_data_begin_ = 0;
|
||||||
|
orig_data_end_ = 0;
|
||||||
|
|
||||||
|
linebreak_style_ = linebreak_style;
|
||||||
|
ResetLineState();
|
||||||
|
|
||||||
|
mode_ = UNKNOWN_MODE;
|
||||||
|
frame_length_ = 0;
|
||||||
|
chunked_ = false;
|
||||||
|
|
||||||
|
data_seq_at_orig_data_end_ = 0;
|
||||||
|
eof_ = false;
|
||||||
|
have_pending_request_ = false;
|
||||||
|
|
||||||
|
buffer_n_ = 0;
|
||||||
|
|
||||||
|
NewMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowBuffer::~FlowBuffer()
|
||||||
|
{
|
||||||
|
if ( buffer_ )
|
||||||
|
free(buffer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::NewMessage()
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(frame_length_ >= 0);
|
||||||
|
|
||||||
|
int bytes_to_advance = 0;
|
||||||
|
if ( buffer_n_ == 0 )
|
||||||
|
{
|
||||||
|
switch ( mode_ )
|
||||||
|
{
|
||||||
|
case LINE_MODE:
|
||||||
|
bytes_to_advance = (frame_length_ +
|
||||||
|
(linebreak_style_ == STRICT_CRLF ?
|
||||||
|
2 : 1));
|
||||||
|
break;
|
||||||
|
case FRAME_MODE:
|
||||||
|
bytes_to_advance = frame_length_;
|
||||||
|
break;
|
||||||
|
case UNKNOWN_MODE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
orig_data_begin_ += bytes_to_advance;
|
||||||
|
BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_);
|
||||||
|
|
||||||
|
buffer_n_ = 0;
|
||||||
|
message_complete_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::ResetLineState()
|
||||||
|
{
|
||||||
|
switch ( linebreak_style_ )
|
||||||
|
{
|
||||||
|
case CR_OR_LF:
|
||||||
|
state_ = CR_OR_LF_0;
|
||||||
|
break;
|
||||||
|
case STRICT_CRLF:
|
||||||
|
state_ = STRICT_CRLF_0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BINPAC_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::ExpandBuffer(int length)
|
||||||
|
{
|
||||||
|
if ( buffer_length_ >= length )
|
||||||
|
return;
|
||||||
|
// So length > 0
|
||||||
|
if ( length < 512 )
|
||||||
|
length = 512;
|
||||||
|
|
||||||
|
if ( length < buffer_length_ * 2 )
|
||||||
|
length = buffer_length_ * 2;
|
||||||
|
|
||||||
|
// Allocate a new buffer and copy the existing contents
|
||||||
|
buffer_length_ = length;
|
||||||
|
u_char *new_buf = (u_char *) realloc(buffer_, buffer_length_);
|
||||||
|
BINPAC_ASSERT(new_buf);
|
||||||
|
#if 0
|
||||||
|
u_char* new_buf = new u_char[buffer_length_];
|
||||||
|
if ( buffer_ && buffer_n_ > 0 )
|
||||||
|
memcpy(new_buf, buffer_, buffer_n_);
|
||||||
|
delete [] buffer_;
|
||||||
|
#endif
|
||||||
|
buffer_ = new_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::NewLine()
|
||||||
|
{
|
||||||
|
FlowBuffer::NewMessage();
|
||||||
|
mode_ = LINE_MODE;
|
||||||
|
frame_length_ = 0;
|
||||||
|
chunked_ = false;
|
||||||
|
have_pending_request_ = true;
|
||||||
|
if ( state_ == FRAME_0 )
|
||||||
|
ResetLineState();
|
||||||
|
MarkOrCopyLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::NewFrame(int frame_length, bool chunked)
|
||||||
|
{
|
||||||
|
FlowBuffer::NewMessage();
|
||||||
|
mode_ = FRAME_MODE;
|
||||||
|
frame_length_ = frame_length;
|
||||||
|
chunked_ = chunked;
|
||||||
|
have_pending_request_ = true;
|
||||||
|
MarkOrCopyFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::GrowFrame(int length)
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(frame_length_ >= 0);
|
||||||
|
if ( length <= frame_length_ )
|
||||||
|
return;
|
||||||
|
BINPAC_ASSERT(! chunked_ || frame_length_ == 0);
|
||||||
|
mode_ = FRAME_MODE;
|
||||||
|
frame_length_ = length;
|
||||||
|
MarkOrCopyFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::DiscardData()
|
||||||
|
{
|
||||||
|
mode_ = UNKNOWN_MODE;
|
||||||
|
message_complete_ = false;
|
||||||
|
have_pending_request_ = false;
|
||||||
|
orig_data_begin_ = orig_data_end_ = 0;
|
||||||
|
|
||||||
|
buffer_n_ = 0;
|
||||||
|
frame_length_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::set_eof()
|
||||||
|
{
|
||||||
|
// fprintf(stderr, "EOF\n");
|
||||||
|
eof_ = true;
|
||||||
|
if ( chunked_ )
|
||||||
|
frame_length_ = orig_data_end_ - orig_data_begin_;
|
||||||
|
if ( frame_length_ < 0 )
|
||||||
|
frame_length_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::NewData(const_byteptr begin, const_byteptr end)
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(begin <= end);
|
||||||
|
|
||||||
|
ClearPreviousData();
|
||||||
|
|
||||||
|
BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) ||
|
||||||
|
orig_data_begin_ == orig_data_end_);
|
||||||
|
|
||||||
|
orig_data_begin_ = begin;
|
||||||
|
orig_data_end_ = end;
|
||||||
|
data_seq_at_orig_data_end_ += (end - begin);
|
||||||
|
|
||||||
|
MarkOrCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::MarkOrCopy()
|
||||||
|
{
|
||||||
|
if ( ! message_complete_ )
|
||||||
|
{
|
||||||
|
switch ( mode_ )
|
||||||
|
{
|
||||||
|
case LINE_MODE:
|
||||||
|
MarkOrCopyLine();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FRAME_MODE:
|
||||||
|
MarkOrCopyFrame();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::ClearPreviousData()
|
||||||
|
{
|
||||||
|
// All previous data must have been processed or buffered already
|
||||||
|
if ( orig_data_begin_ < orig_data_end_ )
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(buffer_n_ == 0);
|
||||||
|
if ( chunked_ )
|
||||||
|
{
|
||||||
|
if ( frame_length_ > 0 )
|
||||||
|
{
|
||||||
|
frame_length_ -=
|
||||||
|
(orig_data_end_ - orig_data_begin_);
|
||||||
|
}
|
||||||
|
orig_data_begin_ = orig_data_end_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::NewGap(int length)
|
||||||
|
{
|
||||||
|
ClearPreviousData();
|
||||||
|
|
||||||
|
if ( chunked_ && frame_length_ >= 0 )
|
||||||
|
{
|
||||||
|
frame_length_ -= length;
|
||||||
|
if ( frame_length_ < 0 )
|
||||||
|
frame_length_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
orig_data_begin_ = orig_data_end_ = 0;
|
||||||
|
MarkOrCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::MarkOrCopyLine()
|
||||||
|
{
|
||||||
|
switch ( linebreak_style_ )
|
||||||
|
{
|
||||||
|
case CR_OR_LF:
|
||||||
|
MarkOrCopyLine_CR_OR_LF();
|
||||||
|
break;
|
||||||
|
case STRICT_CRLF:
|
||||||
|
MarkOrCopyLine_STRICT_CRLF();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BINPAC_ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finite state automaton for CR_OR_LF:
|
||||||
|
(!--line is complete, *--add to buffer)
|
||||||
|
|
||||||
|
CR_OR_LF_0:
|
||||||
|
CR: CR_OR_LF_1 !
|
||||||
|
LF: CR_OR_LF_0 !
|
||||||
|
.: CR_OR_LF_0 *
|
||||||
|
|
||||||
|
CR_OR_LF_1:
|
||||||
|
CR: CR_OR_LF_1 !
|
||||||
|
LF: CR_OR_LF_0
|
||||||
|
.: CR_OR_LF_0 *
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FlowBuffer::MarkOrCopyLine_CR_OR_LF()
|
||||||
|
{
|
||||||
|
if ( state_ == CR_OR_LF_1 &&
|
||||||
|
orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF )
|
||||||
|
{
|
||||||
|
state_ = CR_OR_LF_0;
|
||||||
|
++orig_data_begin_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_byteptr data;
|
||||||
|
for ( data = orig_data_begin_; data < orig_data_end_; ++data )
|
||||||
|
{
|
||||||
|
switch ( *data )
|
||||||
|
{
|
||||||
|
case CR:
|
||||||
|
state_ = CR_OR_LF_1;
|
||||||
|
goto found_end_of_line;
|
||||||
|
|
||||||
|
case LF:
|
||||||
|
// state_ = CR_OR_LF_0;
|
||||||
|
goto found_end_of_line;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// state_ = CR_OR_LF_0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_);
|
||||||
|
return;
|
||||||
|
|
||||||
|
found_end_of_line:
|
||||||
|
if ( buffer_n_ == 0 )
|
||||||
|
{
|
||||||
|
frame_length_ = data - orig_data_begin_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
|
||||||
|
// But eliminate the last CR or LF
|
||||||
|
--buffer_n_;
|
||||||
|
}
|
||||||
|
message_complete_ = true;
|
||||||
|
|
||||||
|
#if DEBUG_FLOW_BUFFER
|
||||||
|
fprintf(stderr, "%.6f Line complete: [%s]\n",
|
||||||
|
network_time(),
|
||||||
|
string((const char *) begin(), (const char *) end()).c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finite state automaton and STRICT_CRLF:
|
||||||
|
(!--line is complete, *--add to buffer)
|
||||||
|
|
||||||
|
STRICT_CRLF_0:
|
||||||
|
CR: STRICT_CRLF_1 *
|
||||||
|
LF: STRICT_CRLF_0 *
|
||||||
|
.: STRICT_CRLF_0 *
|
||||||
|
|
||||||
|
STRICT_CRLF_1:
|
||||||
|
CR: STRICT_CRLF_1 *
|
||||||
|
LF: STRICT_CRLF_0 ! (--buffer_n_)
|
||||||
|
.: STRICT_CRLF_0 *
|
||||||
|
*/
|
||||||
|
|
||||||
|
void FlowBuffer::MarkOrCopyLine_STRICT_CRLF()
|
||||||
|
{
|
||||||
|
const_byteptr data;
|
||||||
|
for ( data = orig_data_begin_; data < orig_data_end_; ++data )
|
||||||
|
{
|
||||||
|
switch ( *data )
|
||||||
|
{
|
||||||
|
case CR:
|
||||||
|
state_ = STRICT_CRLF_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LF:
|
||||||
|
if ( state_ == STRICT_CRLF_1 )
|
||||||
|
{
|
||||||
|
state_ = STRICT_CRLF_0;
|
||||||
|
goto found_end_of_line;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
state_ = STRICT_CRLF_0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_);
|
||||||
|
return;
|
||||||
|
|
||||||
|
found_end_of_line:
|
||||||
|
if ( buffer_n_ == 0 )
|
||||||
|
{
|
||||||
|
frame_length_ = data - 1 - orig_data_begin_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
|
||||||
|
// Pop the preceding CR and LF from the buffer
|
||||||
|
buffer_n_ -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message_complete_ = true;
|
||||||
|
|
||||||
|
#if DEBUG_FLOW_BUFFER
|
||||||
|
fprintf(stderr, "%.6f Line complete: [%s]\n",
|
||||||
|
network_time(),
|
||||||
|
string((const char *) begin(), (const char *) end()).c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invariants:
|
||||||
|
//
|
||||||
|
// When buffer_n_ == 0:
|
||||||
|
// Frame = [orig_data_begin_..(orig_data_begin_ + frame_length_)]
|
||||||
|
//
|
||||||
|
// When buffer_n_ > 0:
|
||||||
|
// Frame = [0..buffer_n_][orig_data_begin_..]
|
||||||
|
|
||||||
|
void FlowBuffer::MarkOrCopyFrame()
|
||||||
|
{
|
||||||
|
if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 &&
|
||||||
|
orig_data_begin_ < orig_data_end_ )
|
||||||
|
{
|
||||||
|
// Skip the lingering LF
|
||||||
|
if ( *orig_data_begin_ == LF )
|
||||||
|
{
|
||||||
|
++orig_data_begin_;
|
||||||
|
}
|
||||||
|
state_ = FRAME_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( buffer_n_ == 0 )
|
||||||
|
{
|
||||||
|
// If there is enough data
|
||||||
|
if ( frame_length_ >= 0 &&
|
||||||
|
orig_data_end_ - orig_data_begin_ >= frame_length_ )
|
||||||
|
{
|
||||||
|
// Do nothing except setting the message complete flag
|
||||||
|
message_complete_ = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( ! chunked_ )
|
||||||
|
{
|
||||||
|
AppendToBuffer(orig_data_begin_,
|
||||||
|
orig_data_end_ - orig_data_begin_);
|
||||||
|
}
|
||||||
|
message_complete_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(!chunked_);
|
||||||
|
int bytes_to_copy = orig_data_end_ - orig_data_begin_;
|
||||||
|
message_complete_ = false;
|
||||||
|
if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ )
|
||||||
|
{
|
||||||
|
bytes_to_copy = frame_length_ - buffer_n_;
|
||||||
|
message_complete_ = true;
|
||||||
|
}
|
||||||
|
AppendToBuffer(orig_data_begin_, bytes_to_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG_FLOW_BUFFER
|
||||||
|
if ( message_complete_ )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%.6f frame complete: [%s]\n",
|
||||||
|
network_time(),
|
||||||
|
string((const char *) begin(),
|
||||||
|
(const char *) end()).c_str());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowBuffer::AppendToBuffer(const_byteptr data, int len)
|
||||||
|
{
|
||||||
|
if ( len <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
BINPAC_ASSERT(! chunked_);
|
||||||
|
ExpandBuffer(buffer_n_ + len);
|
||||||
|
memcpy(buffer_ + buffer_n_, data, len);
|
||||||
|
buffer_n_ += len;
|
||||||
|
|
||||||
|
orig_data_begin_ += len;
|
||||||
|
BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace binpac
|
148
aux/binpac/lib/binpac_buffer.h
Normal file
148
aux/binpac/lib/binpac_buffer.h
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
#ifndef binpac_buffer_h
|
||||||
|
#define binpac_buffer_h
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "binpac.h"
|
||||||
|
|
||||||
|
namespace binpac {
|
||||||
|
|
||||||
|
class FlowBuffer {
|
||||||
|
public:
|
||||||
|
enum LineBreakStyle {
|
||||||
|
CR_OR_LF, // CR or LF or CRLF
|
||||||
|
STRICT_CRLF, // CR followed by LF
|
||||||
|
CR_LF_NUL, // CR or LF or CR-LF or CR-NUL
|
||||||
|
};
|
||||||
|
|
||||||
|
FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF);
|
||||||
|
virtual ~FlowBuffer();
|
||||||
|
|
||||||
|
void NewData(const_byteptr begin, const_byteptr end);
|
||||||
|
void NewGap(int length);
|
||||||
|
|
||||||
|
// Discard unprocessed data
|
||||||
|
void DiscardData();
|
||||||
|
|
||||||
|
// Whether there is enough data for the frame
|
||||||
|
bool ready() const{ return message_complete_ || mode_ == UNKNOWN_MODE; }
|
||||||
|
|
||||||
|
inline const_byteptr begin() const
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(ready());
|
||||||
|
return ( buffer_n_ == 0 ) ?
|
||||||
|
orig_data_begin_ : buffer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_byteptr end() const
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(ready());
|
||||||
|
if ( buffer_n_ == 0 )
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(frame_length_ >= 0);
|
||||||
|
const_byteptr end = orig_data_begin_ + frame_length_;
|
||||||
|
BINPAC_ASSERT(end <= orig_data_end_);
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return buffer_ + buffer_n_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int data_length() const
|
||||||
|
{
|
||||||
|
if ( buffer_n_ > 0 )
|
||||||
|
return buffer_n_;
|
||||||
|
|
||||||
|
if ( frame_length_ < 0 ||
|
||||||
|
orig_data_begin_ + frame_length_ > orig_data_end_ )
|
||||||
|
return orig_data_end_ - orig_data_begin_;
|
||||||
|
else
|
||||||
|
return frame_length_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool data_available() const
|
||||||
|
{
|
||||||
|
return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewLine();
|
||||||
|
// A negative frame_length represents a frame till EOF
|
||||||
|
void NewFrame(int frame_length, bool chunked_);
|
||||||
|
void GrowFrame(int new_frame_length);
|
||||||
|
|
||||||
|
int data_seq() const
|
||||||
|
{
|
||||||
|
int data_seq_at_orig_data_begin =
|
||||||
|
data_seq_at_orig_data_end_ -
|
||||||
|
(orig_data_end_ - orig_data_begin_);
|
||||||
|
if ( buffer_n_ > 0 )
|
||||||
|
return data_seq_at_orig_data_begin;
|
||||||
|
else
|
||||||
|
return data_seq_at_orig_data_begin + data_length();
|
||||||
|
}
|
||||||
|
bool eof() const { return eof_; }
|
||||||
|
void set_eof();
|
||||||
|
|
||||||
|
bool have_pending_request() const { return have_pending_request_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Reset the buffer for a new message
|
||||||
|
void NewMessage();
|
||||||
|
|
||||||
|
void ClearPreviousData();
|
||||||
|
|
||||||
|
// Expand the buffer to at least <length> bytes. If there
|
||||||
|
// are contents in the existing buffer, copy them to the new
|
||||||
|
// buffer.
|
||||||
|
void ExpandBuffer(int length);
|
||||||
|
|
||||||
|
// Reset line state when transit from frame mode to line mode.
|
||||||
|
void ResetLineState();
|
||||||
|
|
||||||
|
void AppendToBuffer(const_byteptr data, int len);
|
||||||
|
|
||||||
|
// MarkOrCopy{Line,Frame} sets message_complete_ and
|
||||||
|
// marks begin/end pointers if a line/frame is complete,
|
||||||
|
// otherwise it clears message_complete_ and copies all
|
||||||
|
// the original data to the buffer.
|
||||||
|
//
|
||||||
|
void MarkOrCopy();
|
||||||
|
void MarkOrCopyLine();
|
||||||
|
void MarkOrCopyFrame();
|
||||||
|
|
||||||
|
void MarkOrCopyLine_CR_OR_LF();
|
||||||
|
void MarkOrCopyLine_STRICT_CRLF();
|
||||||
|
|
||||||
|
int buffer_n_; // number of bytes in the buffer
|
||||||
|
int buffer_length_; // size of the buffer
|
||||||
|
u_char *buffer_;
|
||||||
|
bool message_complete_;
|
||||||
|
int frame_length_;
|
||||||
|
bool chunked_;
|
||||||
|
const_byteptr orig_data_begin_, orig_data_end_;
|
||||||
|
|
||||||
|
LineBreakStyle linebreak_style_;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
UNKNOWN_MODE,
|
||||||
|
LINE_MODE,
|
||||||
|
FRAME_MODE,
|
||||||
|
} mode_;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CR_OR_LF_0,
|
||||||
|
CR_OR_LF_1,
|
||||||
|
STRICT_CRLF_0,
|
||||||
|
STRICT_CRLF_1,
|
||||||
|
FRAME_0,
|
||||||
|
} state_;
|
||||||
|
|
||||||
|
int data_seq_at_orig_data_end_;
|
||||||
|
bool eof_;
|
||||||
|
bool have_pending_request_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef FlowBuffer *flow_buffer_t;
|
||||||
|
|
||||||
|
} // namespace binpac
|
||||||
|
|
||||||
|
#endif // binpac_buffer_h
|
24
aux/binpac/lib/binpac_bytestring.cc
Normal file
24
aux/binpac/lib/binpac_bytestring.cc
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#define binpac_regex_h
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "binpac_bytestring.h"
|
||||||
|
|
||||||
|
namespace binpac
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string std_string(bytestring const *s)
|
||||||
|
{
|
||||||
|
return std::string((const char *) s->begin(), (const char *) s->end());
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytestring_to_int(bytestring const *s)
|
||||||
|
{
|
||||||
|
return atoi((const char *) s->begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
double bytestring_to_double(bytestring const *s)
|
||||||
|
{
|
||||||
|
return atof((const char *) s->begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace binpac
|
199
aux/binpac/lib/binpac_bytestring.h
Normal file
199
aux/binpac/lib/binpac_bytestring.h
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
#ifndef binpac_bytestring_h
|
||||||
|
#define binpac_bytestring_h
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <string>
|
||||||
|
#include "binpac.h"
|
||||||
|
|
||||||
|
namespace binpac
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> class datastring;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class const_datastring
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const_datastring()
|
||||||
|
: begin_(0), end_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const_datastring(T const *data, int length)
|
||||||
|
: begin_(data), end_(data + length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const_datastring(const T *begin, const T *end)
|
||||||
|
: begin_(begin), end_(end)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const_datastring(datastring<T> const &s)
|
||||||
|
: begin_(s.begin()), end_(s.end())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(const T *data, int length)
|
||||||
|
{
|
||||||
|
begin_ = data;
|
||||||
|
end_ = data + length;
|
||||||
|
}
|
||||||
|
|
||||||
|
T const *begin() const { return begin_; }
|
||||||
|
T const *end() const { return end_; }
|
||||||
|
int length() const { return end_ - begin_; }
|
||||||
|
|
||||||
|
T const &operator[](int index) const
|
||||||
|
{
|
||||||
|
return begin()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const_datastring<T> const &s)
|
||||||
|
{
|
||||||
|
if ( length() != s.length() )
|
||||||
|
return false;
|
||||||
|
return memcmp((const void *) begin(), (const void *) s.begin(),
|
||||||
|
sizeof(T) * length()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_begin(T const *begin) { begin_ = begin; }
|
||||||
|
void set_end(T const *end) { end_ = end; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T const *begin_;
|
||||||
|
T const *end_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef const_datastring<uint8> const_bytestring;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class datastring
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
datastring()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
datastring(T *data, int len)
|
||||||
|
{
|
||||||
|
set(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
datastring(T const *begin, T const *end)
|
||||||
|
{
|
||||||
|
set_const(begin, end - begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
datastring(datastring<T> const &x)
|
||||||
|
: data_(x.data()), length_(x.length())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit datastring(const_datastring<T> const &x)
|
||||||
|
{
|
||||||
|
set_const(x.begin(), x.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
datastring const &operator=(datastring<T> const &x)
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(!data_);
|
||||||
|
set(x.data(), x.length());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(T const *begin, int length)
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(!data_);
|
||||||
|
set_const(begin, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
data_ = 0; length_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free()
|
||||||
|
{
|
||||||
|
if ( data_ )
|
||||||
|
delete [] data_;
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clone()
|
||||||
|
{
|
||||||
|
set_const(begin(), length());
|
||||||
|
}
|
||||||
|
|
||||||
|
datastring const &operator=(const_datastring<T> const &x)
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(!data_);
|
||||||
|
set_const(x.begin(), x.length());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T const &operator[](int index) const
|
||||||
|
{
|
||||||
|
return begin()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
T *data() const { return data_; }
|
||||||
|
int length() const { return length_; }
|
||||||
|
|
||||||
|
T const *begin() const { return data_; }
|
||||||
|
T const *end() const { return data_ + length_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void set(T *data, int len)
|
||||||
|
{
|
||||||
|
data_ = data;
|
||||||
|
length_ = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_const(T const *data, int len)
|
||||||
|
{
|
||||||
|
length_ = len;
|
||||||
|
data_ = new T[len + 1];
|
||||||
|
memcpy(data_, data, sizeof(T) * len);
|
||||||
|
data_[len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
T * data_;
|
||||||
|
int length_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef datastring<uint8> bytestring;
|
||||||
|
|
||||||
|
inline const char *c_str(bytestring const &s)
|
||||||
|
{
|
||||||
|
return (const char *) s.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string std_str(const_bytestring const &s)
|
||||||
|
{
|
||||||
|
return std::string((const char *) s.begin(), (const char *) s.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(bytestring const &s1, const char *s2)
|
||||||
|
{
|
||||||
|
return strcmp(c_str(s1), s2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void get_pointers(const_bytestring const &s,
|
||||||
|
uint8 const **pbegin, uint8 const **pend)
|
||||||
|
{
|
||||||
|
*pbegin = s.begin();
|
||||||
|
*pend = s.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void get_pointers(bytestring const *s,
|
||||||
|
uint8 const **pbegin, uint8 const **pend)
|
||||||
|
{
|
||||||
|
*pbegin = s->begin();
|
||||||
|
*pend = s->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace binpac
|
||||||
|
|
||||||
|
#endif // binpac_bytestring_h
|
112
aux/binpac/lib/binpac_exception.h
Normal file
112
aux/binpac/lib/binpac_exception.h
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
#ifndef binpac_exception_h
|
||||||
|
#define binpac_exception_h
|
||||||
|
|
||||||
|
namespace binpac {
|
||||||
|
|
||||||
|
class Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Exception(const char* m = 0)
|
||||||
|
: msg_("binpac exception: ")
|
||||||
|
{
|
||||||
|
if ( m )
|
||||||
|
append(m);
|
||||||
|
// abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(string m) { msg_ += m; }
|
||||||
|
string msg() const { return msg_; }
|
||||||
|
const char* c_msg() const { return msg().c_str(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string msg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionOutOfBound : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionOutOfBound(const char* where, int len_needed, int len_given)
|
||||||
|
{
|
||||||
|
append(binpac_fmt("out_of_bound: %s: %d > %d",
|
||||||
|
where, len_needed, len_given));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionInvalidCase : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionInvalidCase(const char* location,
|
||||||
|
int index,
|
||||||
|
const char *expected)
|
||||||
|
: location_(location),
|
||||||
|
index_(index),
|
||||||
|
expected_(expected)
|
||||||
|
{
|
||||||
|
append(binpac_fmt("invalid case: %s: %d (%s)",
|
||||||
|
location, index, expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* location_;
|
||||||
|
int index_;
|
||||||
|
string expected_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionInvalidCaseIndex : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionInvalidCaseIndex(const char* location,
|
||||||
|
int index)
|
||||||
|
: location_(location),
|
||||||
|
index_(index)
|
||||||
|
{
|
||||||
|
append(binpac_fmt("invalid index for case: %s: %d",
|
||||||
|
location, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* location_;
|
||||||
|
int index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionInvalidOffset : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionInvalidOffset(const char* location,
|
||||||
|
int min_offset, int offset)
|
||||||
|
: location_(location),
|
||||||
|
min_offset_(min_offset), offset_(offset)
|
||||||
|
{
|
||||||
|
append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d",
|
||||||
|
location, min_offset, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* location_;
|
||||||
|
int min_offset_, offset_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionStringMismatch : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionStringMismatch(const char* location,
|
||||||
|
const char *expected, const char *actual_data)
|
||||||
|
{
|
||||||
|
append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"",
|
||||||
|
location, expected, actual_data));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionInvalidStringLength : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionInvalidStringLength(const char* location, int len)
|
||||||
|
{
|
||||||
|
append(binpac_fmt("invalid length string: %s: %d",
|
||||||
|
location, len));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // binpac_exception_h
|
0
aux/binpac/lib/binpac_regex.cc
Normal file
0
aux/binpac/lib/binpac_regex.cc
Normal file
43
aux/binpac/lib/binpac_regex.h
Normal file
43
aux/binpac/lib/binpac_regex.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef binpac_regex_h
|
||||||
|
#define binpac_regex_h
|
||||||
|
|
||||||
|
#include "binpac.h"
|
||||||
|
#include "RE.h"
|
||||||
|
|
||||||
|
class RE_Matcher;
|
||||||
|
|
||||||
|
namespace binpac
|
||||||
|
{
|
||||||
|
|
||||||
|
class RegExMatcher {
|
||||||
|
public:
|
||||||
|
RegExMatcher(const char *pattern)
|
||||||
|
: pattern_(pattern)
|
||||||
|
{
|
||||||
|
re_matcher_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~RegExMatcher()
|
||||||
|
{
|
||||||
|
delete re_matcher_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the length of longest match, or -1 on mismatch.
|
||||||
|
int MatchPrefix(const_byteptr data, int len)
|
||||||
|
{
|
||||||
|
if ( ! re_matcher_ )
|
||||||
|
{
|
||||||
|
re_matcher_ = new RE_Matcher(pattern_.c_str());
|
||||||
|
re_matcher_->Compile();
|
||||||
|
}
|
||||||
|
return re_matcher_->MatchPrefix(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string pattern_;
|
||||||
|
RE_Matcher *re_matcher_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace binpac
|
||||||
|
|
||||||
|
#endif // binpac_regex_h
|
31
aux/binpac/patches/binpac-1.patch
Normal file
31
aux/binpac/patches/binpac-1.patch
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_expr.cc bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700
|
||||||
|
@@ -776,6 +776,27 @@
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case EXPR_CALLARGS:
|
||||||
|
+ {
|
||||||
|
+ mhs = 0;
|
||||||
|
+ if ( args_ )
|
||||||
|
+ for ( uint i = 0; i < args_->size(); ++i )
|
||||||
|
+ mhs = mhs_max(mhs, args_->at(i)->MinimalHeaderSize(env));
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ case EXPR_CASE:
|
||||||
|
+ {
|
||||||
|
+ mhs = operand_[0]->MinimalHeaderSize(env);
|
||||||
|
+ for ( uint i = 0; i < cases_->size(); ++i )
|
||||||
|
+ {
|
||||||
|
+ CaseExpr * ce = cases_->at(i);
|
||||||
|
+ if ( ce->index() )
|
||||||
|
+ for ( uint j = 0; j < ce->index()->size(); ++j )
|
||||||
|
+ mhs = mhs_max(mhs, ce->index()->at(j)->MinimalHeaderSize(env));
|
||||||
|
+ mhs = mhs_max(mhs, ce->value()->MinimalHeaderSize(env));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
// Evaluate every operand by default
|
||||||
|
mhs = 0;
|
97
aux/binpac/patches/binpac-2.patch
Normal file
97
aux/binpac/patches/binpac-2.patch
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_expr.cc bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_expr.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.cc 2007-05-04 14:31:11.728494000 -0700
|
||||||
|
@@ -245,6 +245,12 @@
|
||||||
|
out_cc->println("%s %s;",
|
||||||
|
val_type->DataTypeStr().c_str(),
|
||||||
|
env->LValue(val_var));
|
||||||
|
+
|
||||||
|
+ // force evaluation of IDs appearing in case stmt
|
||||||
|
+ operand_[0]->ForceIDEval(out_cc, env);
|
||||||
|
+ foreach(i, CaseExprList, cases_)
|
||||||
|
+ (*i)->value()->ForceIDEval(out_cc, env);
|
||||||
|
+
|
||||||
|
out_cc->println("switch ( %s )", operand_[0]->EvalExpr(out_cc, env));
|
||||||
|
|
||||||
|
out_cc->inc_indent();
|
||||||
|
@@ -386,6 +392,49 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void Expr::ForceIDEval(Output* out_cc, Env* env)
|
||||||
|
+ {
|
||||||
|
+ switch ( expr_type_ )
|
||||||
|
+ {
|
||||||
|
+ case EXPR_NUM:
|
||||||
|
+ case EXPR_SIZEOF:
|
||||||
|
+ case EXPR_OFFSETOF:
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EXPR_ID:
|
||||||
|
+ if ( ! env->Evaluated(id_) )
|
||||||
|
+ env->Evaluate(out_cc, id_);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EXPR_MEMBER:
|
||||||
|
+ operand_[0]->ForceIDEval(out_cc, env);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EXPR_CALLARGS:
|
||||||
|
+ {
|
||||||
|
+ foreach(i, ExprList, args_)
|
||||||
|
+ (*i)->ForceIDEval(out_cc, env);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case EXPR_CASE:
|
||||||
|
+ {
|
||||||
|
+ operand_[0]->ForceIDEval(out_cc, env);
|
||||||
|
+ foreach(i, CaseExprList, cases_)
|
||||||
|
+ (*i)->value()->ForceIDEval(out_cc, env);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ // Evaluate every operand by default
|
||||||
|
+ for ( int i = 0; i < 3; ++i )
|
||||||
|
+ if ( operand_[i] )
|
||||||
|
+ operand_[i]->ForceIDEval(out_cc, env);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+
|
||||||
|
const char* Expr::EvalExpr(Output* out_cc, Env* env)
|
||||||
|
{
|
||||||
|
GenEval(out_cc, env);
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_expr.h bro-1.2.1-ssl-binpac/src/binpac/pac_expr.h
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_expr.h 2006-07-26 15:02:39.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_expr.h 2007-05-04 14:16:31.624287000 -0700
|
||||||
|
@@ -56,6 +56,11 @@
|
||||||
|
//
|
||||||
|
const char *EvalExpr(Output *out, Env *env);
|
||||||
|
|
||||||
|
+ // force evaulation of IDs contained in this expression;
|
||||||
|
+ // necessary with case expr and conditional let fields (&if)
|
||||||
|
+ // for correct parsing of fields
|
||||||
|
+ void ForceIDEval(Output *out_cc, Env *env);
|
||||||
|
+
|
||||||
|
// Returns the set_* function of the expression.
|
||||||
|
// The expression must be of form ID or x.ID.
|
||||||
|
string SetFunc(Output *out, Env *env);
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_let.cc bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_let.cc 2006-07-26 15:02:39.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc 2007-05-04 15:32:09.695568000 -0700
|
||||||
|
@@ -80,7 +80,12 @@
|
||||||
|
if ( type_->attr_if_expr() )
|
||||||
|
{
|
||||||
|
// A conditional field
|
||||||
|
+
|
||||||
|
env->Evaluate(out_cc, type_->has_value_var());
|
||||||
|
+
|
||||||
|
+ // force evaluation of IDs contained in this expr
|
||||||
|
+ expr()->ForceIDEval(out_cc, env);
|
||||||
|
+
|
||||||
|
out_cc->println("if ( %s )",
|
||||||
|
env->RValue(type_->has_value_var()));
|
||||||
|
out_cc->inc_indent();
|
37
aux/binpac/patches/binpac-3.patch
Normal file
37
aux/binpac/patches/binpac-3.patch
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_let.cc bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_let.cc 2006-07-26 15:02:39.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_let.cc 2007-05-04 15:32:09.695568000 -0700
|
||||||
|
@@ -108,11 +108,6 @@
|
||||||
|
void LetField::GenEval(Output* out_cc, Env* env)
|
||||||
|
{
|
||||||
|
GenParseCode(out_cc, env);
|
||||||
|
- if ( type_->attr_if_expr() )
|
||||||
|
- {
|
||||||
|
- out_cc->println("BINPAC_ASSERT(%s);",
|
||||||
|
- env->RValue(type_->has_value_var()));
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
|
||||||
|
LetDecl::LetDecl(ID *id, Type *type, Expr *expr)
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700
|
||||||
|
@@ -316,9 +316,15 @@
|
||||||
|
{
|
||||||
|
if ( DefineValueVar() )
|
||||||
|
{
|
||||||
|
- out_h->println("%s %s const { return %s; }",
|
||||||
|
- DataTypeConstRefStr().c_str(),
|
||||||
|
- env->RValue(value_var()), lvalue());
|
||||||
|
+ if ( attr_if_expr_ )
|
||||||
|
+ out_h->println("%s %s const { BINPAC_ASSERT(%s); return %s; }",
|
||||||
|
+ DataTypeConstRefStr().c_str(),
|
||||||
|
+ env->RValue(value_var()),
|
||||||
|
+ env->RValue(has_value_var()), lvalue());
|
||||||
|
+ else
|
||||||
|
+ out_h->println("%s %s const { return %s; }",
|
||||||
|
+ DataTypeConstRefStr().c_str(),
|
||||||
|
+ env->RValue(value_var()), lvalue());
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (i, FieldList, fields_)
|
12
aux/binpac/patches/binpac-4.patch
Normal file
12
aux/binpac/patches/binpac-4.patch
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_record.cc bro-1.2.1-ssl-binpac/src/binpac/pac_record.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_record.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_record.cc 2007-05-08 16:13:33.373850000 -0700
|
||||||
|
@@ -123,7 +123,7 @@
|
||||||
|
void RecordType::DoGenParseCode(Output* out_cc, Env* env,
|
||||||
|
const DataPtr& data, int flags)
|
||||||
|
{
|
||||||
|
- if ( StaticSize(env) >= 0 )
|
||||||
|
+ if ( !incremental_input() && StaticSize(env) >= 0 )
|
||||||
|
GenBoundaryCheck(out_cc, env, data);
|
||||||
|
|
||||||
|
if ( incremental_parsing() )
|
66
aux/binpac/patches/binpac-5.patch
Normal file
66
aux/binpac/patches/binpac-5.patch
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_paramtype.cc bro-1.2.1-ssl-binpac/src/binpac/pac_paramtype.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_paramtype.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_paramtype.cc 2007-05-10 15:09:47.470104000 -0700
|
||||||
|
@@ -208,7 +208,13 @@
|
||||||
|
const char *parse_func;
|
||||||
|
string parse_params;
|
||||||
|
|
||||||
|
- if ( ref_type->incremental_input() )
|
||||||
|
+ if ( buffer_mode() == BUFFER_NOTHING )
|
||||||
|
+ {
|
||||||
|
+ ASSERT(!ref_type->incremental_input());
|
||||||
|
+ parse_func = kParseFuncWithoutBuffer;
|
||||||
|
+ parse_params = "0, 0";
|
||||||
|
+ }
|
||||||
|
+ else if ( ref_type->incremental_input() )
|
||||||
|
{
|
||||||
|
parse_func = kParseFuncWithBuffer;
|
||||||
|
parse_params = env->RValue(flow_buffer_id);
|
||||||
|
@@ -239,15 +245,24 @@
|
||||||
|
|
||||||
|
if ( incremental_input() )
|
||||||
|
{
|
||||||
|
- ASSERT(parsing_complete_var());
|
||||||
|
- out_cc->println("%s = %s;",
|
||||||
|
- env->LValue(parsing_complete_var()),
|
||||||
|
- call_parse_func.c_str());
|
||||||
|
-
|
||||||
|
- // parsing_complete_var might have been already
|
||||||
|
- // evaluated when set to false
|
||||||
|
- if ( ! env->Evaluated(parsing_complete_var()) )
|
||||||
|
- env->SetEvaluated(parsing_complete_var());
|
||||||
|
+ if ( buffer_mode() == BUFFER_NOTHING )
|
||||||
|
+ {
|
||||||
|
+ out_cc->println("%s;", call_parse_func.c_str());
|
||||||
|
+ out_cc->println("%s = true;",
|
||||||
|
+ env->LValue(parsing_complete_var()));
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ ASSERT(parsing_complete_var());
|
||||||
|
+ out_cc->println("%s = %s;",
|
||||||
|
+ env->LValue(parsing_complete_var()),
|
||||||
|
+ call_parse_func.c_str());
|
||||||
|
+
|
||||||
|
+ // parsing_complete_var might have been already
|
||||||
|
+ // evaluated when set to false
|
||||||
|
+ if ( ! env->Evaluated(parsing_complete_var()) )
|
||||||
|
+ env->SetEvaluated(parsing_complete_var());
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700
|
||||||
|
@@ -501,8 +501,8 @@
|
||||||
|
|
||||||
|
if ( buffer_mode() == BUFFER_NOTHING )
|
||||||
|
{
|
||||||
|
- out_cc->println("%s = true;",
|
||||||
|
- env->LValue(parsing_complete_var()));
|
||||||
|
+ // this is the empty type
|
||||||
|
+ DoGenParseCode(out_cc, env, data, flags);
|
||||||
|
}
|
||||||
|
else if ( buffer_input() )
|
||||||
|
{
|
28
aux/binpac/patches/binpac-6.patch
Normal file
28
aux/binpac/patches/binpac-6.patch
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/lib/binpac_buffer.h bro-1.2.1-ssl-binpac/src/binpac/lib/binpac_buffer.h
|
||||||
|
--- bro-1.2.1-orig/src/binpac/lib/binpac_buffer.h 2006-07-26 15:02:38.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/lib/binpac_buffer.h 2007-05-09 16:14:54.501656000 -0700
|
||||||
|
@@ -59,6 +59,11 @@
|
||||||
|
return frame_length_;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ inline bool data_available() const
|
||||||
|
+ {
|
||||||
|
+ return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
void NewLine();
|
||||||
|
// A negative frame_length represents a frame till EOF
|
||||||
|
void NewFrame(int frame_length, bool chunked_);
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_flow.cc bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700
|
||||||
|
@@ -272,7 +272,8 @@
|
||||||
|
env_->RValue(begin_of_data),
|
||||||
|
env_->RValue(end_of_data));
|
||||||
|
|
||||||
|
- out_cc->println("while ( true )");
|
||||||
|
+ out_cc->println("while ( %s->data_available() )",
|
||||||
|
+ env_->LValue(flow_buffer_id));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
21
aux/binpac/patches/binpac-7.patch
Normal file
21
aux/binpac/patches/binpac-7.patch
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_type.cc bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_type.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_type.cc 2007-05-24 10:56:42.140658000 -0700
|
||||||
|
@@ -393,7 +393,7 @@
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUFFER_BY_LENGTH:
|
||||||
|
- if ( buffering_state_var_field_ )
|
||||||
|
+ if ( env->GetDataType(buffering_state_id) )
|
||||||
|
{
|
||||||
|
out_cc->println("if ( %s == 0 )",
|
||||||
|
env->RValue(buffering_state_id));
|
||||||
|
@@ -421,7 +421,7 @@
|
||||||
|
frame_buffer_arg.c_str(),
|
||||||
|
attr_chunked() ? "true" : "false");
|
||||||
|
|
||||||
|
- if ( buffering_state_var_field_ )
|
||||||
|
+ if ( env->GetDataType(buffering_state_id) )
|
||||||
|
{
|
||||||
|
out_cc->println("%s = 1;",
|
||||||
|
env->LValue(buffering_state_id));
|
190
aux/binpac/patches/binpac-8.patch
Normal file
190
aux/binpac/patches/binpac-8.patch
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.cc bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_analyzer.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.cc 2007-05-22 17:00:10.091531000 -0700
|
||||||
|
@@ -26,8 +26,9 @@
|
||||||
|
helpers_ = new AnalyzerHelperList();
|
||||||
|
functions_ = new FunctionList();
|
||||||
|
|
||||||
|
- constructor_helper_ = 0;
|
||||||
|
- destructor_helper_ = 0;
|
||||||
|
+ constructor_helpers_ = new AnalyzerHelperList();
|
||||||
|
+ destructor_helpers_ = new AnalyzerHelperList();
|
||||||
|
+ eof_helpers_ = new AnalyzerHelperList();
|
||||||
|
|
||||||
|
SetAnalyzerContext();
|
||||||
|
|
||||||
|
@@ -41,6 +42,9 @@
|
||||||
|
delete_list(AnalyzerHelperList, helpers_);
|
||||||
|
delete_list(FunctionList, functions_);
|
||||||
|
delete_list(ParamList, params_);
|
||||||
|
+ delete_list(AnalyzerHelperList, constructor_helpers_);
|
||||||
|
+ delete_list(AnalyzerHelperList, destructor_helpers_);
|
||||||
|
+ delete_list(AnalyzerHelperList, eof_helpers_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist)
|
||||||
|
@@ -75,28 +79,20 @@
|
||||||
|
AnalyzerHelper *helper_elem =
|
||||||
|
(AnalyzerHelper *) elem;
|
||||||
|
|
||||||
|
- if ( helper_elem->helper_type() ==
|
||||||
|
- AnalyzerHelper::INIT_CODE)
|
||||||
|
- {
|
||||||
|
- if ( constructor_helper_ )
|
||||||
|
- {
|
||||||
|
- throw Exception(elem,
|
||||||
|
- "Repeated definition of %init code");
|
||||||
|
- }
|
||||||
|
- constructor_helper_ = helper_elem;
|
||||||
|
+ switch ( helper_elem->helper_type() )
|
||||||
|
+ {
|
||||||
|
+ case AnalyzerHelper::INIT_CODE:
|
||||||
|
+ constructor_helpers_->push_back(helper_elem);
|
||||||
|
+ break;
|
||||||
|
+ case AnalyzerHelper::CLEANUP_CODE:
|
||||||
|
+ destructor_helpers_->push_back(helper_elem);
|
||||||
|
+ break;
|
||||||
|
+ case AnalyzerHelper::EOF_CODE:
|
||||||
|
+ eof_helpers_->push_back(helper_elem);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ helpers_->push_back(helper_elem);
|
||||||
|
}
|
||||||
|
- else if ( helper_elem->helper_type() ==
|
||||||
|
- AnalyzerHelper::CLEANUP_CODE)
|
||||||
|
- {
|
||||||
|
- if ( destructor_helper_ )
|
||||||
|
- {
|
||||||
|
- throw Exception(elem,
|
||||||
|
- "Repeated definition of %cleanup code");
|
||||||
|
- }
|
||||||
|
- destructor_helper_ = helper_elem;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- helpers_->push_back(helper_elem);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AnalyzerElement::FUNCTION:
|
||||||
|
@@ -217,15 +213,19 @@
|
||||||
|
void AnalyzerDecl::GenInitCode(Output *out_cc)
|
||||||
|
{
|
||||||
|
TypeDecl::GenInitCode(out_cc);
|
||||||
|
- if ( constructor_helper_ )
|
||||||
|
- constructor_helper_->GenCode(0, out_cc, this);
|
||||||
|
+ foreach(i, AnalyzerHelperList, constructor_helpers_)
|
||||||
|
+ {
|
||||||
|
+ (*i)->GenCode(0, out_cc, this);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenCleanUpCode(Output *out_cc)
|
||||||
|
{
|
||||||
|
TypeDecl::GenCleanUpCode(out_cc);
|
||||||
|
- if ( destructor_helper_ )
|
||||||
|
- destructor_helper_->GenCode(0, out_cc, this);
|
||||||
|
+ foreach(i, AnalyzerHelperList, destructor_helpers_)
|
||||||
|
+ {
|
||||||
|
+ (*i)->GenCode(0, out_cc, this);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenStateVarDecls(Output *out_h)
|
||||||
|
@@ -295,6 +295,7 @@
|
||||||
|
break;
|
||||||
|
case INIT_CODE:
|
||||||
|
case CLEANUP_CODE:
|
||||||
|
+ case EOF_CODE:
|
||||||
|
out = out_cc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_analyzer.h bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.h
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_analyzer.h 2006-07-26 15:02:39.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_analyzer.h 2007-05-22 16:32:08.397926000 -0700
|
||||||
|
@@ -76,8 +76,9 @@
|
||||||
|
AnalyzerHelperList *helpers_;
|
||||||
|
FunctionList *functions_;
|
||||||
|
|
||||||
|
- AnalyzerHelper *constructor_helper_;
|
||||||
|
- AnalyzerHelper *destructor_helper_;
|
||||||
|
+ AnalyzerHelperList *constructor_helpers_;
|
||||||
|
+ AnalyzerHelperList *destructor_helpers_;
|
||||||
|
+ AnalyzerHelperList *eof_helpers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AnalyzerElement : public Object
|
||||||
|
@@ -117,6 +118,7 @@
|
||||||
|
MEMBER_DECLS,
|
||||||
|
INIT_CODE,
|
||||||
|
CLEANUP_CODE,
|
||||||
|
+ EOF_CODE,
|
||||||
|
};
|
||||||
|
AnalyzerHelper(Type helper_type, EmbeddedCode *code)
|
||||||
|
: AnalyzerElement(HELPER),
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_conn.cc bro-1.2.1-ssl-binpac/src/binpac/pac_conn.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_conn.cc 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_conn.cc 2007-05-22 16:42:35.406135000 -0700
|
||||||
|
@@ -97,6 +97,12 @@
|
||||||
|
out_cc->println("%s->%s();",
|
||||||
|
env_->LValue(downflow_id),
|
||||||
|
kFlowEOF);
|
||||||
|
+
|
||||||
|
+ foreach(i, AnalyzerHelperList, eof_helpers_)
|
||||||
|
+ {
|
||||||
|
+ (*i)->GenCode(0, out_cc, this);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
out_cc->dec_indent();
|
||||||
|
|
||||||
|
out_cc->println("}");
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_flow.cc bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_flow.cc 2006-10-12 14:13:12.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_flow.cc 2007-05-22 16:43:55.997562000 -0700
|
||||||
|
@@ -151,6 +151,11 @@
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
+ foreach(i, AnalyzerHelperList, eof_helpers_)
|
||||||
|
+ {
|
||||||
|
+ (*i)->GenCode(0, out_cc, this);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT )
|
||||||
|
{
|
||||||
|
out_cc->println("%s->set_eof();",
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_parse.yy bro-1.2.1-ssl-binpac/src/binpac/pac_parse.yy
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_parse.yy 2006-10-12 14:13:12.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_parse.yy 2007-05-22 16:56:09.280526000 -0700
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
%token TOK_STATE TOK_ACTION TOK_WHEN TOK_HELPER
|
||||||
|
%token TOK_DATAUNIT TOK_FLOWDIR TOK_WITHCONTEXT
|
||||||
|
%token TOK_LPB_EXTERN TOK_LPB_HEADER TOK_LPB_CODE
|
||||||
|
-%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP
|
||||||
|
+%token TOK_LPB_MEMBER TOK_LPB_INIT TOK_LPB_CLEANUP TOK_LPB_EOF
|
||||||
|
%token TOK_LPB TOK_RPB
|
||||||
|
%token TOK_EMBEDDED_ATOM TOK_EMBEDDED_STRING
|
||||||
|
%token TOK_PAC_VAL TOK_PAC_SET TOK_PAC_TYPE TOK_PAC_TYPEOF TOK_PAC_CONST_DEF
|
||||||
|
@@ -795,6 +795,10 @@
|
||||||
|
{
|
||||||
|
$$ = new AnalyzerHelper(AnalyzerHelper::CLEANUP_CODE, $2);
|
||||||
|
}
|
||||||
|
+ | TOK_LPB_EOF embedded_code TOK_RPB
|
||||||
|
+ {
|
||||||
|
+ $$ = new AnalyzerHelper(AnalyzerHelper::EOF_CODE, $2);
|
||||||
|
+ }
|
||||||
|
| TOK_FLOWDIR '=' tok_id optargs ';'
|
||||||
|
{
|
||||||
|
$$ = new AnalyzerFlow((AnalyzerFlow::Direction) $1, $3, $4);
|
||||||
|
diff -urN bro-1.2.1-orig/src/binpac/pac_scan.ll bro-1.2.1-ssl-binpac/src/binpac/pac_scan.ll
|
||||||
|
--- bro-1.2.1-orig/src/binpac/pac_scan.ll 2006-07-26 15:02:40.000000000 -0700
|
||||||
|
+++ bro-1.2.1-ssl-binpac/src/binpac/pac_scan.ll 2007-05-22 16:55:19.349644000 -0700
|
||||||
|
@@ -96,6 +96,10 @@
|
||||||
|
BEGIN(EC);
|
||||||
|
return TOK_LPB_MEMBER;
|
||||||
|
}
|
||||||
|
+<INITIAL>"%eof{" {
|
||||||
|
+ BEGIN(EC);
|
||||||
|
+ return TOK_LPB_EOF;
|
||||||
|
+ }
|
||||||
|
<INITIAL>"%{" {
|
||||||
|
BEGIN(EC);
|
||||||
|
return TOK_LPB;
|
87
aux/binpac/patches/binpac-patch-doc.txt
Normal file
87
aux/binpac/patches/binpac-patch-doc.txt
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
binpac fixes
|
||||||
|
----------------
|
||||||
|
|
||||||
|
numbers of issues below correspond to the patch numbers
|
||||||
|
|
||||||
|
(1) correct calculation of minimal header size in pac_expr.cc
|
||||||
|
- problem: EXPR_CALLARGS and EXPR_CASE not considered for the calculation
|
||||||
|
of minimal header size
|
||||||
|
- solution: added two cases in switch stmt of Expr::MinimalHeaderSize
|
||||||
|
for EXPR_CALLARGS and EXPR_CASE
|
||||||
|
|
||||||
|
|
||||||
|
(2) ensure parsing of fields first referenced in a case expression or
|
||||||
|
let field with an &if attribute
|
||||||
|
- problem: in cases where the if expression evaluates to false or the
|
||||||
|
proper case does not occur, fields get not parsed at all
|
||||||
|
- solution: force evaluation of all IDs referenced in a let field with
|
||||||
|
if attribute or a case expression before the body of the corresponding
|
||||||
|
switch stmt or the if stmt
|
||||||
|
- added public method Expr::ForceIDEval, properly called before
|
||||||
|
generating the code of a field with if attribute or the case expression
|
||||||
|
|
||||||
|
|
||||||
|
(3) properly assert the use of fields with an if attribute
|
||||||
|
- problem: the use of fields with an if attribute was not asserted in all
|
||||||
|
cases and asserted in the wrong way in some others due to the
|
||||||
|
corresponding BINPAC_ASSERT only called upon parsing the field
|
||||||
|
- solution: perform BINPAC_ASSERT upon calling the fields accessor
|
||||||
|
function
|
||||||
|
- moved BINPAC_ASSERT statement from LetField::GenEval to
|
||||||
|
Type::GenPubDecls
|
||||||
|
|
||||||
|
|
||||||
|
(4) incremental input with records with a non-negative StaticSize
|
||||||
|
- problem: incremental input with records with a StaticSize >= 0
|
||||||
|
cannot be performed due to necessary length attribute, leading to
|
||||||
|
an invalid call of GenBoundaryCheck in RecordType::DoGenParseCode
|
||||||
|
- solution: added a check for incremental input in
|
||||||
|
RecordType::DoGenParseCode before calling GenBoundaryCheck
|
||||||
|
|
||||||
|
|
||||||
|
(5) empty type with incremental input
|
||||||
|
- problem: with an empty type and incremental input, although the
|
||||||
|
Parse function is created, it is never called, leading to problems,
|
||||||
|
if additional actions are to be performed when encountering that
|
||||||
|
empty type
|
||||||
|
- solution: generate call to Parse of empty type in Type::GenParseBuffer
|
||||||
|
|
||||||
|
|
||||||
|
(6) parsing loop in flow ParseBuffer (while(true))
|
||||||
|
- problem: while(true) leads to problems after parsing of a type is
|
||||||
|
complete; at this time, it is unexpected that parsing continues, even
|
||||||
|
if no data is available in the flow buffer
|
||||||
|
- solution: check if data is available before starting a new parsing
|
||||||
|
cycle
|
||||||
|
- added a method data_available to FlowBuffer
|
||||||
|
- changed while(true) in FlowDecl::GenCodeFlowUnit to
|
||||||
|
while(flow_buffer_->data_available())
|
||||||
|
|
||||||
|
|
||||||
|
(7) initialization of flow buffer in CaseType with bufferable fields
|
||||||
|
in cases
|
||||||
|
- problem: initialization of buffer occurs in every Parse call,
|
||||||
|
regardless if it was initialized before or not; initialization
|
||||||
|
is correct only on first such occurence
|
||||||
|
- solution: check to buffer_state is to be created always when
|
||||||
|
buffering_state_id is in environment in Type::GenBufferConfig
|
||||||
|
- changed condition from buffering_state_var_field_ to
|
||||||
|
env->GetDataType(buffering_state_id)
|
||||||
|
|
||||||
|
|
||||||
|
(8) allowing init and cleanup code to be redefined, as well as addition
|
||||||
|
of code to FlowEOF calls in analyzer and flow
|
||||||
|
- problem 1: when refining an analyzer or flow definition, additional
|
||||||
|
init and cleanup code was not allowed, if these were already defined
|
||||||
|
before; this leads to problems when adding new members, as these
|
||||||
|
cannot be initialized and destroyed properly
|
||||||
|
- solution: allow init and cleanup code to be specified more than once
|
||||||
|
- changed deifnitions and usage of constructor_helper and
|
||||||
|
destructor_helper to allow for lists of constructor and destructor
|
||||||
|
helpers (similar to member declarations) in pac_analyzer.h and
|
||||||
|
pac_analyzer.cc
|
||||||
|
- problem 2: in some cases, it is desirable to execute code when
|
||||||
|
encountering the end of the input stream, which is not possible in
|
||||||
|
binpac
|
||||||
|
- solution: added a %eof binpac primitive similar to %init, which adds
|
||||||
|
code to the FlowEOF function of an analyzer or a flow
|
BIN
aux/binpac/patches/brosslbinpacanalyzerpatches.zip
Normal file
BIN
aux/binpac/patches/brosslbinpacanalyzerpatches.zip
Normal file
Binary file not shown.
172
aux/binpac/patches/nadi-bittorrent.patch
Normal file
172
aux/binpac/patches/nadi-bittorrent.patch
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
Index: pac_type.h
|
||||||
|
===================================================================
|
||||||
|
--- pac_type.h (revision 4130)
|
||||||
|
+++ pac_type.h (working copy)
|
||||||
|
@@ -78,12 +78,6 @@
|
||||||
|
string EvalByteOrder(Output *out_cc, Env *env) const;
|
||||||
|
|
||||||
|
virtual string EvalMember(const ID *member_id) const;
|
||||||
|
-#if 0
|
||||||
|
- // member_env() is used for finding a member of the type.
|
||||||
|
- // Thus member_env() of a ParameterizedType should return
|
||||||
|
- // ReferredDataType()->env()
|
||||||
|
- // virtual Env *member_env() const;
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
// The variable defined by the type
|
||||||
|
const ID *value_var() const { return value_var_; }
|
||||||
|
@@ -223,6 +217,8 @@
|
||||||
|
|
||||||
|
virtual bool ByteOrderSensitive() const = 0;
|
||||||
|
|
||||||
|
+ bool NeedsBufferingStateVar() const;
|
||||||
|
+
|
||||||
|
void GenBufferingLoop(Output* out_cc, Env* env, int flags);
|
||||||
|
void GenParseBuffer(Output* out_cc, Env* env, int flags);
|
||||||
|
void GenParseCode2(Output* out_cc, Env* env, const DataPtr& data, int flags);
|
||||||
|
Index: lib/binpac_buffer.h
|
||||||
|
===================================================================
|
||||||
|
--- lib/binpac_buffer.h (revision 4130)
|
||||||
|
+++ lib/binpac_buffer.h (working copy)
|
||||||
|
@@ -24,18 +24,18 @@
|
||||||
|
void DiscardData();
|
||||||
|
|
||||||
|
// Whether there is enough data for the frame
|
||||||
|
- bool ready() const{ return message_complete_; }
|
||||||
|
+ bool ready() const{ return message_complete_ || mode_ == UNKNOWN_MODE; }
|
||||||
|
|
||||||
|
inline const_byteptr begin() const
|
||||||
|
{
|
||||||
|
- BINPAC_ASSERT(message_complete_);
|
||||||
|
+ BINPAC_ASSERT(ready());
|
||||||
|
return ( buffer_n_ == 0 ) ?
|
||||||
|
orig_data_begin_ : buffer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_byteptr end() const
|
||||||
|
{
|
||||||
|
- BINPAC_ASSERT(message_complete_);
|
||||||
|
+ BINPAC_ASSERT(ready());
|
||||||
|
if ( buffer_n_ == 0 )
|
||||||
|
{
|
||||||
|
BINPAC_ASSERT(frame_length_ >= 0);
|
||||||
|
Index: pac_type.cc
|
||||||
|
===================================================================
|
||||||
|
--- pac_type.cc (revision 4130)
|
||||||
|
+++ pac_type.cc (working copy)
|
||||||
|
@@ -285,9 +285,8 @@
|
||||||
|
parsing_complete_var, extern_type_bool->Clone());
|
||||||
|
parsing_complete_var_field_->Prepare(env);
|
||||||
|
|
||||||
|
- if ( ( buffer_mode() == BUFFER_BY_LENGTH ||
|
||||||
|
- buffer_mode() == BUFFER_BY_LINE ) &&
|
||||||
|
- ! env->GetDataType(buffering_state_id) )
|
||||||
|
+ if ( NeedsBufferingStateVar() &&
|
||||||
|
+ !env->GetDataType(buffering_state_id) )
|
||||||
|
{
|
||||||
|
buffering_state_var_field_ = new PrivVarField(
|
||||||
|
buffering_state_id->clone(),
|
||||||
|
@@ -387,17 +386,17 @@
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUFFER_BY_LENGTH:
|
||||||
|
- if ( buffering_state_var_field_ )
|
||||||
|
- {
|
||||||
|
- out_cc->println("if ( %s == 0 )",
|
||||||
|
- env->RValue(buffering_state_id));
|
||||||
|
- out_cc->inc_indent();
|
||||||
|
- out_cc->println("{");
|
||||||
|
- }
|
||||||
|
+ if ( !NeedsBufferingStateVar() )
|
||||||
|
+ break;
|
||||||
|
|
||||||
|
+ ASSERT(env->GetDataType(buffering_state_id));
|
||||||
|
+ out_cc->println("if ( %s == 0 )",
|
||||||
|
+ env->RValue(buffering_state_id));
|
||||||
|
+ out_cc->inc_indent();
|
||||||
|
+ out_cc->println("{");
|
||||||
|
+
|
||||||
|
if ( attr_length_expr_ )
|
||||||
|
{
|
||||||
|
- // frame_buffer_arg = attr_length_expr_->EvalExpr(out_cc, env);
|
||||||
|
frame_buffer_arg = strfmt("%d", InitialBufferLength());
|
||||||
|
}
|
||||||
|
else if ( attr_restofflow_ )
|
||||||
|
@@ -407,7 +406,7 @@
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- frame_buffer_arg = strfmt("%d", InitialBufferLength());
|
||||||
|
+ ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_cc->println("%s->NewFrame(%s, %s);",
|
||||||
|
@@ -415,16 +414,14 @@
|
||||||
|
frame_buffer_arg.c_str(),
|
||||||
|
attr_chunked() ? "true" : "false");
|
||||||
|
|
||||||
|
- if ( buffering_state_var_field_ )
|
||||||
|
- {
|
||||||
|
- out_cc->println("%s = 1;",
|
||||||
|
- env->LValue(buffering_state_id));
|
||||||
|
- out_cc->println("}");
|
||||||
|
- out_cc->dec_indent();
|
||||||
|
- }
|
||||||
|
+ out_cc->println("%s = 1;",
|
||||||
|
+ env->LValue(buffering_state_id));
|
||||||
|
+ out_cc->println("}");
|
||||||
|
+ out_cc->dec_indent();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUFFER_BY_LINE:
|
||||||
|
+ ASSERT(env->GetDataType(buffering_state_id));
|
||||||
|
out_cc->println("if ( %s == 0 )",
|
||||||
|
env->RValue(buffering_state_id));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
@@ -890,6 +887,25 @@
|
||||||
|
return ! attr_byteorder_expr() && ByteOrderSensitive();
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool Type::NeedsBufferingStateVar() const
|
||||||
|
+ {
|
||||||
|
+ if ( !incremental_input() )
|
||||||
|
+ return false;
|
||||||
|
+ switch ( buffer_mode() )
|
||||||
|
+ {
|
||||||
|
+ case BUFFER_NOTHING:
|
||||||
|
+ case NOT_BUFFERABLE:
|
||||||
|
+ return false;
|
||||||
|
+ case BUFFER_BY_LINE:
|
||||||
|
+ return true;
|
||||||
|
+ case BUFFER_BY_LENGTH:
|
||||||
|
+ return ( attr_length_expr_ || attr_restofflow_ );
|
||||||
|
+ default:
|
||||||
|
+ ASSERT(0);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
bool Type::DoTraverse(DataDepVisitor *visitor)
|
||||||
|
{
|
||||||
|
foreach (i, FieldList, fields_)
|
||||||
|
Index: pac_flow.cc
|
||||||
|
===================================================================
|
||||||
|
--- pac_flow.cc (revision 4130)
|
||||||
|
+++ pac_flow.cc (working copy)
|
||||||
|
@@ -224,15 +224,13 @@
|
||||||
|
out_cc->println("catch ( Exception const &e )");
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
- out_cc->println("DEBUG_MSG(\"%%.6f binpac exception: %%s\\n\", network_time(), e.c_msg());");
|
||||||
|
GenCleanUpCode(out_cc);
|
||||||
|
if ( dataunit_->type() == AnalyzerDataUnit::FLOWUNIT )
|
||||||
|
{
|
||||||
|
out_cc->println("%s->DiscardData();",
|
||||||
|
env_->LValue(flow_buffer_id));
|
||||||
|
- out_cc->println("BINPAC_ASSERT(!%s->ready());",
|
||||||
|
- env_->RValue(flow_buffer_id));
|
||||||
|
}
|
||||||
|
+ out_cc->println("throw e;");
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
|
716
aux/binpac/shtool
Executable file
716
aux/binpac/shtool
Executable file
|
@ -0,0 +1,716 @@
|
||||||
|
#!/bin/sh
|
||||||
|
##
|
||||||
|
## GNU shtool -- The GNU Portable Shell Tool
|
||||||
|
## Copyright (c) 1994-2000 Ralf S. Engelschall <rse@engelschall.com>
|
||||||
|
##
|
||||||
|
## See http://www.gnu.org/software/shtool/ for more information.
|
||||||
|
## See ftp://ftp.gnu.org/gnu/shtool/ for latest version.
|
||||||
|
##
|
||||||
|
## Version 1.4.9 (16-Apr-2000)
|
||||||
|
## Ingredients: 3/17 available modules
|
||||||
|
##
|
||||||
|
|
||||||
|
##
|
||||||
|
## This program is free software; you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation; either version 2 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program is distributed in the hope that it will be useful,
|
||||||
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
## General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License
|
||||||
|
## along with this program; if not, write to the Free Software
|
||||||
|
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||||
|
## USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
|
||||||
|
##
|
||||||
|
## Notice: Given that you include this file verbatim into your own
|
||||||
|
## source tree, you are justified in saying that it remains separate
|
||||||
|
## from your package, and that this way you are simply just using GNU
|
||||||
|
## shtool. So, in this situation, there is no requirement that your
|
||||||
|
## package itself is licensed under the GNU General Public License in
|
||||||
|
## order to take advantage of GNU shtool.
|
||||||
|
##
|
||||||
|
|
||||||
|
##
|
||||||
|
## Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]
|
||||||
|
##
|
||||||
|
## Available commands:
|
||||||
|
## echo Print string with optional construct expansion
|
||||||
|
## install Install a program, script or datafile
|
||||||
|
## mkdir Make one or more directories
|
||||||
|
##
|
||||||
|
## Not available commands (because module was not built-in):
|
||||||
|
## mdate Pretty-print modification time of a file or dir
|
||||||
|
## table Pretty-print a field-separated list as a table
|
||||||
|
## prop Display progress with a running propeller
|
||||||
|
## move Move files with simultaneous substitution
|
||||||
|
## mkln Make link with calculation of relative paths
|
||||||
|
## mkshadow Make a shadow tree through symbolic links
|
||||||
|
## fixperm Fix file permissions inside a source tree
|
||||||
|
## tarball Roll distribution tarballs
|
||||||
|
## guessos Simple operating system guesser
|
||||||
|
## arx Extended archive command
|
||||||
|
## slo Separate linker options by library class
|
||||||
|
## scpp Sharing C Pre-Processor
|
||||||
|
## version Generate and maintain a version information file
|
||||||
|
## path Deal with program paths
|
||||||
|
##
|
||||||
|
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo "$0:Error: invalid command line" 1>&2
|
||||||
|
echo "$0:Hint: run \`$0 -h' for usage" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ".$1" = ".-h" -o ".$1" = ".--help" ]; then
|
||||||
|
echo "This is GNU shtool, version 1.4.9 (16-Apr-2000)"
|
||||||
|
echo "Copyright (c) 1994-2000 Ralf S. Engelschall <rse@engelschall.com>"
|
||||||
|
echo "Report bugs to <bug-shtool@gnu.org>"
|
||||||
|
echo ''
|
||||||
|
echo "Usage: shtool [<options>] [<cmd-name> [<cmd-options>] [<cmd-args>]]"
|
||||||
|
echo ''
|
||||||
|
echo 'Available global <options>:'
|
||||||
|
echo ' -v, --version display shtool version information'
|
||||||
|
echo ' -h, --help display shtool usage help page (this one)'
|
||||||
|
echo ' -d, --debug display shell trace information'
|
||||||
|
echo ''
|
||||||
|
echo 'Available <cmd-name> [<cmd-options>] [<cmd-args>]:'
|
||||||
|
echo ' echo [-n] [-e] [<str> ...]'
|
||||||
|
echo ' install [-v] [-t] [-c] [-C] [-s] [-m<mode>] [-o<owner>] [-g<group>]'
|
||||||
|
echo ' [-e<ext>] <file> <path>'
|
||||||
|
echo ' mkdir [-t] [-f] [-p] [-m<mode>] <dir> [<dir> ...]'
|
||||||
|
echo ''
|
||||||
|
echo 'Not available <cmd-name> (because module was not built-in):'
|
||||||
|
echo ' mdate [-n] [-z] [-s] [-d] [-f<str>] [-o<spec>] <path>'
|
||||||
|
echo ' table [-F<sep>] [-w<width>] [-c<cols>] [-s<strip>] <str><sep><str>...'
|
||||||
|
echo ' prop [-p<str>]'
|
||||||
|
echo ' move [-v] [-t] [-e] [-p] <src-file> <dst-file>'
|
||||||
|
echo ' mkln [-t] [-f] [-s] <src-path> [<src-path> ...] <dst-path>'
|
||||||
|
echo ' mkshadow [-v] [-t] [-a] <src-dir> <dst-dir>'
|
||||||
|
echo ' fixperm [-v] [-t] <path> [<path> ...]'
|
||||||
|
echo ' tarball [-t] [-v] [-o <tarball>] [-c <prog>] [-d <dir>] [-u'
|
||||||
|
echo ' <user>] [-g <group>] [-e <pattern>] <path> [<path> ...]'
|
||||||
|
echo ' guessos '
|
||||||
|
echo ' arx [-t] [-C<cmd>] <op> <archive> [<file> ...]'
|
||||||
|
echo ' slo [-p<str>] -- -L<dir> -l<lib> [-L<dir> -l<lib> ...]'
|
||||||
|
echo ' scpp [-v] [-p] [-f<filter>] [-o<ofile>] [-t<tfile>] [-M<mark>]'
|
||||||
|
echo ' [-D<dname>] [-C<cname>] <file> [<file> ...]'
|
||||||
|
echo ' version [-l<lang>] [-n<name>] [-p<prefix>] [-s<version>] [-i<knob>]'
|
||||||
|
echo ' [-d<type>] <file>'
|
||||||
|
echo ' path [-s] [-r] [-d] [-b] [-m] [-p<path>] <str> [<str> ...]'
|
||||||
|
echo ''
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [ ".$1" = ".-v" -o ".$1" = ."--version" ]; then
|
||||||
|
echo "GNU shtool 1.4.9 (16-Apr-2000)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [ ".$1" = ".-d" -o ".$1" = ."--debug" ]; then
|
||||||
|
shift
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
name=`echo "$0" | sed -e 's;.*/\([^/]*\)$;\1;' -e 's;-sh$;;' -e 's;\.sh$;;'`
|
||||||
|
case "$name" in
|
||||||
|
echo|install|mkdir )
|
||||||
|
# implicit tool command selection
|
||||||
|
tool="$name"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
# explicit tool command selection
|
||||||
|
tool="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
arg_spec=""
|
||||||
|
opt_spec=""
|
||||||
|
gen_tmpfile=no
|
||||||
|
|
||||||
|
##
|
||||||
|
## DISPATCH INTO SCRIPT PROLOG
|
||||||
|
##
|
||||||
|
|
||||||
|
case $tool in
|
||||||
|
echo )
|
||||||
|
str_tool="echo"
|
||||||
|
str_usage="[-n] [-e] [<str> ...]"
|
||||||
|
arg_spec="0+"
|
||||||
|
opt_spec="n.e."
|
||||||
|
opt_n=no
|
||||||
|
opt_e=no
|
||||||
|
;;
|
||||||
|
install )
|
||||||
|
str_tool="install"
|
||||||
|
str_usage="[-v] [-t] [-c] [-C] [-s] [-m<mode>] [-o<owner>] [-g<group>] [-e<ext>] <file> <path>"
|
||||||
|
arg_spec="2="
|
||||||
|
opt_spec="v.t.c.C.s.m:o:g:e:"
|
||||||
|
opt_v=no
|
||||||
|
opt_t=no
|
||||||
|
opt_c=no
|
||||||
|
opt_C=no
|
||||||
|
opt_s=no
|
||||||
|
opt_m=""
|
||||||
|
opt_o=""
|
||||||
|
opt_g=""
|
||||||
|
opt_e=""
|
||||||
|
;;
|
||||||
|
mkdir )
|
||||||
|
str_tool="mkdir"
|
||||||
|
str_usage="[-t] [-f] [-p] [-m<mode>] <dir> [<dir> ...]"
|
||||||
|
arg_spec="1+"
|
||||||
|
opt_spec="t.f.p.m:"
|
||||||
|
opt_t=no
|
||||||
|
opt_f=no
|
||||||
|
opt_p=no
|
||||||
|
opt_m=""
|
||||||
|
;;
|
||||||
|
-* )
|
||||||
|
echo "$0:Error: unknown option \`$tool'" 2>&1
|
||||||
|
echo "$0:Hint: run \`$0 -h' for usage" 2>&1
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo "$0:Error: unknown command \`$tool'" 2>&1
|
||||||
|
echo "$0:Hint: run \`$0 -h' for usage" 2>&1
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
##
|
||||||
|
## COMMON UTILITY CODE
|
||||||
|
##
|
||||||
|
|
||||||
|
# determine name of tool
|
||||||
|
if [ ".$tool" != . ]; then
|
||||||
|
# used inside shtool script
|
||||||
|
toolcmd="$0 $tool"
|
||||||
|
toolcmdhelp="shtool $tool"
|
||||||
|
msgprefix="shtool:$tool"
|
||||||
|
else
|
||||||
|
# used as standalone script
|
||||||
|
toolcmd="$0"
|
||||||
|
toolcmdhelp="sh $0"
|
||||||
|
msgprefix="$str_tool"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# parse argument specification string
|
||||||
|
eval `echo $arg_spec |\
|
||||||
|
sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
|
||||||
|
|
||||||
|
# parse option specification string
|
||||||
|
eval `echo h.$opt_spec |\
|
||||||
|
sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
|
||||||
|
|
||||||
|
# interate over argument line
|
||||||
|
opt_PREV=''
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
# special option stops processing
|
||||||
|
if [ ".$1" = ".--" ]; then
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
# determine option and argument
|
||||||
|
opt_ARG_OK=no
|
||||||
|
if [ ".$opt_PREV" != . ]; then
|
||||||
|
# merge previous seen option with argument
|
||||||
|
opt_OPT="$opt_PREV"
|
||||||
|
opt_ARG="$1"
|
||||||
|
opt_ARG_OK=yes
|
||||||
|
opt_PREV=''
|
||||||
|
else
|
||||||
|
# split argument into option and argument
|
||||||
|
case "$1" in
|
||||||
|
-[a-zA-Z0-9]*)
|
||||||
|
eval `echo "x$1" |\
|
||||||
|
sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
|
||||||
|
-e 's/";\(.*\)$/"; opt_ARG="\1"/'`
|
||||||
|
;;
|
||||||
|
-[a-zA-Z0-9])
|
||||||
|
opt_OPT=`echo "x$1" | cut -c3-`
|
||||||
|
opt_ARG=''
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# eat up option
|
||||||
|
shift
|
||||||
|
|
||||||
|
# determine whether option needs an argument
|
||||||
|
eval "opt_MODE=\$opt_MODE_${opt_OPT}"
|
||||||
|
if [ ".$opt_ARG" = . -a ".$opt_ARG_OK" != .yes ]; then
|
||||||
|
if [ ".$opt_MODE" = ".:" -o ".$opt_MODE" = ".+" ]; then
|
||||||
|
opt_PREV="$opt_OPT"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# process option
|
||||||
|
case $opt_MODE in
|
||||||
|
'.' )
|
||||||
|
# boolean option
|
||||||
|
eval "opt_${opt_OPT}=yes"
|
||||||
|
;;
|
||||||
|
':' )
|
||||||
|
# option with argument (multiple occurances override)
|
||||||
|
eval "opt_${opt_OPT}=\"\$opt_ARG\""
|
||||||
|
;;
|
||||||
|
'+' )
|
||||||
|
# option with argument (multiple occurances append)
|
||||||
|
eval "opt_${opt_OPT}=\"\$opt_${opt_OPT} \$opt_ARG\""
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
echo "$msgprefix:Error: unknown option: \`-$opt_OPT'" 1>&2
|
||||||
|
echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [ ".$opt_PREV" != . ]; then
|
||||||
|
echo "$msgprefix:Error: missing argument to option \`-$opt_PREV'" 1>&2
|
||||||
|
echo "$msgprefix:Hint: run \`$toolcmdhelp -h' or \`man shtool' for details" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# process help option
|
||||||
|
if [ ".$opt_h" = .yes ]; then
|
||||||
|
echo "Usage: $toolcmdhelp $str_usage"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# complain about incorrect number of arguments
|
||||||
|
case $arg_MODE in
|
||||||
|
'=' )
|
||||||
|
if [ $# -ne $arg_NUMS ]; then
|
||||||
|
echo "$msgprefix:Error: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
|
||||||
|
echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man shtool' for details" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
'+' )
|
||||||
|
if [ $# -lt $arg_NUMS ]; then
|
||||||
|
echo "$msgprefix:Error: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
|
||||||
|
echo "$msgprefix:Hint: run \`$toolcmd -h' or \`man shtool' for details" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# establish a temporary file on request
|
||||||
|
if [ ".$gen_tmpfile" = .yes ]; then
|
||||||
|
if [ ".$TMPDIR" != . ]; then
|
||||||
|
tmpdir="$TMPDIR"
|
||||||
|
elif [ ".$TEMPDIR" != . ]; then
|
||||||
|
tmpdir="$TEMPDIR"
|
||||||
|
else
|
||||||
|
tmpdir="/tmp"
|
||||||
|
fi
|
||||||
|
tmpfile="$tmpdir/.shtool.$$"
|
||||||
|
rm -f $tmpfile >/dev/null 2>&1
|
||||||
|
touch $tmpfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
##
|
||||||
|
## DISPATCH INTO SCRIPT BODY
|
||||||
|
##
|
||||||
|
|
||||||
|
case $tool in
|
||||||
|
|
||||||
|
echo )
|
||||||
|
##
|
||||||
|
## echo -- Print string with optional construct expansion
|
||||||
|
## Copyright (c) 1998-2000 Ralf S. Engelschall <rse@engelschall.com>
|
||||||
|
## Originally written for WML as buildinfo
|
||||||
|
##
|
||||||
|
|
||||||
|
text="$*"
|
||||||
|
|
||||||
|
# check for broken escape sequence expansion
|
||||||
|
seo=''
|
||||||
|
bytes=`echo '\1' | wc -c | awk '{ printf("%s", $1); }'`
|
||||||
|
if [ ".$bytes" != .3 ]; then
|
||||||
|
bytes=`echo -E '\1' | wc -c | awk '{ printf("%s", $1); }'`
|
||||||
|
if [ ".$bytes" = .3 ]; then
|
||||||
|
seo='-E'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# check for existing -n option (to suppress newline)
|
||||||
|
minusn=''
|
||||||
|
bytes=`echo -n 123 2>/dev/null | wc -c | awk '{ printf("%s", $1); }'`
|
||||||
|
if [ ".$bytes" = .3 ]; then
|
||||||
|
minusn='-n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# determine terminal bold sequence
|
||||||
|
term_bold=''
|
||||||
|
term_norm=''
|
||||||
|
if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[Bb]'`" != . ]; then
|
||||||
|
case $TERM in
|
||||||
|
# for the most important terminal types we directly know the sequences
|
||||||
|
xterm|xterm*|vt220|vt220*)
|
||||||
|
term_bold=`awk 'BEGIN { printf("%c%c%c%c", 27, 91, 49, 109); }' </dev/null 2>/dev/null`
|
||||||
|
term_norm=`awk 'BEGIN { printf("%c%c%c", 27, 91, 109); }' </dev/null 2>/dev/null`
|
||||||
|
;;
|
||||||
|
vt100|vt100*)
|
||||||
|
term_bold=`awk 'BEGIN { printf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); }' </dev/null 2>/dev/null`
|
||||||
|
term_norm=`awk 'BEGIN { printf("%c%c%c%c%c", 27, 91, 109, 0, 0); }' </dev/null 2>/dev/null`
|
||||||
|
;;
|
||||||
|
# for all others, we try to use a possibly existing `tput' or `tcout' utility
|
||||||
|
* )
|
||||||
|
paths=`echo $PATH | sed -e 's/:/ /g'`
|
||||||
|
for tool in tput tcout; do
|
||||||
|
for dir in $paths; do
|
||||||
|
if [ -r "$dir/$tool" ]; then
|
||||||
|
for seq in bold md smso; do # 'smso' is last
|
||||||
|
bold="`$dir/$tool $seq 2>/dev/null`"
|
||||||
|
if [ ".$bold" != . ]; then
|
||||||
|
term_bold="$bold"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ ".$term_bold" != . ]; then
|
||||||
|
for seq in sgr0 me rmso reset; do # 'reset' is last
|
||||||
|
norm="`$dir/$tool $seq 2>/dev/null`"
|
||||||
|
if [ ".$norm" != . ]; then
|
||||||
|
term_norm="$norm"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ ".$term_bold" != . -a ".$term_norm" != . ]; then
|
||||||
|
break;
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ ".$term_bold" = . -o ".$term_norm" = . ]; then
|
||||||
|
echo "$msgprefix:Warning: unable to determine terminal sequence for bold mode" 1>&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# determine user name
|
||||||
|
username=''
|
||||||
|
if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[uU]'`" != . ]; then
|
||||||
|
username="$LOGNAME"
|
||||||
|
if [ ".$username" = . ]; then
|
||||||
|
username="$USER"
|
||||||
|
if [ ".$username" = . ]; then
|
||||||
|
username="`(whoami) 2>/dev/null |\
|
||||||
|
awk '{ printf("%s", $1); }'`"
|
||||||
|
if [ ".$username" = . ]; then
|
||||||
|
username="`(who am i) 2>/dev/null |\
|
||||||
|
awk '{ printf("%s", $1); }'`"
|
||||||
|
if [ ".$username" = . ]; then
|
||||||
|
username='unknown'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# determine user id
|
||||||
|
userid=''
|
||||||
|
if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%U'`" != . ]; then
|
||||||
|
userid="`(id -u) 2>/dev/null`"
|
||||||
|
if [ ".$userid" = . ]; then
|
||||||
|
str="`(id) 2>/dev/null`"
|
||||||
|
if [ ".`echo $str | grep '^uid[ ]*=[ ]*[0-9]*('`" != . ]; then
|
||||||
|
userid=`echo $str | sed -e 's/^uid[ ]*=[ ]*//' -e 's/(.*//'`
|
||||||
|
fi
|
||||||
|
if [ ".$userid" = . ]; then
|
||||||
|
userid=`egrep "^${username}:" /etc/passwd 2>/dev/null | \
|
||||||
|
sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
|
||||||
|
if [ ".$userid" = . ]; then
|
||||||
|
userid=`(ypcat passwd) 2>/dev/null |
|
||||||
|
egrep "^${username}:" | \
|
||||||
|
sed -e 's/[^:]*:[^:]*://' -e 's/:.*$//'`
|
||||||
|
if [ ".$userid" = . ]; then
|
||||||
|
userid='?'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# determine host name
|
||||||
|
hostname=''
|
||||||
|
if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%h'`" != . ]; then
|
||||||
|
hostname="`(uname -n) 2>/dev/null |\
|
||||||
|
awk '{ printf("%s", $1); }'`"
|
||||||
|
if [ ".$hostname" = . ]; then
|
||||||
|
hostname="`(hostname) 2>/dev/null |\
|
||||||
|
awk '{ printf("%s", $1); }'`"
|
||||||
|
if [ ".$hostname" = . ]; then
|
||||||
|
hostname='unknown'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
case $hostname in
|
||||||
|
*.* )
|
||||||
|
domainname=".`echo $hostname | cut -d. -f2-`"
|
||||||
|
hostname="`echo $hostname | cut -d. -f1`"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# determine domain name
|
||||||
|
domainname=''
|
||||||
|
if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%d'`" != . ]; then
|
||||||
|
if [ ".$domainname" = . ]; then
|
||||||
|
if [ -f /etc/resolv.conf ]; then
|
||||||
|
domainname="`egrep '^[ ]*domain' /etc/resolv.conf | head -1 |\
|
||||||
|
sed -e 's/.*domain//' \
|
||||||
|
-e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \
|
||||||
|
-e 's/^\.//' -e 's/^/./' |\
|
||||||
|
awk '{ printf("%s", $1); }'`"
|
||||||
|
if [ ".$domainname" = . ]; then
|
||||||
|
domainname="`egrep '^[ ]*search' /etc/resolv.conf | head -1 |\
|
||||||
|
sed -e 's/.*search//' \
|
||||||
|
-e 's/^[ ]*//' -e 's/^ *//' -e 's/^ *//' \
|
||||||
|
-e 's/ .*//' -e 's/ .*//' \
|
||||||
|
-e 's/^\.//' -e 's/^/./' |\
|
||||||
|
awk '{ printf("%s", $1); }'`"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# determine current time
|
||||||
|
time_day=''
|
||||||
|
time_month=''
|
||||||
|
time_year=''
|
||||||
|
time_monthname=''
|
||||||
|
if [ ".$opt_e" = .yes -a ".`echo $text | egrep '%[DMYm]'`" != . ]; then
|
||||||
|
time_day=`date '+%d'`
|
||||||
|
time_month=`date '+%m'`
|
||||||
|
time_year=`date '+%Y' 2>/dev/null`
|
||||||
|
if [ ".$time_year" = . ]; then
|
||||||
|
time_year=`date '+%y'`
|
||||||
|
case $time_year in
|
||||||
|
[5-9][0-9]) time_year="19$time_year" ;;
|
||||||
|
[0-4][0-9]) time_year="20$time_year" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
case $time_month in
|
||||||
|
1|01) time_monthname='Jan' ;;
|
||||||
|
2|02) time_monthname='Feb' ;;
|
||||||
|
3|03) time_monthname='Mar' ;;
|
||||||
|
4|04) time_monthname='Apr' ;;
|
||||||
|
5|05) time_monthname='May' ;;
|
||||||
|
6|06) time_monthname='Jun' ;;
|
||||||
|
7|07) time_monthname='Jul' ;;
|
||||||
|
8|08) time_monthname='Aug' ;;
|
||||||
|
9|09) time_monthname='Sep' ;;
|
||||||
|
10) time_monthname='Oct' ;;
|
||||||
|
11) time_monthname='Nov' ;;
|
||||||
|
12) time_monthname='Dec' ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# expand special ``%x'' constructs
|
||||||
|
if [ ".$opt_e" = .yes ]; then
|
||||||
|
text=`echo $seo "$text" |\
|
||||||
|
sed -e "s/%B/${term_bold}/g" \
|
||||||
|
-e "s/%b/${term_norm}/g" \
|
||||||
|
-e "s/%u/${username}/g" \
|
||||||
|
-e "s/%U/${userid}/g" \
|
||||||
|
-e "s/%h/${hostname}/g" \
|
||||||
|
-e "s/%d/${domainname}/g" \
|
||||||
|
-e "s/%D/${time_day}/g" \
|
||||||
|
-e "s/%M/${time_month}/g" \
|
||||||
|
-e "s/%Y/${time_year}/g" \
|
||||||
|
-e "s/%m/${time_monthname}/g" 2>/dev/null`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# create output
|
||||||
|
if [ .$opt_n = .no ]; then
|
||||||
|
echo $seo "$text"
|
||||||
|
else
|
||||||
|
# the harder part: echo -n is best, because
|
||||||
|
# awk may complain about some \xx sequences.
|
||||||
|
if [ ".$minusn" != . ]; then
|
||||||
|
echo $seo $minusn "$text"
|
||||||
|
else
|
||||||
|
echo dummy | awk '{ printf("%s", TEXT); }' TEXT="$text"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
install )
|
||||||
|
##
|
||||||
|
## install -- Install a program, script or datafile
|
||||||
|
## Copyright (c) 1997-2000 Ralf S. Engelschall <rse@engelschall.com>
|
||||||
|
## Originally written for shtool
|
||||||
|
##
|
||||||
|
|
||||||
|
src="$1"
|
||||||
|
dst="$2"
|
||||||
|
|
||||||
|
# If destination is a directory, append the input filename
|
||||||
|
if [ -d $dst ]; then
|
||||||
|
dst=`echo "$dst" | sed -e 's:/$::'`
|
||||||
|
dstfile=`echo "$src" | sed -e 's;.*/\([^/]*\)$;\1;'`
|
||||||
|
dst="$dst/$dstfile"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add a possible extension to src and dst
|
||||||
|
if [ ".$opt_e" != . ]; then
|
||||||
|
src="$src$opt_e"
|
||||||
|
dst="$dst$opt_e"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for correct arguments
|
||||||
|
if [ ".$src" = ".$dst" ]; then
|
||||||
|
echo "$msgprefix:Error: source and destination are the same" 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make a temp file name in the destination directory
|
||||||
|
dstdir=`echo $dst | sed -e 's;[^/]*$;;' -e 's;\(.\)/$;\1;' -e 's;^$;.;'`
|
||||||
|
dsttmp="$dstdir/#INST@$$#"
|
||||||
|
|
||||||
|
# Verbosity
|
||||||
|
if [ ".$opt_v" = .yes ]; then
|
||||||
|
echo "$src -> $dst" 1>&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy or move the file name to the temp name
|
||||||
|
# (because we might be not allowed to change the source)
|
||||||
|
if [ ".$opt_C" = .yes ]; then
|
||||||
|
opt_c=yes
|
||||||
|
fi
|
||||||
|
if [ ".$opt_c" = .yes ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "cp $src $dsttmp" 1>&2
|
||||||
|
fi
|
||||||
|
cp $src $dsttmp || exit $?
|
||||||
|
else
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "mv $src $dsttmp" 1>&2
|
||||||
|
fi
|
||||||
|
mv $src $dsttmp || exit $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Adjust the target file
|
||||||
|
# (we do chmod last to preserve setuid bits)
|
||||||
|
if [ ".$opt_s" = .yes ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "strip $dsttmp" 1>&2
|
||||||
|
fi
|
||||||
|
strip $dsttmp || exit $?
|
||||||
|
fi
|
||||||
|
if [ ".$opt_o" != . ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "chown $opt_o $dsttmp" 1>&2
|
||||||
|
fi
|
||||||
|
chown $opt_o $dsttmp || exit $?
|
||||||
|
fi
|
||||||
|
if [ ".$opt_g" != . ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "chgrp $opt_g $dsttmp" 1>&2
|
||||||
|
fi
|
||||||
|
chgrp $opt_g $dsttmp || exit $?
|
||||||
|
fi
|
||||||
|
if [ ".$opt_m" != . ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "chmod $opt_m $dsttmp" 1>&2
|
||||||
|
fi
|
||||||
|
chmod $opt_m $dsttmp || exit $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine whether to do a quick install
|
||||||
|
# (has to be done _after_ the strip was already done)
|
||||||
|
quick=no
|
||||||
|
if [ ".$opt_C" = .yes ]; then
|
||||||
|
if [ -r $dst ]; then
|
||||||
|
if cmp -s $src $dst; then
|
||||||
|
quick=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Finally install the file to the real destination
|
||||||
|
if [ $quick = yes ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "rm -f $dsttmp" 1>&2
|
||||||
|
fi
|
||||||
|
rm -f $dsttmp
|
||||||
|
else
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "rm -f $dst && mv $dsttmp $dst" 1>&2
|
||||||
|
fi
|
||||||
|
rm -f $dst && mv $dsttmp $dst
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
mkdir )
|
||||||
|
##
|
||||||
|
## mkdir -- Make one or more directories
|
||||||
|
## Copyright (c) 1996-2000 Ralf S. Engelschall <rse@engelschall.com>
|
||||||
|
## Originally written for public domain by Noah Friedman <friedman@prep.ai.mit.edu>
|
||||||
|
## Cleaned up and enhanced for shtool
|
||||||
|
##
|
||||||
|
|
||||||
|
errstatus=0
|
||||||
|
for p in ${1+"$@"}; do
|
||||||
|
# if the directory already exists...
|
||||||
|
if [ -d "$p" ]; then
|
||||||
|
if [ ".$opt_f" = .no ] && [ ".$opt_p" = .no ]; then
|
||||||
|
echo "$msgprefix:Error: directory already exists: $p" 1>&2
|
||||||
|
errstatus=1
|
||||||
|
break
|
||||||
|
else
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# if the directory has to be created...
|
||||||
|
if [ ".$opt_p" = .no ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "mkdir $p" 1>&2
|
||||||
|
fi
|
||||||
|
mkdir $p || errstatus=$?
|
||||||
|
else
|
||||||
|
# the smart situation
|
||||||
|
set fnord `echo ":$p" |\
|
||||||
|
sed -e 's/^:\//%/' \
|
||||||
|
-e 's/^://' \
|
||||||
|
-e 's/\// /g' \
|
||||||
|
-e 's/^%/\//'`
|
||||||
|
shift
|
||||||
|
pathcomp=''
|
||||||
|
for d in ${1+"$@"}; do
|
||||||
|
pathcomp="$pathcomp$d"
|
||||||
|
case "$pathcomp" in
|
||||||
|
-* ) pathcomp="./$pathcomp" ;;
|
||||||
|
esac
|
||||||
|
if [ ! -d "$pathcomp" ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "mkdir $pathcomp" 1>&2
|
||||||
|
fi
|
||||||
|
mkdir $pathcomp || errstatus=$?
|
||||||
|
if [ ".$opt_m" != . ]; then
|
||||||
|
if [ ".$opt_t" = .yes ]; then
|
||||||
|
echo "chmod $opt_m $pathcomp" 1>&2
|
||||||
|
fi
|
||||||
|
chmod $opt_m $pathcomp || errstatus=$?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
pathcomp="$pathcomp/"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit $errstatus
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
##EOF##
|
62
aux/binpac/src/Makefile.am
Normal file
62
aux/binpac/src/Makefile.am
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
AM_YFLAGS = -d -t -v
|
||||||
|
AM_CPPFLAGS = -W -Wall -Wno-unused
|
||||||
|
|
||||||
|
noinst_PROGRAMS = binpac
|
||||||
|
|
||||||
|
binpac_SOURCES = \
|
||||||
|
pac_scan.ll pac_parse.yy \
|
||||||
|
pac_action.cc \
|
||||||
|
pac_analyzer.cc \
|
||||||
|
pac_array.cc \
|
||||||
|
pac_attr.cc \
|
||||||
|
pac_btype.cc \
|
||||||
|
pac_case.cc \
|
||||||
|
pac_conn.cc \
|
||||||
|
pac_context.cc \
|
||||||
|
pac_cstr.cc \
|
||||||
|
pac_datadep.cc \
|
||||||
|
pac_dataptr.cc \
|
||||||
|
pac_dataunit.cc \
|
||||||
|
pac_decl.cc \
|
||||||
|
pac_embedded.cc \
|
||||||
|
pac_enum.cc \
|
||||||
|
pac_expr.cc \
|
||||||
|
pac_exttype.cc \
|
||||||
|
pac_field.cc \
|
||||||
|
pac_flow.cc \
|
||||||
|
pac_func.cc \
|
||||||
|
pac_id.cc \
|
||||||
|
pac_inputbuf.cc \
|
||||||
|
pac_let.cc \
|
||||||
|
pac_param.cc \
|
||||||
|
pac_paramtype.cc \
|
||||||
|
pac_primitive.cc \
|
||||||
|
pac_record.cc \
|
||||||
|
pac_redef.cc \
|
||||||
|
pac_regex.cc \
|
||||||
|
pac_state.cc \
|
||||||
|
pac_strtype.cc \
|
||||||
|
pac_type.cc \
|
||||||
|
pac_typedecl.cc \
|
||||||
|
pac_withinput.cc \
|
||||||
|
pac_output.cc pac_utils.cc pac_exception.cc \
|
||||||
|
pac_main.cc \
|
||||||
|
pac_action.h pac_analyzer.h pac_array.h pac_attr.h pac_btype.h \
|
||||||
|
pac_case.h pac_cclass.h pac_common.h pac_conn.h pac_context.h \
|
||||||
|
pac_cstr.h pac_ctype.h pac_datadep.h pac_dataptr.h pac_dataunit.h \
|
||||||
|
pac_dbg.h pac_decl-inl.h pac_decl.h pac_embedded.h pac_enum.h \
|
||||||
|
pac_exception.h pac_expr.h pac_exttype.h pac_field.h pac_flow.h \
|
||||||
|
pac_func.h pac_id.h pac_inputbuf.h pac_let.h pac_number.h \
|
||||||
|
pac_output.h pac_param.h pac_paramtype.h pac_parse.h pac_primitive.h \
|
||||||
|
pac_record.h pac_redef.h pac_regex.h pac_state.h pac_strtype.h \
|
||||||
|
pac_type.h pac_typedecl.h pac_utils.h pac_varfield.h pac_withinput.h
|
||||||
|
|
||||||
|
EXTRA_DIST = pac_expr.def pac_type.def pac_externtype.def
|
||||||
|
|
||||||
|
DISTCLEANFILES = pac_parse.cc pac_parse.h pac_scan.cc y.output
|
||||||
|
|
||||||
|
# Manual rules below:
|
||||||
|
|
||||||
|
pac_scan.o: pac_parse.h
|
119
aux/binpac/src/pac_action.cc
Normal file
119
aux/binpac/src/pac_action.cc
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
#include "pac_embedded.h"
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
#include "pac_typedecl.h"
|
||||||
|
#include "pac_utils.h"
|
||||||
|
|
||||||
|
#include "pac_action.h"
|
||||||
|
|
||||||
|
AnalyzerAction::AnalyzerAction(ID *action_id,
|
||||||
|
When when,
|
||||||
|
ActionParam *param,
|
||||||
|
EmbeddedCode *code)
|
||||||
|
: AnalyzerElement(ACTION),
|
||||||
|
action_id_(action_id),
|
||||||
|
when_(when),
|
||||||
|
param_(param),
|
||||||
|
code_(code),
|
||||||
|
analyzer_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerAction::~AnalyzerAction()
|
||||||
|
{
|
||||||
|
delete action_id_;
|
||||||
|
delete param_;
|
||||||
|
delete code_;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AnalyzerAction::action_function() const
|
||||||
|
{
|
||||||
|
return strfmt("Action_%s", action_id_->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerAction::InstallHook(AnalyzerDecl *analyzer)
|
||||||
|
{
|
||||||
|
ASSERT(0);
|
||||||
|
analyzer_ = analyzer;
|
||||||
|
// param_->MainDataType()->InstallAction(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerAction::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl)
|
||||||
|
{
|
||||||
|
Env action_func_env(decl->env(), this);
|
||||||
|
action_func_env.AddID(param_->id(),
|
||||||
|
TEMP_VAR,
|
||||||
|
param_->DataType());
|
||||||
|
action_func_env.SetEvaluated(param_->id());
|
||||||
|
|
||||||
|
string action_func_proto =
|
||||||
|
strfmt("%s(%s)",
|
||||||
|
action_function().c_str(),
|
||||||
|
ParamDecls(&action_func_env).c_str());
|
||||||
|
|
||||||
|
out_h->println("void %s;", action_func_proto.c_str());
|
||||||
|
|
||||||
|
out_cc->println("void %s::%s",
|
||||||
|
decl->class_name().c_str(),
|
||||||
|
action_func_proto.c_str());
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
code_->GenCode(out_cc, &action_func_env);
|
||||||
|
|
||||||
|
out_cc->println("");
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
out_cc->println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
string AnalyzerAction::ParamDecls(Env *env) const
|
||||||
|
{
|
||||||
|
return param_->DeclStr(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *ActionParam::MainDataType() const
|
||||||
|
{
|
||||||
|
// Note: this is not equal to DataType()
|
||||||
|
Type *main_type = TypeDecl::LookUpType(type()->type_id());
|
||||||
|
|
||||||
|
if ( ! main_type )
|
||||||
|
{
|
||||||
|
throw Exception(type()->type_id(),
|
||||||
|
"type not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
return main_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *ActionParam::DataType() const
|
||||||
|
{
|
||||||
|
Type *main_type = MainDataType();
|
||||||
|
|
||||||
|
if ( ! type()->field_id() )
|
||||||
|
{
|
||||||
|
return main_type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Type *member_type =
|
||||||
|
main_type->MemberDataType(type()->field_id());
|
||||||
|
if ( ! member_type )
|
||||||
|
{
|
||||||
|
throw Exception(type()->field_id(),
|
||||||
|
fmt("cannot find member type for `%s.%s'",
|
||||||
|
type()->type_id()->Name(),
|
||||||
|
type()->field_id()->Name()));
|
||||||
|
}
|
||||||
|
return member_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string ActionParam::DeclStr(Env *env) const
|
||||||
|
{
|
||||||
|
return strfmt("%s %s",
|
||||||
|
DataType()->DataTypeStr().c_str(),
|
||||||
|
env->LValue(id()));
|
||||||
|
}
|
74
aux/binpac/src/pac_action.h
Normal file
74
aux/binpac/src/pac_action.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef pac_action_h
|
||||||
|
#define pac_action_h
|
||||||
|
|
||||||
|
// Classes representing analyzer actions.
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_analyzer.h"
|
||||||
|
|
||||||
|
class AnalyzerAction : public AnalyzerElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum When { BEFORE, AFTER };
|
||||||
|
|
||||||
|
AnalyzerAction(ID *action_id,
|
||||||
|
When when,
|
||||||
|
ActionParam *param,
|
||||||
|
EmbeddedCode *code);
|
||||||
|
|
||||||
|
~AnalyzerAction();
|
||||||
|
|
||||||
|
When when() const { return when_; }
|
||||||
|
ActionParam *param() const { return param_; }
|
||||||
|
AnalyzerDecl *analyzer() const { return analyzer_; }
|
||||||
|
string action_function() const;
|
||||||
|
|
||||||
|
// Generate function prototype and code for the action
|
||||||
|
void GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl);
|
||||||
|
|
||||||
|
// Install the hook at the corresponding data type parsing
|
||||||
|
// function to invoke the action.
|
||||||
|
void InstallHook(AnalyzerDecl *analyzer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string ParamDecls(Env *env) const;
|
||||||
|
|
||||||
|
ID *action_id_;
|
||||||
|
When when_;
|
||||||
|
ActionParam *param_;
|
||||||
|
EmbeddedCode *code_;
|
||||||
|
AnalyzerDecl *analyzer_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ActionParam
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActionParam(const ID *id, ActionParamType *type)
|
||||||
|
: id_(id), type_(type) {}
|
||||||
|
|
||||||
|
const ID *id() const { return id_; }
|
||||||
|
ActionParamType *type() const { return type_; }
|
||||||
|
|
||||||
|
Type *MainDataType() const;
|
||||||
|
Type *DataType() const;
|
||||||
|
string DeclStr(Env *env) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ID *id_;
|
||||||
|
ActionParamType *type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ActionParamType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ActionParamType(const ID *type_id, const ID *field_id = 0)
|
||||||
|
: type_id_(type_id), field_id_(field_id) {}
|
||||||
|
|
||||||
|
const ID *type_id() const { return type_id_; }
|
||||||
|
const ID *field_id() const { return field_id_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const ID *type_id_, *field_id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_action_h
|
358
aux/binpac/src/pac_analyzer.cc
Normal file
358
aux/binpac/src/pac_analyzer.cc
Normal file
|
@ -0,0 +1,358 @@
|
||||||
|
#include "pac_action.h"
|
||||||
|
#include "pac_context.h"
|
||||||
|
#include "pac_embedded.h"
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
#include "pac_flow.h"
|
||||||
|
#include "pac_func.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_param.h"
|
||||||
|
#include "pac_paramtype.h"
|
||||||
|
#include "pac_state.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
#include "pac_varfield.h"
|
||||||
|
|
||||||
|
#include "pac_analyzer.h"
|
||||||
|
|
||||||
|
AnalyzerDecl::AnalyzerDecl(ID *id,
|
||||||
|
DeclType decl_type,
|
||||||
|
ParamList *params)
|
||||||
|
: TypeDecl(id, params, new DummyType())
|
||||||
|
{
|
||||||
|
decl_type_ = decl_type;
|
||||||
|
|
||||||
|
statevars_ = new StateVarList();
|
||||||
|
actions_ = new AnalyzerActionList();
|
||||||
|
helpers_ = new AnalyzerHelperList();
|
||||||
|
functions_ = new FunctionList();
|
||||||
|
|
||||||
|
constructor_helpers_ = new AnalyzerHelperList();
|
||||||
|
destructor_helpers_ = new AnalyzerHelperList();
|
||||||
|
eof_helpers_ = new AnalyzerHelperList();
|
||||||
|
|
||||||
|
SetAnalyzerContext();
|
||||||
|
|
||||||
|
env_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerDecl::~AnalyzerDecl()
|
||||||
|
{
|
||||||
|
delete_list(StateVarList, statevars_);
|
||||||
|
delete_list(AnalyzerActionList, actions_);
|
||||||
|
delete_list(AnalyzerHelperList, helpers_);
|
||||||
|
delete_list(FunctionList, functions_);
|
||||||
|
delete_list(ParamList, params_);
|
||||||
|
delete_list(AnalyzerHelperList, constructor_helpers_);
|
||||||
|
delete_list(AnalyzerHelperList, destructor_helpers_);
|
||||||
|
delete_list(AnalyzerHelperList, eof_helpers_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::AddElements(AnalyzerElementList *elemlist)
|
||||||
|
{
|
||||||
|
ASSERT(! env_);
|
||||||
|
foreach(i, AnalyzerElementList, elemlist)
|
||||||
|
{
|
||||||
|
AnalyzerElement *elem = *i;
|
||||||
|
switch ( elem->type() )
|
||||||
|
{
|
||||||
|
case AnalyzerElement::STATE:
|
||||||
|
{
|
||||||
|
ASSERT(0);
|
||||||
|
AnalyzerState *state_elem =
|
||||||
|
(AnalyzerState *) elem;
|
||||||
|
statevars_->insert(
|
||||||
|
statevars_->end(),
|
||||||
|
state_elem->statevars()->begin(),
|
||||||
|
state_elem->statevars()->end());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AnalyzerElement::ACTION:
|
||||||
|
{
|
||||||
|
ASSERT(0);
|
||||||
|
AnalyzerAction *action_elem =
|
||||||
|
(AnalyzerAction *) elem;
|
||||||
|
actions_->push_back(action_elem);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AnalyzerElement::HELPER:
|
||||||
|
{
|
||||||
|
AnalyzerHelper *helper_elem =
|
||||||
|
(AnalyzerHelper *) elem;
|
||||||
|
|
||||||
|
switch ( helper_elem->helper_type() )
|
||||||
|
{
|
||||||
|
case AnalyzerHelper::INIT_CODE:
|
||||||
|
constructor_helpers_->push_back(helper_elem);
|
||||||
|
break;
|
||||||
|
case AnalyzerHelper::CLEANUP_CODE:
|
||||||
|
destructor_helpers_->push_back(helper_elem);
|
||||||
|
break;
|
||||||
|
case AnalyzerHelper::EOF_CODE:
|
||||||
|
eof_helpers_->push_back(helper_elem);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
helpers_->push_back(helper_elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AnalyzerElement::FUNCTION:
|
||||||
|
{
|
||||||
|
AnalyzerFunction *func_elem =
|
||||||
|
(AnalyzerFunction *) elem;
|
||||||
|
Function *func = func_elem->function();
|
||||||
|
func->set_analyzer_decl(this);
|
||||||
|
functions_->push_back(func);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AnalyzerElement::FLOW:
|
||||||
|
{
|
||||||
|
AnalyzerFlow *flow_elem =
|
||||||
|
(AnalyzerFlow *) elem;
|
||||||
|
ProcessFlowElement(flow_elem);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AnalyzerElement::DATAUNIT:
|
||||||
|
{
|
||||||
|
AnalyzerDataUnit *dataunit_elem =
|
||||||
|
(AnalyzerDataUnit *) elem;
|
||||||
|
ProcessDataUnitElement(dataunit_elem);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string AnalyzerDecl::class_name() const
|
||||||
|
{
|
||||||
|
return id_->Name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::Prepare()
|
||||||
|
{
|
||||||
|
TypeDecl::Prepare();
|
||||||
|
|
||||||
|
ASSERT(statevars_->empty());
|
||||||
|
ASSERT(actions_->empty());
|
||||||
|
|
||||||
|
foreach(i, FunctionList, functions_)
|
||||||
|
{
|
||||||
|
Function *function = *i;
|
||||||
|
function->Prepare(env_);
|
||||||
|
}
|
||||||
|
foreach(i, StateVarList, statevars_)
|
||||||
|
{
|
||||||
|
StateVar *statevar = *i;
|
||||||
|
env_->AddID(statevar->id(), STATE_VAR, statevar->type());
|
||||||
|
}
|
||||||
|
foreach(i, AnalyzerActionList, actions_)
|
||||||
|
{
|
||||||
|
AnalyzerAction *action = *i;
|
||||||
|
action->InstallHook(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenForwardDeclaration(Output* out_h)
|
||||||
|
{
|
||||||
|
out_h->println("class %s;", class_name().c_str());
|
||||||
|
foreach(i, FunctionList, functions_)
|
||||||
|
{
|
||||||
|
Function *function = *i;
|
||||||
|
function->GenForwardDeclaration(out_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenActions(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
foreach(i, AnalyzerActionList, actions_)
|
||||||
|
{
|
||||||
|
(*i)->GenCode(out_h, out_cc, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenHelpers(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
foreach(i, AnalyzerHelperList, helpers_)
|
||||||
|
{
|
||||||
|
(*i)->GenCode(out_h, out_cc, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenPubDecls(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
TypeDecl::GenPubDecls(out_h, out_cc);
|
||||||
|
|
||||||
|
GenProcessFunc(out_h, out_cc);
|
||||||
|
GenGapFunc(out_h, out_cc);
|
||||||
|
GenEOFFunc(out_h, out_cc);
|
||||||
|
out_h->println("");
|
||||||
|
|
||||||
|
if ( ! functions_->empty() )
|
||||||
|
{
|
||||||
|
out_h->println("// Functions");
|
||||||
|
GenFunctions(out_h, out_cc);
|
||||||
|
out_h->println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: export public state variables
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenPrivDecls(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
TypeDecl::GenPrivDecls(out_h, out_cc);
|
||||||
|
|
||||||
|
if ( ! helpers_->empty() )
|
||||||
|
{
|
||||||
|
out_h->println("");
|
||||||
|
out_h->println("// Additional members");
|
||||||
|
GenHelpers(out_h, out_cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: declare state variables
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenInitCode(Output *out_cc)
|
||||||
|
{
|
||||||
|
TypeDecl::GenInitCode(out_cc);
|
||||||
|
foreach(i, AnalyzerHelperList, constructor_helpers_)
|
||||||
|
{
|
||||||
|
(*i)->GenCode(0, out_cc, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenCleanUpCode(Output *out_cc)
|
||||||
|
{
|
||||||
|
TypeDecl::GenCleanUpCode(out_cc);
|
||||||
|
foreach(i, AnalyzerHelperList, destructor_helpers_)
|
||||||
|
{
|
||||||
|
(*i)->GenCode(0, out_cc, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenStateVarDecls(Output *out_h)
|
||||||
|
{
|
||||||
|
foreach(i, StateVarList, statevars_)
|
||||||
|
{
|
||||||
|
StateVar *var = *i;
|
||||||
|
var->GenDecl(out_h, env_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenStateVarSetFunctions(Output *out_h)
|
||||||
|
{
|
||||||
|
foreach(i, StateVarList, statevars_)
|
||||||
|
{
|
||||||
|
StateVar *var = *i;
|
||||||
|
var->GenSetFunction(out_h, env_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenStateVarInitCode(Output *out_cc)
|
||||||
|
{
|
||||||
|
foreach(i, StateVarList, statevars_)
|
||||||
|
{
|
||||||
|
StateVar *var = *i;
|
||||||
|
var->GenInitCode(out_cc, env_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenStateVarCleanUpCode(Output *out_cc)
|
||||||
|
{
|
||||||
|
foreach(i, StateVarList, statevars_)
|
||||||
|
{
|
||||||
|
StateVar *var = *i;
|
||||||
|
var->GenCleanUpCode(out_cc, env_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDecl::GenFunctions(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
foreach(i, FunctionList, functions_)
|
||||||
|
{
|
||||||
|
Function *function = *i;
|
||||||
|
function->GenCode(out_h, out_cc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerState::~AnalyzerState()
|
||||||
|
{
|
||||||
|
// Note: do not delete elements of statevars_, because they
|
||||||
|
// are referenced by the AnalyzerDecl.
|
||||||
|
delete statevars_;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerHelper::~AnalyzerHelper()
|
||||||
|
{
|
||||||
|
delete code_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerHelper::GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl)
|
||||||
|
{
|
||||||
|
Output *out = 0;
|
||||||
|
switch ( helper_type_ )
|
||||||
|
{
|
||||||
|
case MEMBER_DECLS:
|
||||||
|
out = out_h;
|
||||||
|
break;
|
||||||
|
case INIT_CODE:
|
||||||
|
case CLEANUP_CODE:
|
||||||
|
case EOF_CODE:
|
||||||
|
out = out_cc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ASSERT(out);
|
||||||
|
code()->GenCode(out, decl->env());
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowField::FlowField(ID *flow_id, ParameterizedType *flow_type)
|
||||||
|
: Field(FLOW_FIELD,
|
||||||
|
TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE,
|
||||||
|
flow_id, flow_type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowField::GenInitCode(Output *out_cc, Env *env)
|
||||||
|
{
|
||||||
|
type_->GenPreParsing(out_cc, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerFlow::AnalyzerFlow(Direction dir, ID *type_id, ExprList *params)
|
||||||
|
: AnalyzerElement(FLOW),
|
||||||
|
dir_(dir),
|
||||||
|
type_id_(type_id)
|
||||||
|
{
|
||||||
|
if ( ! params )
|
||||||
|
params = new ExprList();
|
||||||
|
|
||||||
|
// Add "this" to the list of params
|
||||||
|
params->insert(params->begin(), new Expr(this_id->clone()));
|
||||||
|
|
||||||
|
ID *flow_id = ((dir == UP) ? upflow_id : downflow_id)->clone();
|
||||||
|
|
||||||
|
ParameterizedType *flow_type = new ParameterizedType(type_id_, params);
|
||||||
|
|
||||||
|
flow_field_ = new FlowField(flow_id, flow_type);
|
||||||
|
|
||||||
|
flow_decl_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerFlow::~AnalyzerFlow()
|
||||||
|
{
|
||||||
|
delete flow_field_;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowDecl *AnalyzerFlow::flow_decl()
|
||||||
|
{
|
||||||
|
DEBUG_MSG("Getting flow_decl for %s\n", type_id_->Name());
|
||||||
|
if ( ! flow_decl_ )
|
||||||
|
{
|
||||||
|
Decl *decl = Decl::LookUpDecl(type_id_);
|
||||||
|
if ( decl && decl->decl_type() == Decl::FLOW )
|
||||||
|
flow_decl_ = static_cast<FlowDecl *>(decl);
|
||||||
|
if ( ! flow_decl_ )
|
||||||
|
{
|
||||||
|
throw Exception(this,
|
||||||
|
"cannot find the flow declaration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flow_decl_;
|
||||||
|
}
|
168
aux/binpac/src/pac_analyzer.h
Normal file
168
aux/binpac/src/pac_analyzer.h
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
#ifndef pac_analyzer_h
|
||||||
|
#define pac_analyzer_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_field.h"
|
||||||
|
#include "pac_typedecl.h"
|
||||||
|
|
||||||
|
class AnalyzerElement;
|
||||||
|
class AnalyzerState;
|
||||||
|
class AnalyzerAction; // defined in pac_action.h
|
||||||
|
class AnalyzerHelper;
|
||||||
|
class AnalyzerFlow;
|
||||||
|
class AnalyzerDataUnit;
|
||||||
|
class AnalyzerFunction;
|
||||||
|
class ConnDecl;
|
||||||
|
class FlowDecl;
|
||||||
|
typedef vector<AnalyzerHelper *> AnalyzerHelperList;
|
||||||
|
typedef vector<Function *> FunctionList;
|
||||||
|
|
||||||
|
class AnalyzerDecl : public TypeDecl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AnalyzerDecl(ID *id, DeclType decl_type, ParamList *params);
|
||||||
|
~AnalyzerDecl();
|
||||||
|
|
||||||
|
void AddElements(AnalyzerElementList *elemlist);
|
||||||
|
|
||||||
|
void Prepare();
|
||||||
|
void GenForwardDeclaration(Output *out_h);
|
||||||
|
// void GenCode(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
void GenInitCode(Output *out_cc);
|
||||||
|
void GenCleanUpCode(Output *out_cc);
|
||||||
|
|
||||||
|
string class_name() const;
|
||||||
|
// string cookie_name() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void ProcessFlowElement(AnalyzerFlow *flow_elem) = 0;
|
||||||
|
virtual void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem) = 0;
|
||||||
|
|
||||||
|
// Generate public/private declarations for member functions and
|
||||||
|
// variables
|
||||||
|
void GenPubDecls(Output *out_h, Output *out_cc);
|
||||||
|
void GenPrivDecls(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
// Generate the NewData() function
|
||||||
|
virtual void GenProcessFunc(Output *out_h, Output *out_cc) = 0;
|
||||||
|
|
||||||
|
// Generate the NewGap() function
|
||||||
|
virtual void GenGapFunc(Output *out_h, Output *out_cc) = 0;
|
||||||
|
|
||||||
|
// Generate the FlowEOF() function
|
||||||
|
virtual void GenEOFFunc(Output *out_h, Output *out_cc) = 0;
|
||||||
|
|
||||||
|
// Generate the functions
|
||||||
|
void GenFunctions(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
// Generate the action functions
|
||||||
|
void GenActions(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
// Generate the helper code segments
|
||||||
|
void GenHelpers(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
// Generate declarations for state variables and their set functions
|
||||||
|
void GenStateVarDecls(Output *out_h);
|
||||||
|
void GenStateVarSetFunctions(Output *out_h);
|
||||||
|
|
||||||
|
// Generate code for initializing and cleaning up (including
|
||||||
|
// memory de-allocating) state variables
|
||||||
|
void GenStateVarInitCode(Output *out_cc);
|
||||||
|
void GenStateVarCleanUpCode(Output *out_cc);
|
||||||
|
|
||||||
|
StateVarList *statevars_;
|
||||||
|
AnalyzerActionList *actions_;
|
||||||
|
AnalyzerHelperList *helpers_;
|
||||||
|
FunctionList *functions_;
|
||||||
|
|
||||||
|
AnalyzerHelperList *constructor_helpers_;
|
||||||
|
AnalyzerHelperList *destructor_helpers_;
|
||||||
|
AnalyzerHelperList *eof_helpers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AnalyzerElement : public Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ElementType { STATE, ACTION, FUNCTION, HELPER, FLOW, DATAUNIT };
|
||||||
|
AnalyzerElement(ElementType type)
|
||||||
|
: type_(type) {}
|
||||||
|
virtual ~AnalyzerElement() {}
|
||||||
|
|
||||||
|
ElementType type() const { return type_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElementType type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A collection of variables representing analyzer states.
|
||||||
|
class AnalyzerState : public AnalyzerElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AnalyzerState(StateVarList *statevars)
|
||||||
|
: AnalyzerElement(STATE),
|
||||||
|
statevars_(statevars) {}
|
||||||
|
~AnalyzerState();
|
||||||
|
|
||||||
|
StateVarList *statevars() const { return statevars_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
StateVarList *statevars_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A collection of embedded C++ code
|
||||||
|
class AnalyzerHelper : public AnalyzerElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Type {
|
||||||
|
MEMBER_DECLS,
|
||||||
|
INIT_CODE,
|
||||||
|
CLEANUP_CODE,
|
||||||
|
EOF_CODE,
|
||||||
|
};
|
||||||
|
AnalyzerHelper(Type helper_type, EmbeddedCode *code)
|
||||||
|
: AnalyzerElement(HELPER),
|
||||||
|
helper_type_(helper_type),
|
||||||
|
code_(code) {}
|
||||||
|
~AnalyzerHelper();
|
||||||
|
|
||||||
|
Type helper_type() const { return helper_type_; }
|
||||||
|
|
||||||
|
void GenCode(Output *out_h, Output *out_cc, AnalyzerDecl *decl);
|
||||||
|
|
||||||
|
EmbeddedCode *code() const { return code_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type helper_type_;
|
||||||
|
EmbeddedCode *code_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The type and parameters of (uni-directional) flows of a connection.
|
||||||
|
|
||||||
|
class FlowField : public Field
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FlowField(ID *flow_id, ParameterizedType *flow_type);
|
||||||
|
void GenInitCode(Output *out, Env *env);
|
||||||
|
};
|
||||||
|
|
||||||
|
class AnalyzerFlow : public AnalyzerElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Direction { UP, DOWN };
|
||||||
|
AnalyzerFlow(Direction dir, ID *type_id, ExprList *params);
|
||||||
|
~AnalyzerFlow();
|
||||||
|
|
||||||
|
Direction dir() const { return dir_; }
|
||||||
|
FlowField *flow_field() const { return flow_field_; }
|
||||||
|
|
||||||
|
FlowDecl *flow_decl();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Direction dir_;
|
||||||
|
ID *type_id_;
|
||||||
|
FlowField *flow_field_;
|
||||||
|
FlowDecl *flow_decl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_analyzer_h
|
700
aux/binpac/src/pac_array.cc
Normal file
700
aux/binpac/src/pac_array.cc
Normal file
|
@ -0,0 +1,700 @@
|
||||||
|
#include "pac_attr.h"
|
||||||
|
#include "pac_dataptr.h"
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
#include "pac_exttype.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_number.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_utils.h"
|
||||||
|
#include "pac_varfield.h"
|
||||||
|
|
||||||
|
#include "pac_array.h"
|
||||||
|
|
||||||
|
ArrayType::ArrayType(Type *elemtype, Expr *length)
|
||||||
|
: Type(ARRAY), elemtype_(elemtype), length_(length)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
|
switch ( elemtype_->tot() )
|
||||||
|
{
|
||||||
|
case BUILTIN:
|
||||||
|
case PARAMETERIZED:
|
||||||
|
case STRING:
|
||||||
|
case EXTERN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARRAY:
|
||||||
|
case CASE:
|
||||||
|
case DUMMY:
|
||||||
|
case EMPTY:
|
||||||
|
case RECORD:
|
||||||
|
case UNDEF:
|
||||||
|
ASSERT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::init()
|
||||||
|
{
|
||||||
|
arraylength_var_field_ = 0;
|
||||||
|
elem_it_var_field_ = 0;
|
||||||
|
elem_var_field_ = 0;
|
||||||
|
elem_dataptr_var_field_ = 0;
|
||||||
|
elem_input_var_field_ = 0;
|
||||||
|
|
||||||
|
elem_dataptr_until_expr_ = 0;
|
||||||
|
|
||||||
|
end_of_array_loop_label_ = "@@@";
|
||||||
|
|
||||||
|
vector_str_ = strfmt("vector<%s>", elemtype_->DataTypeStr().c_str());
|
||||||
|
|
||||||
|
datatype_str_ = strfmt("%s *", vector_str_.c_str());
|
||||||
|
|
||||||
|
attr_generic_until_expr_ = 0;
|
||||||
|
attr_until_element_expr_ = 0;
|
||||||
|
attr_until_input_expr_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayType::~ArrayType()
|
||||||
|
{
|
||||||
|
delete arraylength_var_field_;
|
||||||
|
delete elem_it_var_field_;
|
||||||
|
delete elem_var_field_;
|
||||||
|
delete elem_dataptr_var_field_;
|
||||||
|
delete elem_input_var_field_;
|
||||||
|
|
||||||
|
delete elem_dataptr_until_expr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *ArrayType::DoClone() const
|
||||||
|
{
|
||||||
|
Type *elemtype = elemtype_->Clone();
|
||||||
|
if ( ! elemtype )
|
||||||
|
return 0;
|
||||||
|
return new ArrayType(elemtype, length_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArrayType::DefineValueVar() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string ArrayType::DataTypeStr() const
|
||||||
|
{
|
||||||
|
return datatype_str_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *ArrayType::ElementDataType() const
|
||||||
|
{
|
||||||
|
return elemtype_;
|
||||||
|
}
|
||||||
|
|
||||||
|
string ArrayType::EvalElement(const string &array, const string &index) const
|
||||||
|
{
|
||||||
|
return strfmt("(*(%s))[%s]", array.c_str(), index.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
const ID *ArrayType::arraylength_var() const
|
||||||
|
{
|
||||||
|
return arraylength_var_field_ ? arraylength_var_field_->id() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ID *ArrayType::elem_it_var() const
|
||||||
|
{
|
||||||
|
return elem_it_var_field_ ? elem_it_var_field_->id() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ID *ArrayType::elem_var() const
|
||||||
|
{
|
||||||
|
return elem_var_field_ ? elem_var_field_->id() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ID *ArrayType::elem_dataptr_var() const
|
||||||
|
{
|
||||||
|
return elem_dataptr_var_field_ ? elem_dataptr_var_field_->id() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ID *ArrayType::elem_input_var() const
|
||||||
|
{
|
||||||
|
return elem_input_var_field_ ? elem_input_var_field_->id() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::ProcessAttr(Attr *a)
|
||||||
|
{
|
||||||
|
Type::ProcessAttr(a);
|
||||||
|
|
||||||
|
switch ( a->type() )
|
||||||
|
{
|
||||||
|
case ATTR_RESTOFDATA:
|
||||||
|
{
|
||||||
|
if ( elemtype_->StaticSize(env()) != 1 )
|
||||||
|
{
|
||||||
|
throw Exception(elemtype_,
|
||||||
|
"&restofdata can be applied"
|
||||||
|
" to only byte arrays");
|
||||||
|
}
|
||||||
|
if ( length_ )
|
||||||
|
{
|
||||||
|
throw Exception(length_,
|
||||||
|
"&restofdata cannot be applied"
|
||||||
|
" to arrays with specified length");
|
||||||
|
}
|
||||||
|
attr_restofdata_ = true;
|
||||||
|
// As the array automatically extends to the end of
|
||||||
|
// data, we do not have to check boundary.
|
||||||
|
SetBoundaryChecked();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ATTR_RESTOFFLOW:
|
||||||
|
attr_restofflow_ = true;
|
||||||
|
// TODO: handle &restofflow
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ATTR_UNTIL:
|
||||||
|
{
|
||||||
|
bool ref_element = a->expr()->HasReference(element_macro_id);
|
||||||
|
bool ref_input = a->expr()->HasReference(input_macro_id);
|
||||||
|
if ( ref_element && ref_input )
|
||||||
|
{
|
||||||
|
throw Exception(a->expr(),
|
||||||
|
"cannot reference both $element and $input "
|
||||||
|
"in the same &until---please separate them.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ref_element )
|
||||||
|
{
|
||||||
|
if ( attr_until_element_expr_ )
|
||||||
|
{
|
||||||
|
throw Exception(a->expr(),
|
||||||
|
"multiple &until on $element");
|
||||||
|
}
|
||||||
|
attr_until_element_expr_ = a->expr();
|
||||||
|
}
|
||||||
|
else if ( ref_input )
|
||||||
|
{
|
||||||
|
if ( attr_until_input_expr_ )
|
||||||
|
{
|
||||||
|
throw Exception(a->expr(),
|
||||||
|
"multiple &until on $input");
|
||||||
|
}
|
||||||
|
attr_until_input_expr_ = a->expr();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( attr_generic_until_expr_ )
|
||||||
|
{
|
||||||
|
throw Exception(a->expr(),
|
||||||
|
"multiple &until condition");
|
||||||
|
}
|
||||||
|
attr_generic_until_expr_ = a->expr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::Prepare(Env *env, int flags)
|
||||||
|
{
|
||||||
|
if ( flags & TO_BE_PARSED )
|
||||||
|
{
|
||||||
|
ID *arraylength_var = new ID(fmt("%s__arraylength", value_var()->Name()));
|
||||||
|
ID *elem_var = new ID(fmt("%s__elem", value_var()->Name()));
|
||||||
|
ID *elem_it_var = new ID(fmt("%s__it", elem_var->Name()));
|
||||||
|
|
||||||
|
elem_var_field_ =
|
||||||
|
new ParseVarField(Field::CLASS_MEMBER, elem_var, elemtype_);
|
||||||
|
AddField(elem_var_field_);
|
||||||
|
|
||||||
|
if ( incremental_parsing() )
|
||||||
|
{
|
||||||
|
arraylength_var_field_ =
|
||||||
|
new PrivVarField(arraylength_var, extern_type_int->Clone());
|
||||||
|
elem_it_var_field_ =
|
||||||
|
new PrivVarField(elem_it_var, extern_type_int->Clone());
|
||||||
|
|
||||||
|
AddField(arraylength_var_field_);
|
||||||
|
AddField(elem_it_var_field_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arraylength_var_field_ =
|
||||||
|
new TempVarField(arraylength_var, extern_type_int->Clone());
|
||||||
|
elem_it_var_field_ =
|
||||||
|
new TempVarField(elem_it_var, extern_type_int->Clone());
|
||||||
|
|
||||||
|
arraylength_var_field_->Prepare(env);
|
||||||
|
elem_it_var_field_->Prepare(env);
|
||||||
|
|
||||||
|
// Add elem_dataptr_var only when not parsing incrementally
|
||||||
|
ID *elem_dataptr_var =
|
||||||
|
new ID(fmt("%s__dataptr", elem_var->Name()));
|
||||||
|
elem_dataptr_var_field_ = new TempVarField(
|
||||||
|
elem_dataptr_var,
|
||||||
|
extern_type_const_byteptr->Clone());
|
||||||
|
elem_dataptr_var_field_->Prepare(env);
|
||||||
|
|
||||||
|
// until(dataptr >= end_of_data)
|
||||||
|
elem_dataptr_until_expr_ = new Expr(
|
||||||
|
Expr::EXPR_GE,
|
||||||
|
new Expr(elem_dataptr_var->clone()),
|
||||||
|
new Expr(end_of_data->clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( attr_until_input_expr_ )
|
||||||
|
{
|
||||||
|
elemtype_->SetUntilCheck(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
end_of_array_loop_label_ = strfmt("end_of_%s", value_var()->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Prepare(env, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenArrayLength(Output *out_cc, Env *env, const DataPtr& data)
|
||||||
|
{
|
||||||
|
if ( env->Evaluated(arraylength_var()) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ! incremental_parsing() )
|
||||||
|
{
|
||||||
|
arraylength_var_field_->GenTempDecls(out_cc, env);
|
||||||
|
arraylength_var_field_->GenInitCode(out_cc, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( length_ )
|
||||||
|
{
|
||||||
|
out_cc->println("%s = %s;",
|
||||||
|
env->LValue(arraylength_var()),
|
||||||
|
length_->EvalExpr(out_cc, env));
|
||||||
|
|
||||||
|
env->SetEvaluated(arraylength_var());
|
||||||
|
|
||||||
|
// Check for overlong array length. We cap it at the
|
||||||
|
// maximum data size as we won't store more elements.
|
||||||
|
out_cc->println("if ( t_begin_of_data + %s > t_end_of_data + 1 )",
|
||||||
|
env->LValue(arraylength_var()));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
out_cc->println("%s = t_end_of_data - t_begin_of_data + 1;",
|
||||||
|
env->LValue(arraylength_var()));
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
|
||||||
|
// Check negative array length
|
||||||
|
out_cc->println("if ( %s < 0 )",
|
||||||
|
env->LValue(arraylength_var()));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
out_cc->println("%s = 0;",
|
||||||
|
env->LValue(arraylength_var()));
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
else if ( attr_restofdata_ )
|
||||||
|
{
|
||||||
|
ASSERT(elemtype_->StaticSize(env) == 1);
|
||||||
|
out_cc->println("%s = (%s) - (%s);",
|
||||||
|
env->LValue(arraylength_var()),
|
||||||
|
env->RValue(end_of_data),
|
||||||
|
data.ptr_expr());
|
||||||
|
env->SetEvaluated(arraylength_var());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenPubDecls(Output *out_h, Env *env)
|
||||||
|
{
|
||||||
|
Type::GenPubDecls(out_h, env);
|
||||||
|
|
||||||
|
if ( declared_as_type() )
|
||||||
|
{
|
||||||
|
out_h->println("int size() const { return %s ? %s->size() : 0; }",
|
||||||
|
env->RValue(value_var()),
|
||||||
|
env->RValue(value_var()));
|
||||||
|
out_h->println("%s operator[](int index) const { BINPAC_ASSERT(%s); return (*%s)[index]; }",
|
||||||
|
elemtype_->DataTypeConstRefStr().c_str(),
|
||||||
|
env->RValue(value_var()),
|
||||||
|
env->RValue(value_var()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenPrivDecls(Output *out_h, Env *env)
|
||||||
|
{
|
||||||
|
ASSERT(elem_var_field_->type() == elemtype_);
|
||||||
|
ASSERT(elemtype_->value_var());
|
||||||
|
Type::GenPrivDecls(out_h, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenInitCode(Output *out_cc, Env *env)
|
||||||
|
{
|
||||||
|
// Do not initiate the array here
|
||||||
|
// out_cc->println("%s = new %s;", lvalue(), vector_str_.c_str());
|
||||||
|
out_cc->println("%s = 0;", lvalue());
|
||||||
|
|
||||||
|
Type::GenInitCode(out_cc, env);
|
||||||
|
if ( incremental_parsing() )
|
||||||
|
{
|
||||||
|
out_cc->println("%s = -1;",
|
||||||
|
env->LValue(elem_it_var()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenCleanUpCode(Output *out_cc, Env *env)
|
||||||
|
{
|
||||||
|
Type::GenCleanUpCode(out_cc, env);
|
||||||
|
if ( elemtype_->NeedsCleanUp() )
|
||||||
|
{
|
||||||
|
if ( ! elem_var_field_ )
|
||||||
|
{
|
||||||
|
ID *elem_var = new ID(fmt("%s__elem", value_var()->Name()));
|
||||||
|
elem_var_field_ =
|
||||||
|
new ParseVarField(
|
||||||
|
Field::NOT_CLASS_MEMBER,
|
||||||
|
elem_var,
|
||||||
|
elemtype_);
|
||||||
|
elem_var_field_->Prepare(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_cc->println("if ( %s )", env->RValue(value_var()));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
out_cc->println("for ( int i = 0; i < (int) %s->size(); ++i )",
|
||||||
|
env->RValue(value_var()));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
out_cc->println("%s %s = (*%s)[i];",
|
||||||
|
elemtype_->DataTypeStr().c_str(),
|
||||||
|
env->LValue(elem_var()),
|
||||||
|
lvalue());
|
||||||
|
elemtype_->GenCleanUpCode(out_cc, env);
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
out_cc->println("delete %s;", lvalue());
|
||||||
|
}
|
||||||
|
|
||||||
|
string ArrayType::GenArrayInit(Output *out_cc, Env *env, bool known_array_length)
|
||||||
|
{
|
||||||
|
string array_str;
|
||||||
|
|
||||||
|
array_str = lvalue();
|
||||||
|
if ( incremental_parsing() )
|
||||||
|
{
|
||||||
|
out_cc->println("if ( %s < 0 )",
|
||||||
|
env->LValue(elem_it_var()));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
out_cc->println("// Initialize only once");
|
||||||
|
out_cc->println("%s = 0;", env->LValue(elem_it_var()));
|
||||||
|
}
|
||||||
|
|
||||||
|
out_cc->println("%s = new %s;",
|
||||||
|
lvalue(), vector_str_.c_str());
|
||||||
|
|
||||||
|
if ( known_array_length )
|
||||||
|
{
|
||||||
|
out_cc->println("%s->reserve(%s);",
|
||||||
|
lvalue(), env->RValue(arraylength_var()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( incremental_parsing() )
|
||||||
|
{
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenElementAssignment(Output *out_cc, Env *env,
|
||||||
|
string const &array_str, bool use_vector)
|
||||||
|
{
|
||||||
|
// Assign the element
|
||||||
|
if ( ! use_vector )
|
||||||
|
{
|
||||||
|
out_cc->println("%s[%s] = %s;",
|
||||||
|
array_str.c_str(),
|
||||||
|
env->LValue(elem_it_var()),
|
||||||
|
env->LValue(elem_var()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_cc->println("%s->push_back(%s);",
|
||||||
|
array_str.c_str(),
|
||||||
|
env->LValue(elem_var()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::DoGenParseCode(Output *out_cc, Env *env,
|
||||||
|
const DataPtr& data, int flags)
|
||||||
|
{
|
||||||
|
GenArrayLength(out_cc, env, data);
|
||||||
|
|
||||||
|
// Otherwise these variables are declared as member variables
|
||||||
|
if ( ! incremental_parsing() )
|
||||||
|
{
|
||||||
|
// Declare and initialize temporary variables
|
||||||
|
elem_var_field_->GenInitCode(out_cc, env);
|
||||||
|
elem_it_var_field_->GenTempDecls(out_cc, env);
|
||||||
|
out_cc->println("%s = 0;", env->LValue(elem_it_var()));
|
||||||
|
env->SetEvaluated(elem_it_var());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the input length can be determined without parsing
|
||||||
|
individual elements, generate the boundary checking before
|
||||||
|
parsing (unless in the case of incremental parsing).
|
||||||
|
|
||||||
|
There are two cases when the input length can be determined:
|
||||||
|
1. The array has a static size;
|
||||||
|
2. The array length can be computed before parsing and
|
||||||
|
each element is of constant size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool compute_size_var = false;
|
||||||
|
|
||||||
|
if ( incremental_input() )
|
||||||
|
{
|
||||||
|
// Do not compute size_var on incremental input
|
||||||
|
compute_size_var = false;
|
||||||
|
|
||||||
|
if ( ! incremental_parsing() &&
|
||||||
|
( StaticSize(env) >= 0 ||
|
||||||
|
( env->Evaluated(arraylength_var()) &&
|
||||||
|
elemtype_->StaticSize(env) >= 0 ) ) )
|
||||||
|
{
|
||||||
|
GenBoundaryCheck(out_cc, env, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
compute_size_var = AddSizeVar(out_cc, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool known_array_length = env->Evaluated(arraylength_var());
|
||||||
|
string array_str = GenArrayInit(out_cc, env, known_array_length);
|
||||||
|
|
||||||
|
bool use_vector = true;
|
||||||
|
|
||||||
|
ASSERT(elem_it_var());
|
||||||
|
|
||||||
|
DataPtr elem_data(env, 0, 0);
|
||||||
|
|
||||||
|
if ( elem_dataptr_var() )
|
||||||
|
{
|
||||||
|
out_cc->println("const_byteptr %s = %s;",
|
||||||
|
env->LValue(elem_dataptr_var()), data.ptr_expr());
|
||||||
|
env->SetEvaluated(elem_dataptr_var());
|
||||||
|
|
||||||
|
elem_data = DataPtr(env, elem_dataptr_var(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
string for_condition = known_array_length ?
|
||||||
|
strfmt("%s < %s",
|
||||||
|
env->LValue(elem_it_var()),
|
||||||
|
env->RValue(arraylength_var())) :
|
||||||
|
"/* forever */";
|
||||||
|
|
||||||
|
out_cc->println("for (; %s; ++%s)",
|
||||||
|
for_condition.c_str(),
|
||||||
|
env->LValue(elem_it_var()));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
if ( attr_generic_until_expr_ )
|
||||||
|
GenUntilCheck(out_cc, env, attr_generic_until_expr_, true);
|
||||||
|
|
||||||
|
if ( elem_dataptr_var() )
|
||||||
|
GenUntilCheck(out_cc, env, elem_dataptr_until_expr_, false);
|
||||||
|
|
||||||
|
elemtype_->GenPreParsing(out_cc, env);
|
||||||
|
elemtype_->GenParseCode(out_cc, env, elem_data, flags);
|
||||||
|
|
||||||
|
if ( incremental_parsing() )
|
||||||
|
{
|
||||||
|
out_cc->println("if ( ! %s )",
|
||||||
|
elemtype_->parsing_complete(env).c_str());
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("goto %s;", kNeedMoreData);
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
GenElementAssignment(out_cc, env, array_str, use_vector);
|
||||||
|
|
||||||
|
if ( elem_dataptr_var() )
|
||||||
|
{
|
||||||
|
out_cc->println("%s += %s;",
|
||||||
|
env->LValue(elem_dataptr_var()),
|
||||||
|
elemtype_->DataSize(0, env, elem_data).c_str());
|
||||||
|
out_cc->println("BINPAC_ASSERT(%s <= %s);",
|
||||||
|
env->RValue(elem_dataptr_var()),
|
||||||
|
env->RValue(end_of_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( attr_until_element_expr_ )
|
||||||
|
GenUntilCheck(out_cc, env, attr_until_element_expr_, false);
|
||||||
|
|
||||||
|
if ( elemtype_->IsPointerType() )
|
||||||
|
out_cc->println("%s = 0;", env->LValue(elem_var()));
|
||||||
|
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
|
||||||
|
out_cc->dec_indent();
|
||||||
|
out_cc->println("%s: ;", end_of_array_loop_label_.c_str());
|
||||||
|
out_cc->inc_indent();
|
||||||
|
|
||||||
|
if ( compute_size_var && elem_dataptr_var() && ! env->Evaluated(size_var()) )
|
||||||
|
{
|
||||||
|
// Compute the data size
|
||||||
|
out_cc->println("%s = %s - (%s);",
|
||||||
|
env->LValue(size_var()),
|
||||||
|
env->RValue(elem_dataptr_var()),
|
||||||
|
data.ptr_expr());
|
||||||
|
env->SetEvaluated(size_var());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenUntilInputCheck(Output *out_cc, Env *env)
|
||||||
|
{
|
||||||
|
ID *elem_input_var_id = new ID(
|
||||||
|
fmt("%s__elem_input", value_var()->Name()));
|
||||||
|
elem_input_var_field_ = new TempVarField(
|
||||||
|
elem_input_var_id, extern_type_const_bytestring->Clone());
|
||||||
|
elem_input_var_field_->Prepare(env);
|
||||||
|
|
||||||
|
out_cc->println("%s %s(%s, %s);",
|
||||||
|
extern_type_const_bytestring->DataTypeStr().c_str(),
|
||||||
|
env->LValue(elem_input_var()),
|
||||||
|
env->RValue(begin_of_data),
|
||||||
|
env->RValue(end_of_data));
|
||||||
|
env->SetEvaluated(elem_input_var());
|
||||||
|
|
||||||
|
GenUntilCheck(out_cc, env, attr_until_input_expr_, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenUntilCheck(Output *out_cc, Env *env,
|
||||||
|
Expr *until_expr, bool delete_elem)
|
||||||
|
{
|
||||||
|
ASSERT(until_expr);
|
||||||
|
|
||||||
|
Env check_env(env, this);
|
||||||
|
check_env.AddMacro(element_macro_id,
|
||||||
|
new Expr(elem_var()->clone()));
|
||||||
|
if ( elem_input_var() )
|
||||||
|
{
|
||||||
|
check_env.AddMacro(input_macro_id,
|
||||||
|
new Expr(elem_input_var()->clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
out_cc->println("// Check &until(%s)", until_expr->orig());
|
||||||
|
out_cc->println("if ( %s )",
|
||||||
|
until_expr->EvalExpr(out_cc, &check_env));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
if ( parsing_complete_var() )
|
||||||
|
{
|
||||||
|
out_cc->println("%s = true;",
|
||||||
|
env->LValue(parsing_complete_var()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( elemtype_->IsPointerType() )
|
||||||
|
{
|
||||||
|
if ( delete_elem )
|
||||||
|
elemtype_->GenCleanUpCode(out_cc, env);
|
||||||
|
else
|
||||||
|
out_cc->println("%s = 0;", env->LValue(elem_var()));
|
||||||
|
}
|
||||||
|
|
||||||
|
out_cc->println("goto %s;", end_of_array_loop_label_.c_str());
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::GenDynamicSize(Output *out_cc, Env *env,
|
||||||
|
const DataPtr& data)
|
||||||
|
{
|
||||||
|
ASSERT(! incremental_input());
|
||||||
|
DEBUG_MSG("Generating dynamic size for array `%s'\n",
|
||||||
|
value_var()->Name());
|
||||||
|
|
||||||
|
int elem_w = elemtype_->StaticSize(env);
|
||||||
|
if ( elem_w >= 0 &&
|
||||||
|
! attr_until_element_expr_ &&
|
||||||
|
! attr_until_input_expr_ &&
|
||||||
|
( length_ || attr_restofdata_ ) )
|
||||||
|
{
|
||||||
|
// If the elements have a fixed size,
|
||||||
|
// we only need to compute the number of elements
|
||||||
|
bool compute_size_var = AddSizeVar(out_cc, env);
|
||||||
|
ASSERT(compute_size_var);
|
||||||
|
GenArrayLength(out_cc, env, data);
|
||||||
|
ASSERT(env->Evaluated(arraylength_var()));
|
||||||
|
out_cc->println("%s = %d * %s;",
|
||||||
|
env->LValue(size_var()), elem_w, env->RValue(arraylength_var()));
|
||||||
|
env->SetEvaluated(size_var());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise we need parse the array dynamically
|
||||||
|
GenParseCode(out_cc, env, data, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ArrayType::StaticSize(Env *env) const
|
||||||
|
{
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
if ( ! length_ || ! length_->ConstFold(env, &num) )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int elem_w = elemtype_->StaticSize(env);
|
||||||
|
if ( elem_w < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
DEBUG_MSG("static size of %s:%s = %d * %d\n",
|
||||||
|
decl_id()->Name(), lvalue(), elem_w, num);
|
||||||
|
|
||||||
|
return num * elem_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::SetBoundaryChecked()
|
||||||
|
{
|
||||||
|
Type::SetBoundaryChecked();
|
||||||
|
elemtype_->SetBoundaryChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayType::DoMarkIncrementalInput()
|
||||||
|
{
|
||||||
|
elemtype_->MarkIncrementalInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArrayType::RequiresAnalyzerContext()
|
||||||
|
{
|
||||||
|
return Type::RequiresAnalyzerContext() ||
|
||||||
|
( length_ && length_->RequiresAnalyzerContext() ) ||
|
||||||
|
elemtype_->RequiresAnalyzerContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArrayType::DoTraverse(DataDepVisitor *visitor)
|
||||||
|
{
|
||||||
|
if ( ! Type::DoTraverse(visitor) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( length_ && ! length_->Traverse(visitor) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( ! elemtype_->Traverse(visitor) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
92
aux/binpac/src/pac_array.h
Normal file
92
aux/binpac/src/pac_array.h
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#ifndef pac_array_h
|
||||||
|
#define pac_array_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
|
||||||
|
// Fixed-length array and variable length sequence with an ending pattern
|
||||||
|
|
||||||
|
class ArrayType : public Type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ArrayType(Type *arg_elemtype, Expr *arg_length = 0);
|
||||||
|
~ArrayType();
|
||||||
|
|
||||||
|
bool DefineValueVar() const;
|
||||||
|
string DataTypeStr() const;
|
||||||
|
string DefaultValue() const { return "0"; }
|
||||||
|
Type *ElementDataType() const;
|
||||||
|
|
||||||
|
string EvalElement(const string &array, const string &index) const;
|
||||||
|
|
||||||
|
void ProcessAttr(Attr *a);
|
||||||
|
|
||||||
|
void Prepare(Env *env, int flags);
|
||||||
|
|
||||||
|
void GenPubDecls(Output *out, Env *env);
|
||||||
|
void GenPrivDecls(Output *out, Env *env);
|
||||||
|
|
||||||
|
void GenInitCode(Output *out, Env *env);
|
||||||
|
void GenCleanUpCode(Output *out, Env *env);
|
||||||
|
|
||||||
|
int StaticSize(Env *env) const;
|
||||||
|
|
||||||
|
void SetBoundaryChecked();
|
||||||
|
void GenUntilInputCheck(Output *out_cc, Env *env);
|
||||||
|
|
||||||
|
bool IsPointerType() const { return true; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags);
|
||||||
|
void GenDynamicSize(Output *out, Env *env, const DataPtr& data);
|
||||||
|
void GenArrayLength(Output *out_cc, Env *env, const DataPtr& data);
|
||||||
|
string GenArrayInit(Output *out_cc, Env *env, bool known_array_length);
|
||||||
|
void GenElementAssignment(Output *out_cc, Env *env,
|
||||||
|
string const &array_str, bool use_vector);
|
||||||
|
void GenUntilCheck(Output *out_cc, Env *env,
|
||||||
|
Expr *until_condition, bool delete_elem);
|
||||||
|
|
||||||
|
bool ByteOrderSensitive() const
|
||||||
|
{
|
||||||
|
return elemtype_->RequiresByteOrder();
|
||||||
|
}
|
||||||
|
bool RequiresAnalyzerContext();
|
||||||
|
|
||||||
|
Type *DoClone() const;
|
||||||
|
|
||||||
|
void DoMarkIncrementalInput();
|
||||||
|
|
||||||
|
const ID *arraylength_var() const;
|
||||||
|
const ID *elem_it_var() const;
|
||||||
|
const ID *elem_var() const;
|
||||||
|
const ID *elem_dataptr_var() const;
|
||||||
|
const ID *elem_input_var() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool DoTraverse(DataDepVisitor *visitor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *elemtype_;
|
||||||
|
Expr *length_;
|
||||||
|
|
||||||
|
string vector_str_;
|
||||||
|
string datatype_str_;
|
||||||
|
string end_of_array_loop_label_;
|
||||||
|
|
||||||
|
Field *arraylength_var_field_;
|
||||||
|
Field *elem_it_var_field_;
|
||||||
|
Field *elem_var_field_;
|
||||||
|
Field *elem_dataptr_var_field_;
|
||||||
|
Field *elem_input_var_field_;
|
||||||
|
|
||||||
|
// This does not come from &until, but is internally generated
|
||||||
|
Expr *elem_dataptr_until_expr_;
|
||||||
|
|
||||||
|
Expr *attr_generic_until_expr_;
|
||||||
|
Expr *attr_until_element_expr_;
|
||||||
|
Expr *attr_until_input_expr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_array_h
|
57
aux/binpac/src/pac_attr.cc
Normal file
57
aux/binpac/src/pac_attr.cc
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#include "pac_attr.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
|
||||||
|
bool Attr::DoTraverse(DataDepVisitor *visitor)
|
||||||
|
{
|
||||||
|
if ( expr_ && ! expr_->Traverse(visitor) )
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Attr::RequiresAnalyzerContext() const
|
||||||
|
{
|
||||||
|
return (expr_ && expr_->RequiresAnalyzerContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Attr::init()
|
||||||
|
{
|
||||||
|
expr_ = 0;
|
||||||
|
seqend_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr::Attr(AttrType type)
|
||||||
|
: DataDepElement(DataDepElement::ATTR)
|
||||||
|
{
|
||||||
|
type_ = type;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr::Attr(AttrType type, Expr *expr)
|
||||||
|
: DataDepElement(DataDepElement::ATTR)
|
||||||
|
{
|
||||||
|
type_ = type;
|
||||||
|
init();
|
||||||
|
expr_ = expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr::Attr(AttrType type, ExprList *exprlist)
|
||||||
|
: DataDepElement(DataDepElement::ATTR)
|
||||||
|
{
|
||||||
|
type_ = type;
|
||||||
|
init();
|
||||||
|
expr_ = new Expr(exprlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr::Attr(AttrType type, SeqEnd *seqend)
|
||||||
|
: DataDepElement(DataDepElement::ATTR)
|
||||||
|
{
|
||||||
|
type_ = type;
|
||||||
|
init();
|
||||||
|
seqend_ = seqend;
|
||||||
|
}
|
||||||
|
|
||||||
|
LetAttr::LetAttr(FieldList *letfields)
|
||||||
|
: Attr(ATTR_LET)
|
||||||
|
{
|
||||||
|
letfields_ = letfields;
|
||||||
|
}
|
61
aux/binpac/src/pac_attr.h
Normal file
61
aux/binpac/src/pac_attr.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#ifndef pac_attr_h
|
||||||
|
#define pac_attr_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_datadep.h"
|
||||||
|
|
||||||
|
enum AttrType {
|
||||||
|
ATTR_BYTEORDER,
|
||||||
|
ATTR_CHECK,
|
||||||
|
ATTR_CHUNKED,
|
||||||
|
ATTR_EXPORTSOURCEDATA,
|
||||||
|
ATTR_IF,
|
||||||
|
ATTR_LENGTH,
|
||||||
|
ATTR_LET,
|
||||||
|
ATTR_LINEBREAKER,
|
||||||
|
ATTR_MULTILINE,
|
||||||
|
ATTR_ONELINE,
|
||||||
|
ATTR_REFCOUNT,
|
||||||
|
ATTR_REQUIRES,
|
||||||
|
ATTR_RESTOFDATA,
|
||||||
|
ATTR_RESTOFFLOW,
|
||||||
|
ATTR_TRANSIENT,
|
||||||
|
ATTR_UNTIL,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Attr : public Object, public DataDepElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Attr(AttrType type);
|
||||||
|
Attr(AttrType type, Expr *expr);
|
||||||
|
Attr(AttrType type, ExprList *exprlist);
|
||||||
|
Attr(AttrType type, SeqEnd *seqend);
|
||||||
|
|
||||||
|
AttrType type() const { return type_; }
|
||||||
|
Expr *expr() const { return expr_; }
|
||||||
|
SeqEnd *seqend() const { return seqend_; }
|
||||||
|
|
||||||
|
bool RequiresAnalyzerContext() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool DoTraverse(DataDepVisitor *visitor);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void init();
|
||||||
|
|
||||||
|
AttrType type_;
|
||||||
|
Expr *expr_;
|
||||||
|
SeqEnd *seqend_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LetAttr : public Attr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LetAttr(FieldList *letfields);
|
||||||
|
FieldList *letfields() const { return letfields_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
FieldList *letfields_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_attr_h
|
144
aux/binpac/src/pac_btype.cc
Normal file
144
aux/binpac/src/pac_btype.cc
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
#include "pac_btype.h"
|
||||||
|
#include "pac_dataptr.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
|
||||||
|
Type *BuiltInType::DoClone() const
|
||||||
|
{
|
||||||
|
return new BuiltInType(bit_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltInType::IsNumericType() const
|
||||||
|
{
|
||||||
|
BITType t = bit_type();
|
||||||
|
return (t == INT8 || t == INT16 || t == INT32 ||
|
||||||
|
t == UINT8 || t == UINT16 || t == UINT32);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuiltInType::CompatibleBuiltInTypes(BuiltInType *type1,
|
||||||
|
BuiltInType *type2)
|
||||||
|
{
|
||||||
|
return type1->IsNumericType() && type2->IsNumericType();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* basic_pactype_name[] = {
|
||||||
|
# define TYPE_DEF(name, pactype, ctype, size) pactype,
|
||||||
|
# include "pac_type.def"
|
||||||
|
# undef TYPE_DEF
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
void BuiltInType::static_init()
|
||||||
|
{
|
||||||
|
for ( int bit_type = 0; basic_pactype_name[bit_type]; ++bit_type )
|
||||||
|
{
|
||||||
|
Type::AddPredefinedType(
|
||||||
|
basic_pactype_name[bit_type],
|
||||||
|
new BuiltInType((BITType) bit_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BuiltInType::LookUpByName(const char* name)
|
||||||
|
{
|
||||||
|
ASSERT(0);
|
||||||
|
for ( int i = 0; basic_pactype_name[i]; ++i )
|
||||||
|
if ( strcmp(basic_pactype_name[i], name) == 0 )
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* basic_ctype_name[] = {
|
||||||
|
# define TYPE_DEF(name, pactype, ctype, size) ctype,
|
||||||
|
# include "pac_type.def"
|
||||||
|
# undef TYPE_DEF
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool BuiltInType::DefineValueVar() const
|
||||||
|
{
|
||||||
|
return bit_type_ != EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
string BuiltInType::DataTypeStr() const
|
||||||
|
{
|
||||||
|
return basic_ctype_name[bit_type_];
|
||||||
|
}
|
||||||
|
|
||||||
|
int BuiltInType::StaticSize(Env* /* env */) const
|
||||||
|
{
|
||||||
|
static const size_t basic_type_size[] =
|
||||||
|
{
|
||||||
|
# define TYPE_DEF(name, pactype, ctype, size) size,
|
||||||
|
# include "pac_type.def"
|
||||||
|
# undef TYPE_DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
return basic_type_size[bit_type_];
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltInType::DoMarkIncrementalInput()
|
||||||
|
{
|
||||||
|
if ( bit_type_ == EMPTY )
|
||||||
|
return;
|
||||||
|
Type::DoMarkIncrementalInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltInType::GenInitCode(Output* out_cc, Env* env)
|
||||||
|
{
|
||||||
|
if ( bit_type_ != EMPTY )
|
||||||
|
out_cc->println("%s = 0;", env->LValue(value_var()));
|
||||||
|
Type::GenInitCode(out_cc, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltInType::GenDynamicSize(Output* out_cc, Env* env, const DataPtr& data)
|
||||||
|
{
|
||||||
|
/* should never be called */
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuiltInType::DoGenParseCode(Output* out_cc, Env* env,
|
||||||
|
const DataPtr& data, int flags)
|
||||||
|
{
|
||||||
|
if ( bit_type_ == EMPTY )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// There is no need to generate the size variable
|
||||||
|
// out_cc->println("%s = sizeof(%s);", size_var(), DataTypeStr().c_str());
|
||||||
|
|
||||||
|
GenBoundaryCheck(out_cc, env, data);
|
||||||
|
|
||||||
|
if ( anonymous_value_var() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch ( bit_type_ )
|
||||||
|
{
|
||||||
|
case EMPTY:
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INT8:
|
||||||
|
case UINT8:
|
||||||
|
out_cc->println("%s = *((%s const *) (%s));",
|
||||||
|
lvalue(), DataTypeStr().c_str(), data.ptr_expr());
|
||||||
|
break;
|
||||||
|
case INT16:
|
||||||
|
case UINT16:
|
||||||
|
case INT32:
|
||||||
|
case UINT32:
|
||||||
|
#if 0
|
||||||
|
out_cc->println("%s = UnMarshall<%s>(%s, %s);",
|
||||||
|
lvalue(),
|
||||||
|
DataTypeStr().c_str(),
|
||||||
|
data.ptr_expr(),
|
||||||
|
EvalByteOrder(out_cc, env).c_str());
|
||||||
|
#else
|
||||||
|
out_cc->println("%s = FixByteOrder(%s, *((%s const *) (%s)));",
|
||||||
|
lvalue(),
|
||||||
|
EvalByteOrder(out_cc, env).c_str(),
|
||||||
|
DataTypeStr().c_str(),
|
||||||
|
data.ptr_expr());
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
52
aux/binpac/src/pac_btype.h
Normal file
52
aux/binpac/src/pac_btype.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef pac_btype_h
|
||||||
|
#define pac_btype_h
|
||||||
|
|
||||||
|
#include "pac_type.h"
|
||||||
|
|
||||||
|
class BuiltInType : public Type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum BITType {
|
||||||
|
# define TYPE_DEF(name, pactype, ctype, size) name,
|
||||||
|
# include "pac_type.def"
|
||||||
|
# undef TYPE_DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
static int LookUpByName(const char *name);
|
||||||
|
|
||||||
|
BuiltInType(BITType bit_type)
|
||||||
|
: Type(bit_type == BuiltInType::EMPTY ? Type::EMPTY : BUILTIN),
|
||||||
|
bit_type_(bit_type) {}
|
||||||
|
|
||||||
|
BITType bit_type() const { return bit_type_; }
|
||||||
|
|
||||||
|
bool IsNumericType() const;
|
||||||
|
|
||||||
|
bool DefineValueVar() const;
|
||||||
|
string DataTypeStr() const;
|
||||||
|
string DefaultValue() const { return "0"; }
|
||||||
|
|
||||||
|
int StaticSize(Env *env) const;
|
||||||
|
|
||||||
|
bool IsPointerType() const { return false; }
|
||||||
|
|
||||||
|
bool ByteOrderSensitive() const { return StaticSize(0) >= 2; }
|
||||||
|
|
||||||
|
void GenInitCode(Output *out_cc, Env *env);
|
||||||
|
|
||||||
|
void DoMarkIncrementalInput();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags);
|
||||||
|
void GenDynamicSize(Output *out, Env *env, const DataPtr& data);
|
||||||
|
Type *DoClone() const;
|
||||||
|
|
||||||
|
BITType bit_type_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void static_init();
|
||||||
|
static bool CompatibleBuiltInTypes(BuiltInType *type1,
|
||||||
|
BuiltInType *type2);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_btype_h
|
391
aux/binpac/src/pac_case.cc
Normal file
391
aux/binpac/src/pac_case.cc
Normal file
|
@ -0,0 +1,391 @@
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
#include "pac_exttype.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_typedecl.h"
|
||||||
|
#include "pac_utils.h"
|
||||||
|
|
||||||
|
#include "pac_case.h"
|
||||||
|
|
||||||
|
CaseType::CaseType(Expr* index_expr, CaseFieldList* cases)
|
||||||
|
: Type(CASE), index_expr_(index_expr), cases_(cases)
|
||||||
|
{
|
||||||
|
index_var_ = 0;
|
||||||
|
foreach(i, CaseFieldList, cases_)
|
||||||
|
AddField(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
CaseType::~CaseType()
|
||||||
|
{
|
||||||
|
delete index_var_;
|
||||||
|
delete index_expr_;
|
||||||
|
delete cases_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::AddCaseField(CaseField *f)
|
||||||
|
{
|
||||||
|
// All fields must be added before Prepare()
|
||||||
|
ASSERT(!env());
|
||||||
|
|
||||||
|
AddField(f);
|
||||||
|
cases_->push_back(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CaseType::DefineValueVar() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string CaseType::DataTypeStr() const
|
||||||
|
{
|
||||||
|
ASSERT(type_decl());
|
||||||
|
return strfmt("%s *", type_decl()->class_name().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *CaseType::ValueType() const
|
||||||
|
{
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
return c->type();
|
||||||
|
}
|
||||||
|
ASSERT(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string CaseType::DefaultValue() const
|
||||||
|
{
|
||||||
|
return ValueType()->DefaultValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::Prepare(Env* env, int flags)
|
||||||
|
{
|
||||||
|
ASSERT(flags & TO_BE_PARSED);
|
||||||
|
|
||||||
|
index_var_ = new ID(fmt("%s_case_index", value_var()->Name()));
|
||||||
|
env->AddID(index_var_, MEMBER_VAR, extern_type_int);
|
||||||
|
|
||||||
|
// Sort the cases_ to put the default case at the end of the list
|
||||||
|
CaseFieldList::iterator default_case_it =
|
||||||
|
cases_->end(); // to avoid warning
|
||||||
|
CaseField *default_case = 0;
|
||||||
|
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
if ( ! c->index() )
|
||||||
|
{
|
||||||
|
if ( default_case )
|
||||||
|
throw Exception(c, "duplicate default case");
|
||||||
|
default_case_it = i;
|
||||||
|
default_case = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( default_case )
|
||||||
|
{
|
||||||
|
cases_->erase(default_case_it);
|
||||||
|
cases_->push_back(default_case);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
c->set_index_var(index_var_);
|
||||||
|
c->set_case_type(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Prepare(env, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::GenPrivDecls(Output* out_h, Env* env)
|
||||||
|
{
|
||||||
|
out_h->println("int %s;", env->LValue(index_var_));
|
||||||
|
Type::GenPrivDecls(out_h, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::GenPubDecls(Output* out_h, Env* env)
|
||||||
|
{
|
||||||
|
out_h->println("int %s const { return %s; }",
|
||||||
|
env->RValue(index_var_), env->LValue(index_var_));
|
||||||
|
Type::GenPubDecls(out_h, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::GenInitCode(Output* out_cc, Env* env)
|
||||||
|
{
|
||||||
|
out_cc->println("%s = -1;", env->LValue(index_var_));
|
||||||
|
Type::GenInitCode(out_cc, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::GenCleanUpCode(Output* out_cc, Env* env)
|
||||||
|
{
|
||||||
|
Type::GenCleanUpCode(out_cc, env);
|
||||||
|
|
||||||
|
env->set_in_branch(true);
|
||||||
|
out_cc->println("switch ( %s )", env->RValue(index_var_));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
c->GenCleanUpCode(out_cc, env);
|
||||||
|
}
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
env->set_in_branch(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::DoGenParseCode(Output* out_cc, Env* env,
|
||||||
|
const DataPtr& data, int flags)
|
||||||
|
{
|
||||||
|
if ( StaticSize(env) >= 0 )
|
||||||
|
GenBoundaryCheck(out_cc, env, data);
|
||||||
|
|
||||||
|
bool compute_size_var = false;
|
||||||
|
|
||||||
|
if ( ! incremental_input() )
|
||||||
|
compute_size_var = AddSizeVar(out_cc, env);
|
||||||
|
|
||||||
|
out_cc->println("%s = %s;",
|
||||||
|
env->LValue(index_var_), index_expr_->EvalExpr(out_cc, env));
|
||||||
|
env->SetEvaluated(index_var_);
|
||||||
|
|
||||||
|
env->set_in_branch(true);
|
||||||
|
out_cc->println("switch ( %s )", env->RValue(index_var_));
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
bool has_default_case = false;
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
c->GenParseCode(out_cc, env, data,
|
||||||
|
compute_size_var ? size_var() : 0);
|
||||||
|
if ( c->IsDefaultCase() )
|
||||||
|
has_default_case = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! has_default_case )
|
||||||
|
{
|
||||||
|
out_cc->println("default:");
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("throw ExceptionInvalidCaseIndex(\"%s\", %s);",
|
||||||
|
decl_id()->Name(), env->RValue(index_var_));
|
||||||
|
out_cc->println("break;");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
env->set_in_branch(false);
|
||||||
|
|
||||||
|
if ( compute_size_var )
|
||||||
|
env->SetEvaluated(size_var());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::GenDynamicSize(Output* out_cc, Env* env,
|
||||||
|
const DataPtr& data)
|
||||||
|
{
|
||||||
|
GenParseCode(out_cc, env, data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CaseType::StaticSize(Env* env) const
|
||||||
|
{
|
||||||
|
int static_w = -1;
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
int w = c->StaticSize(env);
|
||||||
|
if ( w < 0 || ( static_w >= 0 && w != static_w ) )
|
||||||
|
return -1;
|
||||||
|
static_w = w;
|
||||||
|
}
|
||||||
|
return static_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::SetBoundaryChecked()
|
||||||
|
{
|
||||||
|
Type::SetBoundaryChecked();
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
c->SetBoundaryChecked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseType::DoMarkIncrementalInput()
|
||||||
|
{
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
c->type()->MarkIncrementalInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CaseType::ByteOrderSensitive() const
|
||||||
|
{
|
||||||
|
foreach (i, CaseFieldList, cases_)
|
||||||
|
{
|
||||||
|
CaseField *c = *i;
|
||||||
|
if ( c->RequiresByteOrder() )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CaseField::CaseField(ExprList* index, ID* id, Type* type)
|
||||||
|
: Field(CASE_FIELD,
|
||||||
|
TYPE_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE,
|
||||||
|
id, type),
|
||||||
|
index_(index)
|
||||||
|
{
|
||||||
|
ASSERT(type_);
|
||||||
|
type_->set_value_var(id, MEMBER_VAR);
|
||||||
|
case_type_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CaseField::~CaseField()
|
||||||
|
{
|
||||||
|
delete_list(ExprList, index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env)
|
||||||
|
{
|
||||||
|
if ( index_list )
|
||||||
|
{
|
||||||
|
foreach(i, ExprList, index_list)
|
||||||
|
{
|
||||||
|
Expr *index_expr = *i;
|
||||||
|
int index_const;
|
||||||
|
|
||||||
|
if ( ! index_expr->ConstFold(env, &index_const) )
|
||||||
|
throw ExceptionNonConstExpr(index_expr);
|
||||||
|
out_cc->println("case %d:", index_const);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_cc->println("default:");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseField::Prepare(Env* env)
|
||||||
|
{
|
||||||
|
ASSERT(index_var_);
|
||||||
|
Field::Prepare(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseField::GenPubDecls(Output* out_h, Env* env)
|
||||||
|
{
|
||||||
|
if ( ! ((flags_ & PUBLIC_READABLE) && (flags_ & CLASS_MEMBER)) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Skip type "empty"
|
||||||
|
if ( type_->DataTypeStr().empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
out_h->println("%s %s const",
|
||||||
|
type_->DataTypeConstRefStr().c_str(), env->RValue(id_));
|
||||||
|
|
||||||
|
out_h->inc_indent();
|
||||||
|
out_h->println("{");
|
||||||
|
|
||||||
|
if ( ! index_ )
|
||||||
|
out_h->println("return %s;", lvalue());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_h->println("switch ( %s )", env->RValue(index_var_));
|
||||||
|
out_h->inc_indent();
|
||||||
|
out_h->println("{");
|
||||||
|
GenCaseStr(index_, out_h, env);
|
||||||
|
out_h->inc_indent();
|
||||||
|
out_h->println("break; // OK");
|
||||||
|
out_h->dec_indent();
|
||||||
|
|
||||||
|
out_h->println("default:");
|
||||||
|
out_h->inc_indent();
|
||||||
|
out_h->println("throw ExceptionInvalidCase(\"%s\", %s, \"%s\");",
|
||||||
|
id_->LocName(),
|
||||||
|
env->RValue(index_var_),
|
||||||
|
OrigExprList(index_).c_str());
|
||||||
|
out_h->println("break;");
|
||||||
|
out_h->dec_indent();
|
||||||
|
|
||||||
|
out_h->println("}");
|
||||||
|
out_h->dec_indent();
|
||||||
|
|
||||||
|
out_h->println("return %s;", lvalue());
|
||||||
|
}
|
||||||
|
|
||||||
|
out_h->println("}");
|
||||||
|
out_h->dec_indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseField::GenInitCode(Output* out_cc, Env* env)
|
||||||
|
{
|
||||||
|
// GenCaseStr(index_, out_cc, env);
|
||||||
|
// out_cc->inc_indent();
|
||||||
|
// out_cc->println("{");
|
||||||
|
// out_cc->println("// Initialize \"%s\"", id_->Name());
|
||||||
|
type_->GenInitCode(out_cc, env);
|
||||||
|
// out_cc->println("}");
|
||||||
|
// out_cc->println("break;");
|
||||||
|
// out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseField::GenCleanUpCode(Output* out_cc, Env* env)
|
||||||
|
{
|
||||||
|
GenCaseStr(index_, out_cc, env);
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("// Clean up \"%s\"", id_->Name());
|
||||||
|
out_cc->println("{");
|
||||||
|
if ( ! anonymous_field() )
|
||||||
|
type_->GenCleanUpCode(out_cc, env);
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->println("break;");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaseField::GenParseCode(Output* out_cc, Env* env,
|
||||||
|
const DataPtr& data, const ID* size_var)
|
||||||
|
{
|
||||||
|
GenCaseStr(index_, out_cc, env);
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("// Parse \"%s\"", id_->Name());
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
{
|
||||||
|
Env case_env(env, this);
|
||||||
|
Env *env = &case_env;
|
||||||
|
|
||||||
|
type_->GenPreParsing(out_cc, env);
|
||||||
|
type_->GenParseCode(out_cc, env, data, 0);
|
||||||
|
if ( size_var )
|
||||||
|
{
|
||||||
|
out_cc->println("%s = %s;",
|
||||||
|
env->LValue(size_var),
|
||||||
|
type_->DataSize(out_cc, env, data).c_str());
|
||||||
|
}
|
||||||
|
if ( type_->incremental_input() )
|
||||||
|
{
|
||||||
|
ASSERT(case_type()->parsing_complete_var());
|
||||||
|
out_cc->println("%s = %s;",
|
||||||
|
env->LValue(case_type()->parsing_complete_var()),
|
||||||
|
env->RValue(type_->parsing_complete_var()));
|
||||||
|
}
|
||||||
|
out_cc->println("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
out_cc->println("break;");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CaseField::DoTraverse(DataDepVisitor *visitor)
|
||||||
|
{
|
||||||
|
return Field::DoTraverse(visitor) &&
|
||||||
|
type()->Traverse(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CaseField::RequiresAnalyzerContext() const
|
||||||
|
{
|
||||||
|
return Field::RequiresAnalyzerContext() ||
|
||||||
|
type()->RequiresAnalyzerContext();
|
||||||
|
}
|
99
aux/binpac/src/pac_case.h
Normal file
99
aux/binpac/src/pac_case.h
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
#ifndef pac_case_h
|
||||||
|
#define pac_case_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_field.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
|
||||||
|
class CaseType : public Type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CaseType(Expr *index, CaseFieldList *cases);
|
||||||
|
~CaseType();
|
||||||
|
|
||||||
|
void AddCaseField(CaseField *f);
|
||||||
|
|
||||||
|
bool DefineValueVar() const;
|
||||||
|
string DataTypeStr() const;
|
||||||
|
string DefaultValue() const;
|
||||||
|
|
||||||
|
void Prepare(Env *env, int flags);
|
||||||
|
|
||||||
|
void GenPubDecls(Output *out, Env *env);
|
||||||
|
void GenPrivDecls(Output *out, Env *env);
|
||||||
|
|
||||||
|
void GenInitCode(Output *out, Env *env);
|
||||||
|
void GenCleanUpCode(Output *out, Env *env);
|
||||||
|
|
||||||
|
int StaticSize(Env *env) const;
|
||||||
|
|
||||||
|
void SetBoundaryChecked();
|
||||||
|
|
||||||
|
Type *ValueType() const;
|
||||||
|
|
||||||
|
bool IsPointerType() const { return ValueType()->IsPointerType(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DoGenParseCode(Output *out, Env *env, const DataPtr& data, int flags);
|
||||||
|
void GenDynamicSize(Output *out, Env *env, const DataPtr& data);
|
||||||
|
Type *DoClone() const { return 0; }
|
||||||
|
void DoMarkIncrementalInput();
|
||||||
|
|
||||||
|
bool ByteOrderSensitive() const;
|
||||||
|
|
||||||
|
Expr *index_expr_;
|
||||||
|
ID *index_var_;
|
||||||
|
CaseFieldList *cases_;
|
||||||
|
|
||||||
|
typedef map<const ID*, CaseField*, ID_ptr_cmp> member_map_t;
|
||||||
|
member_map_t member_map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CaseField : public Field
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CaseField(ExprList *index, ID *id, Type *type);
|
||||||
|
~CaseField();
|
||||||
|
|
||||||
|
CaseType *case_type() const { return case_type_; }
|
||||||
|
void set_case_type(CaseType *t) { case_type_ = t; }
|
||||||
|
|
||||||
|
ExprList *index() const { return index_; }
|
||||||
|
|
||||||
|
const char *lvalue() const { return type_->lvalue(); }
|
||||||
|
|
||||||
|
const char *CaseStr(Env *env);
|
||||||
|
void set_index_var(const ID *var) { index_var_ = var; }
|
||||||
|
|
||||||
|
void Prepare(Env *env);
|
||||||
|
|
||||||
|
void GenPubDecls(Output *out, Env *env);
|
||||||
|
|
||||||
|
void GenInitCode(Output *out, Env *env);
|
||||||
|
void GenCleanUpCode(Output *out, Env *env);
|
||||||
|
void GenParseCode(Output *out, Env *env,
|
||||||
|
const DataPtr& data, const ID *size_var);
|
||||||
|
|
||||||
|
int StaticSize(Env *env) const { return type_->StaticSize(env); }
|
||||||
|
|
||||||
|
bool IsDefaultCase() const { return ! index_; }
|
||||||
|
void SetBoundaryChecked() { type_->SetBoundaryChecked(); }
|
||||||
|
|
||||||
|
bool RequiresByteOrder() const { return type_->RequiresByteOrder(); }
|
||||||
|
bool RequiresAnalyzerContext() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool DoTraverse(DataDepVisitor *visitor);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CaseType *case_type_;
|
||||||
|
ExprList *index_;
|
||||||
|
const ID *index_var_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate a list of "case X:" lines from index_list. Each index
|
||||||
|
// expression must be constant foldable.
|
||||||
|
void GenCaseStr(ExprList *index_list, Output *out_cc, Env *env);
|
||||||
|
|
||||||
|
#endif // pac_case_h
|
81
aux/binpac/src/pac_cclass.h
Normal file
81
aux/binpac/src/pac_cclass.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#ifndef pac_cclass_h
|
||||||
|
#define pac_cclass_h
|
||||||
|
|
||||||
|
class CClass;
|
||||||
|
class CClassMember;
|
||||||
|
class CClassMethod;
|
||||||
|
class CType;
|
||||||
|
class CVariable;
|
||||||
|
|
||||||
|
typedef vector<CClassMember *> CClassMemberList;
|
||||||
|
typedef vector<CClassMethod *> CClassMethodList;
|
||||||
|
typedef vector<CVariable *> CVariableList;
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
|
||||||
|
// Represents a C++ class.
|
||||||
|
//
|
||||||
|
// For now we adopt a simple model:
|
||||||
|
//
|
||||||
|
// 1. All members have a protected member variable "name_" and a
|
||||||
|
// public constant access method "name()".
|
||||||
|
//
|
||||||
|
// 2. All methods are public.
|
||||||
|
//
|
||||||
|
// 3. We do not check repeated names.
|
||||||
|
|
||||||
|
class CClass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CClass(const string &class_name);
|
||||||
|
|
||||||
|
void AddMember(CClassMember *member);
|
||||||
|
void AddMethod(CClassMember *method);
|
||||||
|
|
||||||
|
void GenForwardDeclaration(Output *out_h);
|
||||||
|
void GenCode(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string class_name_;
|
||||||
|
CClassMemberList *members_;
|
||||||
|
CClassMethodList *methods_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CVariable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CClassMember(const string &name, CType *type);
|
||||||
|
|
||||||
|
string name() const { return name_; }
|
||||||
|
CType *type() const { return type_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string name_;
|
||||||
|
CType *type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CClassMember
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CClassMember(CVariable *var);
|
||||||
|
void GenCode(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
string decl() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CVariable *var_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CClassMethod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CClassMethod(CVariable *var, CVariableList *params);
|
||||||
|
|
||||||
|
string decl() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CVariable *var_;
|
||||||
|
CVariableList *params_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_cclass_h
|
134
aux/binpac/src/pac_common.h
Normal file
134
aux/binpac/src/pac_common.h
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
#ifndef pac_common_h
|
||||||
|
#define pac_common_h
|
||||||
|
|
||||||
|
#include "pac_utils.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
extern bool FLAGS_pac_debug;
|
||||||
|
extern vector<string> FLAGS_include_directories;
|
||||||
|
extern string input_filename;
|
||||||
|
extern int line_number;
|
||||||
|
|
||||||
|
// Definition of class Object, which is the base class for all objects
|
||||||
|
// representing language elements -- identifiers, types, expressions,
|
||||||
|
// etc.
|
||||||
|
|
||||||
|
class Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Object()
|
||||||
|
{
|
||||||
|
filename = input_filename;
|
||||||
|
line_num = line_number;
|
||||||
|
location = strfmt("%s:%d", filename.c_str(), line_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Object()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* Location() const { return location.c_str(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string filename;
|
||||||
|
int line_num;
|
||||||
|
string location;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ActionParam;
|
||||||
|
class ActionParamType;
|
||||||
|
class AnalyzerAction;
|
||||||
|
class AnalyzerContextDecl;
|
||||||
|
class AnalyzerDecl;
|
||||||
|
class AnalyzerElement;
|
||||||
|
class ArrayType;
|
||||||
|
class Attr;
|
||||||
|
class CClass;
|
||||||
|
class CType;
|
||||||
|
class ConstString;
|
||||||
|
class CaseExpr;
|
||||||
|
class CaseField;
|
||||||
|
class ContextField;
|
||||||
|
class DataPtr;
|
||||||
|
class Decl;
|
||||||
|
class EmbeddedCode;
|
||||||
|
class Enum;
|
||||||
|
class Env;
|
||||||
|
class ExternType;
|
||||||
|
class Expr;
|
||||||
|
class Field;
|
||||||
|
class Function;
|
||||||
|
class InputBuffer;
|
||||||
|
class LetDef;
|
||||||
|
class LetField;
|
||||||
|
class ID;
|
||||||
|
class Number;
|
||||||
|
class Output;
|
||||||
|
class PacPrimitive;
|
||||||
|
class Param;
|
||||||
|
class ParameterizedType;
|
||||||
|
class RecordType;
|
||||||
|
class RecordField;
|
||||||
|
class RecordDataField;
|
||||||
|
class RecordPaddingField;
|
||||||
|
class RegEx;
|
||||||
|
class SeqEnd;
|
||||||
|
class StateVar;
|
||||||
|
class Type;
|
||||||
|
class TypeDecl;
|
||||||
|
class WithInputField;
|
||||||
|
|
||||||
|
// The ID of the current declaration.
|
||||||
|
extern const ID* current_decl_id;
|
||||||
|
|
||||||
|
typedef vector<ActionParam*> ActionParamList;
|
||||||
|
typedef vector<AnalyzerAction*> AnalyzerActionList;
|
||||||
|
typedef vector<AnalyzerElement*> AnalyzerElementList;
|
||||||
|
typedef vector<Attr*> AttrList;
|
||||||
|
typedef vector<CaseExpr*> CaseExprList;
|
||||||
|
typedef vector<CaseField*> CaseFieldList;
|
||||||
|
typedef vector<ContextField*> ContextFieldList;
|
||||||
|
typedef vector<Decl*> DeclList;
|
||||||
|
typedef vector<Enum*> EnumList;
|
||||||
|
typedef vector<Expr*> ExprList;
|
||||||
|
typedef vector<Field*> FieldList;
|
||||||
|
typedef vector<LetField*> LetFieldList;
|
||||||
|
typedef vector<Number*> NumList;
|
||||||
|
typedef vector<Param*> ParamList;
|
||||||
|
typedef vector<RecordField*> RecordFieldList;
|
||||||
|
typedef vector<StateVar*> StateVarList;
|
||||||
|
|
||||||
|
#define foreach(i, ct, pc) \
|
||||||
|
if ( pc ) \
|
||||||
|
for ( ct::iterator i = (pc)->begin(); i != (pc)->end(); ++i )
|
||||||
|
|
||||||
|
#define delete_list(ct, pc) \
|
||||||
|
{ \
|
||||||
|
foreach(delete_list_i, ct, pc) \
|
||||||
|
delete *delete_list_i; \
|
||||||
|
delete pc; \
|
||||||
|
pc = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const char * const kComputeFrameLength = "compute_frame_length";
|
||||||
|
const char * const kFlowBufferClass = "FlowBuffer";
|
||||||
|
const char * const kFlowBufferVar = "flow_buffer";
|
||||||
|
const char * const kFlowEOF = "FlowEOF";
|
||||||
|
const char * const kFlowGap = "NewGap";
|
||||||
|
const char * const kInitialBufferLengthFunc = "initial_buffer_length";
|
||||||
|
const char * const kNeedMoreData = "need_more_data";
|
||||||
|
const char * const kNewData = "NewData";
|
||||||
|
const char * const kParseFuncWithBuffer = "ParseBuffer";
|
||||||
|
const char * const kParseFuncWithoutBuffer = "Parse";
|
||||||
|
const char * const kRefCountClass = "binpac::RefCount";
|
||||||
|
const char * const kTypeWithLengthClass = "binpac::TypeWithLength";
|
||||||
|
|
||||||
|
#endif // pac_common_h
|
169
aux/binpac/src/pac_conn.cc
Normal file
169
aux/binpac/src/pac_conn.cc
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#include "pac_analyzer.h"
|
||||||
|
#include "pac_dataunit.h"
|
||||||
|
#include "pac_embedded.h"
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
#include "pac_flow.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_paramtype.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
|
||||||
|
#include "pac_conn.h"
|
||||||
|
|
||||||
|
ConnDecl::ConnDecl(ID *conn_id,
|
||||||
|
ParamList *params,
|
||||||
|
AnalyzerElementList *elemlist)
|
||||||
|
: AnalyzerDecl(conn_id, CONN, params)
|
||||||
|
{
|
||||||
|
flows_[0] = flows_[1] = 0;
|
||||||
|
AddElements(elemlist);
|
||||||
|
data_type_ = new ParameterizedType(conn_id->clone(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnDecl::~ConnDecl()
|
||||||
|
{
|
||||||
|
delete flows_[0];
|
||||||
|
delete flows_[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::AddBaseClass(vector<string> *base_classes) const
|
||||||
|
{
|
||||||
|
base_classes->push_back("binpac::ConnectionAnalyzer");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::ProcessFlowElement(AnalyzerFlow *flow_elem)
|
||||||
|
{
|
||||||
|
int flow_index;
|
||||||
|
|
||||||
|
if ( flow_elem->dir() == AnalyzerFlow::UP )
|
||||||
|
flow_index = 0;
|
||||||
|
else
|
||||||
|
flow_index = 1;
|
||||||
|
|
||||||
|
if ( flows_[flow_index] )
|
||||||
|
{
|
||||||
|
throw Exception(flow_elem,
|
||||||
|
fmt("%sflow already defined",
|
||||||
|
flow_index == 0 ? "up" : "down"));
|
||||||
|
}
|
||||||
|
|
||||||
|
flows_[flow_index] = flow_elem;
|
||||||
|
type_->AddField(flow_elem->flow_field());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem)
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
dataunit_elem,
|
||||||
|
"dataunit should be defined in only a flow declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::Prepare()
|
||||||
|
{
|
||||||
|
AnalyzerDecl::Prepare();
|
||||||
|
|
||||||
|
flows_[0]->flow_decl()->set_conn_decl(this);
|
||||||
|
flows_[1]->flow_decl()->set_conn_decl(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::GenPubDecls(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
AnalyzerDecl::GenPubDecls(out_h, out_cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::GenPrivDecls(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
AnalyzerDecl::GenPrivDecls(out_h, out_cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::GenEOFFunc(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
string proto = strfmt("%s(bool is_orig)", kFlowEOF);
|
||||||
|
|
||||||
|
out_h->println("void %s;", proto.c_str());
|
||||||
|
|
||||||
|
out_cc->println("void %s::%s", class_name().c_str(), proto.c_str());
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
out_cc->println("if ( is_orig )");
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("%s->%s();",
|
||||||
|
env_->LValue(upflow_id),
|
||||||
|
kFlowEOF);
|
||||||
|
out_cc->dec_indent();
|
||||||
|
out_cc->println("else");
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("%s->%s();",
|
||||||
|
env_->LValue(downflow_id),
|
||||||
|
kFlowEOF);
|
||||||
|
|
||||||
|
foreach(i, AnalyzerHelperList, eof_helpers_)
|
||||||
|
{
|
||||||
|
(*i)->GenCode(0, out_cc, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_cc->dec_indent();
|
||||||
|
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
out_cc->println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::GenGapFunc(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
string proto = strfmt("%s(bool is_orig, int gap_length)", kFlowGap);
|
||||||
|
|
||||||
|
out_h->println("void %s;", proto.c_str());
|
||||||
|
|
||||||
|
out_cc->println("void %s::%s", class_name().c_str(), proto.c_str());
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
out_cc->println("if ( is_orig )");
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("%s->%s(gap_length);",
|
||||||
|
env_->LValue(upflow_id),
|
||||||
|
kFlowGap);
|
||||||
|
out_cc->dec_indent();
|
||||||
|
out_cc->println("else");
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("%s->%s(gap_length);",
|
||||||
|
env_->LValue(downflow_id),
|
||||||
|
kFlowGap);
|
||||||
|
out_cc->dec_indent();
|
||||||
|
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
out_cc->println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnDecl::GenProcessFunc(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
string proto =
|
||||||
|
strfmt("%s(bool is_orig, const_byteptr begin, const_byteptr end)",
|
||||||
|
kNewData);
|
||||||
|
|
||||||
|
out_h->println("void %s;", proto.c_str());
|
||||||
|
|
||||||
|
out_cc->println("void %s::%s", class_name().c_str(), proto.c_str());
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
out_cc->println("if ( is_orig )");
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("%s->%s(begin, end);",
|
||||||
|
env_->LValue(upflow_id),
|
||||||
|
kNewData);
|
||||||
|
out_cc->dec_indent();
|
||||||
|
out_cc->println("else");
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("%s->%s(begin, end);",
|
||||||
|
env_->LValue(downflow_id),
|
||||||
|
kNewData);
|
||||||
|
out_cc->dec_indent();
|
||||||
|
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
out_cc->println("");
|
||||||
|
}
|
34
aux/binpac/src/pac_conn.h
Normal file
34
aux/binpac/src/pac_conn.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef pac_conn_h
|
||||||
|
#define pac_conn_h
|
||||||
|
|
||||||
|
#include "pac_decl.h"
|
||||||
|
#include "pac_analyzer.h"
|
||||||
|
|
||||||
|
class ConnDecl : public AnalyzerDecl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConnDecl(ID *conn_id, ParamList *params, AnalyzerElementList *elemlist);
|
||||||
|
~ConnDecl();
|
||||||
|
|
||||||
|
void Prepare();
|
||||||
|
|
||||||
|
Type* DataType() const { return data_type_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void AddBaseClass(vector<string> *base_classes) const;
|
||||||
|
|
||||||
|
void GenProcessFunc(Output *out_h, Output *out_cc);
|
||||||
|
void GenGapFunc(Output *out_h, Output *out_cc);
|
||||||
|
void GenEOFFunc(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
void GenPubDecls(Output *out_h, Output *out_cc);
|
||||||
|
void GenPrivDecls(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
void ProcessFlowElement(AnalyzerFlow *flow_elem);
|
||||||
|
void ProcessDataUnitElement(AnalyzerDataUnit *dataunit_elem);
|
||||||
|
|
||||||
|
AnalyzerFlow *flows_[2];
|
||||||
|
Type *data_type_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_conn_h
|
120
aux/binpac/src/pac_context.cc
Normal file
120
aux/binpac/src/pac_context.cc
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
#include "pac_analyzer.h"
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_exttype.h"
|
||||||
|
#include "pac_flow.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_param.h"
|
||||||
|
#include "pac_paramtype.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
#include "pac_utils.h"
|
||||||
|
|
||||||
|
#include "pac_context.h"
|
||||||
|
|
||||||
|
ContextField::ContextField(ID *id, Type *type)
|
||||||
|
: Field(CONTEXT_FIELD,
|
||||||
|
TYPE_NOT_TO_BE_PARSED | CLASS_MEMBER | PUBLIC_READABLE,
|
||||||
|
id, type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerContextDecl *AnalyzerContextDecl::current_analyzer_context_ = 0;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
ParamList *ContextFieldsToParams(ContextFieldList *context_fields)
|
||||||
|
{
|
||||||
|
// Convert context fields to parameters
|
||||||
|
ParamList *params = new ParamList();
|
||||||
|
foreach(i, ContextFieldList, context_fields)
|
||||||
|
{
|
||||||
|
ContextField *f = *i;
|
||||||
|
params->push_back(
|
||||||
|
new Param(f->id()->clone(),
|
||||||
|
f->type()));
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
} // namespace private
|
||||||
|
|
||||||
|
AnalyzerContextDecl::AnalyzerContextDecl(
|
||||||
|
ID *id,
|
||||||
|
ContextFieldList *context_fields)
|
||||||
|
: TypeDecl(new ID(fmt("Context%s", id->Name())),
|
||||||
|
ContextFieldsToParams(context_fields),
|
||||||
|
new DummyType())
|
||||||
|
{
|
||||||
|
context_name_id_ = id;
|
||||||
|
if ( current_analyzer_context_ != 0 )
|
||||||
|
{
|
||||||
|
throw Exception(this,
|
||||||
|
fmt("multiple declaration of analyzer context; "
|
||||||
|
"the previous one is `%s'",
|
||||||
|
current_analyzer_context_->id()->Name()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
current_analyzer_context_ = this;
|
||||||
|
|
||||||
|
context_fields_ = context_fields;
|
||||||
|
|
||||||
|
param_type_ = new ParameterizedType(id_->clone(), 0);
|
||||||
|
|
||||||
|
flow_buffer_added_ = false;
|
||||||
|
|
||||||
|
DEBUG_MSG("Context type: %s\n", param_type()->class_name().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerContextDecl::~AnalyzerContextDecl()
|
||||||
|
{
|
||||||
|
delete context_name_id_;
|
||||||
|
delete_list(ContextFieldList, context_fields_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerContextDecl::GenForwardDeclaration(Output *out_h)
|
||||||
|
{
|
||||||
|
GenNamespaceBegin(out_h);
|
||||||
|
TypeDecl::GenForwardDeclaration(out_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerContextDecl::GenCode(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
GenNamespaceBegin(out_h);
|
||||||
|
GenNamespaceBegin(out_cc);
|
||||||
|
TypeDecl::GenCode(out_h, out_cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerContextDecl::GenNamespaceBegin(Output *out) const
|
||||||
|
{
|
||||||
|
out->println("namespace %s {", context_name_id()->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerContextDecl::GenNamespaceEnd(Output *out) const
|
||||||
|
{
|
||||||
|
out->println("} // namespace %s", context_name_id()->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerContextDecl::AddFlowBuffer()
|
||||||
|
{
|
||||||
|
if ( flow_buffer_added_ )
|
||||||
|
return;
|
||||||
|
|
||||||
|
AddParam(new Param(
|
||||||
|
new ID(kFlowBufferVar),
|
||||||
|
FlowDecl::flow_buffer_type()->Clone()));
|
||||||
|
|
||||||
|
flow_buffer_added_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AnalyzerContextDecl::mb_buffer(Env *env)
|
||||||
|
{
|
||||||
|
// A hack. The orthodox way would be to build an Expr of
|
||||||
|
// context.flow_buffer_var, and then EvalExpr.
|
||||||
|
return fmt("%s->%s()",
|
||||||
|
env->RValue(analyzer_context_id),
|
||||||
|
kFlowBufferVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *DummyType::DoClone() const
|
||||||
|
{
|
||||||
|
// Fields will be copied in Type::Clone().
|
||||||
|
return new DummyType();
|
||||||
|
}
|
97
aux/binpac/src/pac_context.h
Normal file
97
aux/binpac/src/pac_context.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
#ifndef pac_context_h
|
||||||
|
#define pac_context_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_field.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
#include "pac_typedecl.h"
|
||||||
|
|
||||||
|
// AnalyzerContext represents a cookie that an analyzer gives to
|
||||||
|
// parse functions of various message types. The cookie is parsed
|
||||||
|
// to every parse function (if necessary) as parameter 'binpac_context'.
|
||||||
|
//
|
||||||
|
// The members of the cookie is declared through 'analyzer' declarations,
|
||||||
|
// such as in:
|
||||||
|
//
|
||||||
|
// analyzer SunRPC withcontext {
|
||||||
|
// connection: RPC_Conn;
|
||||||
|
// flow: RPC_Flow;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// The cookie usually contains the connection and flow in which
|
||||||
|
// the message appears, and the context information can be
|
||||||
|
// accessed as members of the cookie, such as
|
||||||
|
// ``binpac_context.connection''.
|
||||||
|
|
||||||
|
class ContextField : public Field
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ContextField(ID *id, Type *type);
|
||||||
|
};
|
||||||
|
|
||||||
|
class AnalyzerContextDecl : public TypeDecl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AnalyzerContextDecl(ID *id, ContextFieldList *context_fields);
|
||||||
|
~AnalyzerContextDecl();
|
||||||
|
|
||||||
|
void AddFlowBuffer();
|
||||||
|
|
||||||
|
const ID *context_name_id() const { return context_name_id_; }
|
||||||
|
|
||||||
|
// The type of analyzer context as a parameter
|
||||||
|
ParameterizedType *param_type() const { return param_type_; }
|
||||||
|
|
||||||
|
void GenForwardDeclaration(Output *out_h);
|
||||||
|
void GenCode(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
void GenNamespaceBegin(Output *out) const;
|
||||||
|
void GenNamespaceEnd(Output *out) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ID *context_name_id_;
|
||||||
|
ContextFieldList *context_fields_;
|
||||||
|
ParameterizedType *param_type_;
|
||||||
|
bool flow_buffer_added_;
|
||||||
|
|
||||||
|
// static members
|
||||||
|
public:
|
||||||
|
static AnalyzerContextDecl *current_analyzer_context()
|
||||||
|
{
|
||||||
|
return current_analyzer_context_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string mb_buffer(Env *env);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static AnalyzerContextDecl *current_analyzer_context_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DummyType : public Type
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DummyType() : Type(DUMMY) {}
|
||||||
|
|
||||||
|
bool DefineValueVar() const { return false; }
|
||||||
|
string DataTypeStr() const { ASSERT(0); return ""; }
|
||||||
|
|
||||||
|
int StaticSize(Env* env) const { ASSERT(0); return -1; }
|
||||||
|
|
||||||
|
bool ByteOrderSensitive() const { return false; }
|
||||||
|
|
||||||
|
bool IsPointerType() const { ASSERT(0); return false; }
|
||||||
|
|
||||||
|
void DoGenParseCode(Output* out, Env* env,
|
||||||
|
const DataPtr& data, int flags)
|
||||||
|
{ ASSERT(0); }
|
||||||
|
|
||||||
|
// Generate code for computing the dynamic size of the type
|
||||||
|
void GenDynamicSize(Output* out, Env* env, const DataPtr& data)
|
||||||
|
{ ASSERT(0); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Type *DoClone() const;
|
||||||
|
void DoMarkIncrementalInput() { ASSERT(0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_context_h
|
127
aux/binpac/src/pac_cstr.cc
Normal file
127
aux/binpac/src/pac_cstr.cc
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
#include "pac_cstr.h"
|
||||||
|
#include "pac_dbg.h"
|
||||||
|
#include "pac_exception.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class EscapeException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit EscapeException(const string &s)
|
||||||
|
{
|
||||||
|
msg_ = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string &msg() const { return msg_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
string msg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copied from util.cc of Bro
|
||||||
|
int expand_escape(const char*& s)
|
||||||
|
{
|
||||||
|
switch ( *(s++) ) {
|
||||||
|
case 'b': return '\b';
|
||||||
|
case 'f': return '\f';
|
||||||
|
case 'n': return '\n';
|
||||||
|
case 'r': return '\r';
|
||||||
|
case 't': return '\t';
|
||||||
|
case 'a': return '\a';
|
||||||
|
case 'v': return '\v';
|
||||||
|
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7':
|
||||||
|
{ // \<octal>{1,3}
|
||||||
|
--s; // put back the first octal digit
|
||||||
|
const char* start = s;
|
||||||
|
|
||||||
|
// Don't increment inside loop control
|
||||||
|
// because if isdigit() is a macro it might
|
||||||
|
// expand into multiple increments ...
|
||||||
|
|
||||||
|
// Here we define a maximum length for escape sequence
|
||||||
|
// to allow easy handling of string like: "^H0" as
|
||||||
|
// "\0100".
|
||||||
|
|
||||||
|
for ( int len = 0; len < 3 && isascii(*s) && isdigit(*s); ++s, ++len)
|
||||||
|
;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if ( sscanf(start, "%3o", &result) != 1 )
|
||||||
|
{
|
||||||
|
throw EscapeException(fmt("bad octal escape: \"%s", start));
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
{ /* \x<hex> */
|
||||||
|
const char* start = s;
|
||||||
|
|
||||||
|
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
|
||||||
|
for ( int len = 0; len < 2 && isascii(*s) && isxdigit(*s);
|
||||||
|
++s, ++len)
|
||||||
|
;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if ( sscanf(start, "%2x", &result) != 1 )
|
||||||
|
{
|
||||||
|
throw EscapeException(fmt("bad hexadecimal escape: \"%s", start));
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return s[-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // private namespace
|
||||||
|
|
||||||
|
ConstString::ConstString(const string &s)
|
||||||
|
: str_(s)
|
||||||
|
{
|
||||||
|
// Copied from scan.l of Bro
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const char* text = str_.c_str();
|
||||||
|
int len = strlen(text) + 1;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
char* s = new char[len];
|
||||||
|
|
||||||
|
// Skip leading quote.
|
||||||
|
for ( ++text; *text; ++text )
|
||||||
|
{
|
||||||
|
if ( *text == '\\' )
|
||||||
|
{
|
||||||
|
++text; // skip '\'
|
||||||
|
s[i++] = expand_escape(text);
|
||||||
|
--text; // point to end of sequence
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s[i++] = *text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(i < len);
|
||||||
|
|
||||||
|
// Get rid of trailing quote.
|
||||||
|
ASSERT(s[i-1] == '"');
|
||||||
|
s[i-1] = '\0';
|
||||||
|
|
||||||
|
unescaped_ = s;
|
||||||
|
delete [] s;
|
||||||
|
}
|
||||||
|
catch(EscapeException const &e)
|
||||||
|
{
|
||||||
|
// Throw again with the object
|
||||||
|
throw Exception(this, e.msg().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
23
aux/binpac/src/pac_cstr.h
Normal file
23
aux/binpac/src/pac_cstr.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef pac_cstr_h
|
||||||
|
#define pac_cstr_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
|
||||||
|
class ConstString : public Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConstString(const string &s);
|
||||||
|
|
||||||
|
// The string in its escaped form, with surrounding '"'s
|
||||||
|
const string &str() const { return str_; }
|
||||||
|
const char *c_str() const { return str_.c_str(); }
|
||||||
|
|
||||||
|
// The unescaped string, without surrounding '"'s
|
||||||
|
const string &unescaped() const { return unescaped_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
string str_;
|
||||||
|
string unescaped_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_cstr_h
|
21
aux/binpac/src/pac_ctype.cc
Normal file
21
aux/binpac/src/pac_ctype.cc
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "pac_ctype.h"
|
||||||
|
|
||||||
|
string CType::DeclareInstance(const string &var) const
|
||||||
|
{
|
||||||
|
return strfmt("%s %s", name().c_str(), var.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
string CType::DeclareConstReference(const string &var) const
|
||||||
|
{
|
||||||
|
return strfmt("%s const &%s", name().c_str(), var.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
string CType::DeclareConstPointer(const string &var) const
|
||||||
|
{
|
||||||
|
return strfmt("%s const *%s", name().c_str(), var.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
string CType::DeclarePointer(const string &var) const
|
||||||
|
{
|
||||||
|
return strfmt("%s *%s", name().c_str(), var.c_str());
|
||||||
|
}
|
23
aux/binpac/src/pac_ctype.h
Normal file
23
aux/binpac/src/pac_ctype.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef pac_ctype_h
|
||||||
|
#define pac_ctype_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
|
||||||
|
// Represents a C++ type
|
||||||
|
class CType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CType(const string &name);
|
||||||
|
|
||||||
|
string name() const { return name_; }
|
||||||
|
|
||||||
|
string DeclareInstance(const string &var) const;
|
||||||
|
string DeclareConstReference(const string &var) const;
|
||||||
|
string DeclareConstPointer(const string &var) const;
|
||||||
|
string DeclarePointer(const string &var) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_ctype_h
|
76
aux/binpac/src/pac_datadep.cc
Normal file
76
aux/binpac/src/pac_datadep.cc
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include "pac_datadep.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
|
||||||
|
DataDepElement::DataDepElement(DDE_Type type)
|
||||||
|
: dde_type_(type), in_traversal(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataDepElement::Traverse(DataDepVisitor *visitor)
|
||||||
|
{
|
||||||
|
// Avoid infinite loop
|
||||||
|
if ( in_traversal )
|
||||||
|
return true;
|
||||||
|
if ( ! visitor->PreProcess(this) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
in_traversal = true;
|
||||||
|
bool cont = DoTraverse(visitor);
|
||||||
|
in_traversal = false;
|
||||||
|
|
||||||
|
if ( ! cont )
|
||||||
|
return false;
|
||||||
|
if ( ! visitor->PostProcess(this) )
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr *DataDepElement::expr()
|
||||||
|
{
|
||||||
|
return static_cast<Expr *>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *DataDepElement::type()
|
||||||
|
{
|
||||||
|
return static_cast<Type *>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RequiresAnalyzerContext::PreProcess(DataDepElement *element)
|
||||||
|
{
|
||||||
|
switch ( element->dde_type() )
|
||||||
|
{
|
||||||
|
case DataDepElement::EXPR:
|
||||||
|
ProcessExpr(element->expr());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue traversal until we know the answer is 'yes'
|
||||||
|
return ! requires_analyzer_context_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RequiresAnalyzerContext::PostProcess(DataDepElement *element)
|
||||||
|
{
|
||||||
|
return ! requires_analyzer_context_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequiresAnalyzerContext::ProcessExpr(Expr *expr)
|
||||||
|
{
|
||||||
|
if ( expr->expr_type() == Expr::EXPR_ID )
|
||||||
|
{
|
||||||
|
requires_analyzer_context_ =
|
||||||
|
(requires_analyzer_context_ ||
|
||||||
|
*expr->id() == *analyzer_context_id ||
|
||||||
|
*expr->id() == *context_macro_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RequiresAnalyzerContext::compute(DataDepElement *element)
|
||||||
|
{
|
||||||
|
RequiresAnalyzerContext visitor;
|
||||||
|
element->Traverse(&visitor);
|
||||||
|
return visitor.requires_analyzer_context_;
|
||||||
|
}
|
71
aux/binpac/src/pac_datadep.h
Normal file
71
aux/binpac/src/pac_datadep.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#ifndef pac_datadep_h
|
||||||
|
#define pac_datadep_h
|
||||||
|
|
||||||
|
// To provide a way to traverse through the data dependency graph.
|
||||||
|
// That is, to evaluate X, what must be evaluated.
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_dbg.h"
|
||||||
|
|
||||||
|
class DataDepVisitor;
|
||||||
|
|
||||||
|
class DataDepElement {
|
||||||
|
public:
|
||||||
|
enum DDE_Type {
|
||||||
|
ATTR,
|
||||||
|
CASEEXPR,
|
||||||
|
EXPR,
|
||||||
|
FIELD,
|
||||||
|
INPUT_BUFFER,
|
||||||
|
PARAM,
|
||||||
|
TYPE,
|
||||||
|
};
|
||||||
|
|
||||||
|
DataDepElement(DDE_Type type);
|
||||||
|
virtual ~DataDepElement() {}
|
||||||
|
|
||||||
|
// Returns whether to continue traversal
|
||||||
|
bool Traverse(DataDepVisitor *visitor);
|
||||||
|
|
||||||
|
// Returns whether to continue traversal
|
||||||
|
virtual bool DoTraverse(DataDepVisitor *visitor) = 0;
|
||||||
|
|
||||||
|
DDE_Type dde_type() const { return dde_type_; }
|
||||||
|
Expr *expr();
|
||||||
|
Type *type();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DDE_Type dde_type_;
|
||||||
|
bool in_traversal;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DataDepVisitor {
|
||||||
|
public:
|
||||||
|
virtual ~DataDepVisitor() {}
|
||||||
|
// Returns whether to continue traversal
|
||||||
|
virtual bool PreProcess(DataDepElement *element) = 0;
|
||||||
|
virtual bool PostProcess(DataDepElement *element) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RequiresAnalyzerContext : public DataDepVisitor {
|
||||||
|
public:
|
||||||
|
RequiresAnalyzerContext() : requires_analyzer_context_(false) {}
|
||||||
|
|
||||||
|
// Returns whether to continue traversal
|
||||||
|
bool PreProcess(DataDepElement *element);
|
||||||
|
bool PostProcess(DataDepElement *element);
|
||||||
|
|
||||||
|
bool requires_analyzer_context() const
|
||||||
|
{
|
||||||
|
return requires_analyzer_context_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool compute(DataDepElement *element);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ProcessExpr(Expr *expr);
|
||||||
|
|
||||||
|
bool requires_analyzer_context_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_datadep_h
|
66
aux/binpac/src/pac_dataptr.cc
Normal file
66
aux/binpac/src/pac_dataptr.cc
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_utils.h"
|
||||||
|
|
||||||
|
#include "pac_dataptr.h"
|
||||||
|
|
||||||
|
DataPtr::DataPtr(Env* env, const ID* id, const int offset)
|
||||||
|
: id_(id), offset_(offset)
|
||||||
|
{
|
||||||
|
if ( id_ )
|
||||||
|
{
|
||||||
|
if ( ! env->Evaluated(id_) )
|
||||||
|
throw ExceptionIDNotEvaluated(id_);
|
||||||
|
|
||||||
|
if ( offset_ == 0 )
|
||||||
|
ptr_expr_ = strfmt("%s", env->RValue(id_));
|
||||||
|
else
|
||||||
|
ptr_expr_ = strfmt("(%s + %d)", env->RValue(id_), offset_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ptr_expr_ = "(null id)";
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataPtr::AbsOffset(const ID* base_ptr) const
|
||||||
|
{
|
||||||
|
return ( id() == base_ptr ) ? offset() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* DataPtr::AbsOffsetExpr(Env* env, const ID* base_ptr) const
|
||||||
|
{
|
||||||
|
if ( AbsOffset(base_ptr) >= 0 )
|
||||||
|
return nfmt("%d", offset());
|
||||||
|
else
|
||||||
|
return nfmt("(%s - %s)", ptr_expr(), env->RValue(base_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataPtr::GenBoundaryCheck(Output* out_cc, Env* env,
|
||||||
|
const char* data_size, const char* data_name) const
|
||||||
|
{
|
||||||
|
ASSERT(id_);
|
||||||
|
|
||||||
|
out_cc->println("// Checking out-of-bound for \"%s\"", data_name);
|
||||||
|
out_cc->println("if ( %s + (%s) > %s )",
|
||||||
|
ptr_expr(),
|
||||||
|
data_size,
|
||||||
|
env->RValue(end_of_data));
|
||||||
|
|
||||||
|
out_cc->inc_indent();
|
||||||
|
out_cc->println("{");
|
||||||
|
|
||||||
|
char* data_offset = AbsOffsetExpr(env, begin_of_data);
|
||||||
|
|
||||||
|
out_cc->println("// Handle out-of-bound condition");
|
||||||
|
out_cc->println("throw ExceptionOutOfBound(\"%s\",", data_name);
|
||||||
|
out_cc->println(" (%s) + (%s), ",
|
||||||
|
data_offset, data_size);
|
||||||
|
out_cc->println(" (%s) - (%s));",
|
||||||
|
env->RValue(end_of_data), env->RValue(begin_of_data));
|
||||||
|
|
||||||
|
delete [] data_offset;
|
||||||
|
|
||||||
|
out_cc->println("}");
|
||||||
|
out_cc->dec_indent();
|
||||||
|
}
|
||||||
|
|
47
aux/binpac/src/pac_dataptr.h
Normal file
47
aux/binpac/src/pac_dataptr.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef pac_dataptr_h
|
||||||
|
#define pac_dataptr_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "pac_common.h"
|
||||||
|
|
||||||
|
// A data pointer is represented by an data pointer variable
|
||||||
|
// plus a constant offset.
|
||||||
|
|
||||||
|
class DataPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DataPtr(Env* env, const ID* arg_id, const int arg_off);
|
||||||
|
|
||||||
|
DataPtr const &operator=(DataPtr const &x)
|
||||||
|
{
|
||||||
|
id_ = x.id();
|
||||||
|
offset_ = x.offset();
|
||||||
|
ptr_expr_ = x.ptr_expr();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ID* id() const { return id_; }
|
||||||
|
int offset() const { return offset_; }
|
||||||
|
|
||||||
|
const char* ptr_expr() const
|
||||||
|
{
|
||||||
|
ASSERT(id_);
|
||||||
|
return ptr_expr_.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbsOffset(const ID* base_ptr) const;
|
||||||
|
char* AbsOffsetExpr(Env* env, const ID* base_ptr) const;
|
||||||
|
|
||||||
|
void GenBoundaryCheck(Output* out,
|
||||||
|
Env* env,
|
||||||
|
const char* data_size,
|
||||||
|
const char* data_name) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const ID* id_;
|
||||||
|
int offset_;
|
||||||
|
string ptr_expr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_dataptr_h
|
60
aux/binpac/src/pac_dataunit.cc
Normal file
60
aux/binpac/src/pac_dataunit.cc
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#include "pac_context.h"
|
||||||
|
#include "pac_dataunit.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_paramtype.h"
|
||||||
|
#include "pac_varfield.h"
|
||||||
|
|
||||||
|
AnalyzerDataUnit::AnalyzerDataUnit(
|
||||||
|
DataUnitType type,
|
||||||
|
ID *id,
|
||||||
|
ExprList *type_params,
|
||||||
|
ExprList *context_params)
|
||||||
|
: AnalyzerElement(DATAUNIT),
|
||||||
|
type_(type),
|
||||||
|
id_(id),
|
||||||
|
type_params_(type_params),
|
||||||
|
context_params_(context_params)
|
||||||
|
{
|
||||||
|
data_type_ = new ParameterizedType(id_, type_params_);
|
||||||
|
context_type_ = new ParameterizedType(
|
||||||
|
AnalyzerContextDecl::current_analyzer_context()->id()->clone(),
|
||||||
|
context_params_);
|
||||||
|
|
||||||
|
dataunit_var_field_ = new ParseVarField(
|
||||||
|
Field::CLASS_MEMBER,
|
||||||
|
dataunit_id->clone(),
|
||||||
|
data_type());
|
||||||
|
context_var_field_ = new PrivVarField(
|
||||||
|
analyzer_context_id->clone(),
|
||||||
|
context_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzerDataUnit::~AnalyzerDataUnit()
|
||||||
|
{
|
||||||
|
delete dataunit_var_field_;
|
||||||
|
delete context_var_field_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDataUnit::Prepare(Env *env)
|
||||||
|
{
|
||||||
|
dataunit_var_field_->Prepare(env);
|
||||||
|
context_var_field_->Prepare(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDataUnit::GenNewDataUnit(Output *out_cc, Env *env)
|
||||||
|
{
|
||||||
|
out_cc->println("%s = new %s(%s);",
|
||||||
|
env->LValue(dataunit_id),
|
||||||
|
data_type()->class_name().c_str(),
|
||||||
|
data_type()->EvalParameters(out_cc, env).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzerDataUnit::GenNewContext(Output *out_cc, Env *env)
|
||||||
|
{
|
||||||
|
out_cc->println("%s = new %s(%s);",
|
||||||
|
env->LValue(analyzer_context_id),
|
||||||
|
context_type()->class_name().c_str(),
|
||||||
|
context_type()->EvalParameters(out_cc, env).c_str());
|
||||||
|
env->SetEvaluated(analyzer_context_id);
|
||||||
|
}
|
||||||
|
|
49
aux/binpac/src/pac_dataunit.h
Normal file
49
aux/binpac/src/pac_dataunit.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef pac_dataunit_h
|
||||||
|
#define pac_dataunit_h
|
||||||
|
|
||||||
|
#include "pac_analyzer.h"
|
||||||
|
|
||||||
|
// The type and parameters of input data unit of a flow. For instance, the
|
||||||
|
// data unit of a DCE/RPC flow is DCE_RPC_PDU.
|
||||||
|
|
||||||
|
class AnalyzerDataUnit : public AnalyzerElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum DataUnitType { DATAGRAM, FLOWUNIT };
|
||||||
|
AnalyzerDataUnit(
|
||||||
|
DataUnitType type,
|
||||||
|
ID *id,
|
||||||
|
ExprList *type_params,
|
||||||
|
ExprList *context_params);
|
||||||
|
~AnalyzerDataUnit();
|
||||||
|
|
||||||
|
void Prepare(Env *env);
|
||||||
|
|
||||||
|
// Initializes dataunit_id
|
||||||
|
void GenNewDataUnit(Output *out_cc, Env *env);
|
||||||
|
// Initializes analyzer_context_id
|
||||||
|
void GenNewContext(Output *out_cc, Env *env);
|
||||||
|
|
||||||
|
DataUnitType type() const { return type_; }
|
||||||
|
const ID *id() const { return id_; }
|
||||||
|
ExprList *type_params() const { return type_params_; }
|
||||||
|
ExprList *context_params() const { return context_params_; }
|
||||||
|
|
||||||
|
ParameterizedType *data_type() const { return data_type_; }
|
||||||
|
ParameterizedType *context_type() const { return context_type_; }
|
||||||
|
|
||||||
|
Field *dataunit_var_field() const { return dataunit_var_field_; }
|
||||||
|
Field *context_var_field() const { return context_var_field_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
DataUnitType type_;
|
||||||
|
ID *id_;
|
||||||
|
ExprList *type_params_;
|
||||||
|
ExprList *context_params_;
|
||||||
|
ParameterizedType *data_type_;
|
||||||
|
ParameterizedType *context_type_;
|
||||||
|
Field *dataunit_var_field_;
|
||||||
|
Field *context_var_field_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_dataunit_h
|
14
aux/binpac/src/pac_dbg.h
Normal file
14
aux/binpac/src/pac_dbg.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/* $Id: pac_dbg.h 3265 2006-06-09 21:16:12Z rpang $ */
|
||||||
|
|
||||||
|
#ifndef pac_dbg_h
|
||||||
|
#define pac_dbg_h
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern bool FLAGS_pac_debug;
|
||||||
|
|
||||||
|
#define ASSERT(x) assert(x)
|
||||||
|
#define DEBUG_MSG(x...) if ( FLAGS_pac_debug ) fprintf(stderr, x)
|
||||||
|
|
||||||
|
#endif /* pac_dbg_h */
|
6
aux/binpac/src/pac_decl-inl.h
Normal file
6
aux/binpac/src/pac_decl-inl.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef pac_decl_inl_h
|
||||||
|
#define pac_decl_inl_h
|
||||||
|
|
||||||
|
#include "pac_id.h"
|
||||||
|
|
||||||
|
#endif // pac_decl_inl_h
|
191
aux/binpac/src/pac_decl.cc
Normal file
191
aux/binpac/src/pac_decl.cc
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
#include "pac_attr.h"
|
||||||
|
#include "pac_context.h"
|
||||||
|
#include "pac_dataptr.h"
|
||||||
|
#include "pac_embedded.h"
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
#include "pac_exttype.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_param.h"
|
||||||
|
#include "pac_record.h"
|
||||||
|
#include "pac_type.h"
|
||||||
|
#include "pac_utils.h"
|
||||||
|
|
||||||
|
#include "pac_decl.h"
|
||||||
|
|
||||||
|
DeclList *Decl::decl_list_ = 0;
|
||||||
|
Decl::DeclMap Decl::decl_map_;
|
||||||
|
|
||||||
|
Decl::Decl(ID* id, DeclType decl_type)
|
||||||
|
: id_(id), decl_type_(decl_type), attrlist_(0)
|
||||||
|
{
|
||||||
|
decl_map_[id_] = this;
|
||||||
|
if ( ! decl_list_ )
|
||||||
|
decl_list_ = new DeclList();
|
||||||
|
decl_list_->push_back(this);
|
||||||
|
|
||||||
|
DEBUG_MSG("Finished Decl %s\n", id_->Name());
|
||||||
|
|
||||||
|
analyzer_context_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Decl::~Decl()
|
||||||
|
{
|
||||||
|
delete id_;
|
||||||
|
delete_list(AttrList, attrlist_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decl::AddAttrs(AttrList* attrs)
|
||||||
|
{
|
||||||
|
if ( ! attrs )
|
||||||
|
return;
|
||||||
|
if ( ! attrlist_ )
|
||||||
|
attrlist_ = new AttrList();
|
||||||
|
foreach ( i, AttrList, attrs )
|
||||||
|
{
|
||||||
|
attrlist_->push_back(*i);
|
||||||
|
ProcessAttr(*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decl::ProcessAttr(Attr *attr)
|
||||||
|
{
|
||||||
|
throw Exception(attr, "unhandled attribute");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decl::SetAnalyzerContext()
|
||||||
|
{
|
||||||
|
analyzer_context_ =
|
||||||
|
AnalyzerContextDecl::current_analyzer_context();
|
||||||
|
if ( ! analyzer_context_ )
|
||||||
|
{
|
||||||
|
throw Exception(this,
|
||||||
|
"analyzer context not defined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decl::ProcessDecls(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
if ( ! decl_list_ )
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach(i, DeclList, decl_list_)
|
||||||
|
{
|
||||||
|
Decl *decl = *i;
|
||||||
|
current_decl_id = decl->id();
|
||||||
|
decl->Prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(i, DeclList, decl_list_)
|
||||||
|
{
|
||||||
|
Decl *decl = *i;
|
||||||
|
current_decl_id = decl->id();
|
||||||
|
decl->GenExternDeclaration(out_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_h->println("namespace binpac {\n");
|
||||||
|
out_cc->println("namespace binpac {\n");
|
||||||
|
|
||||||
|
AnalyzerContextDecl *analyzer_context =
|
||||||
|
AnalyzerContextDecl::current_analyzer_context();
|
||||||
|
|
||||||
|
foreach(i, DeclList, decl_list_)
|
||||||
|
{
|
||||||
|
Decl *decl = *i;
|
||||||
|
current_decl_id = decl->id();
|
||||||
|
decl->GenForwardDeclaration(out_h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( analyzer_context )
|
||||||
|
analyzer_context->GenNamespaceEnd(out_h);
|
||||||
|
|
||||||
|
out_h->println("");
|
||||||
|
|
||||||
|
foreach(i, DeclList, decl_list_)
|
||||||
|
{
|
||||||
|
Decl *decl = *i;
|
||||||
|
current_decl_id = decl->id();
|
||||||
|
decl->GenCode(out_h, out_cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( analyzer_context )
|
||||||
|
{
|
||||||
|
analyzer_context->GenNamespaceEnd(out_h);
|
||||||
|
analyzer_context->GenNamespaceEnd(out_cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_h->println("} // namespace binpac");
|
||||||
|
out_cc->println("} // namespace binpac");
|
||||||
|
}
|
||||||
|
|
||||||
|
Decl* Decl::LookUpDecl(const ID* id)
|
||||||
|
{
|
||||||
|
DeclMap::iterator it = decl_map_.find(id);
|
||||||
|
if ( it == decl_map_.end() )
|
||||||
|
return 0;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
int HelperDecl::helper_id_seq = 0;
|
||||||
|
|
||||||
|
HelperDecl::HelperDecl(HelperType helper_type,
|
||||||
|
ID* context_id,
|
||||||
|
EmbeddedCode* code)
|
||||||
|
: Decl(new ID(fmt("helper_%d", ++helper_id_seq)), HELPER),
|
||||||
|
helper_type_(helper_type),
|
||||||
|
context_id_(context_id),
|
||||||
|
code_(code)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HelperDecl::~HelperDecl()
|
||||||
|
{
|
||||||
|
delete context_id_;
|
||||||
|
delete code_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelperDecl::Prepare()
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelperDecl::GenExternDeclaration(Output *out_h)
|
||||||
|
{
|
||||||
|
if ( helper_type_ == EXTERN )
|
||||||
|
code_->GenCode(out_h, global_env());
|
||||||
|
}
|
||||||
|
|
||||||
|
void HelperDecl::GenCode(Output *out_h, Output *out_cc)
|
||||||
|
{
|
||||||
|
Env *env = global_env();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ( context_id_ )
|
||||||
|
{
|
||||||
|
Decl *decl = Decl::LookUpDecl(context_id_);
|
||||||
|
if ( ! decl )
|
||||||
|
{
|
||||||
|
throw Exception(context_id_,
|
||||||
|
fmt("cannot find declaration for %s",
|
||||||
|
context_id_->Name()));
|
||||||
|
}
|
||||||
|
env = decl->env();
|
||||||
|
if ( ! env )
|
||||||
|
{
|
||||||
|
throw Exception(context_id_,
|
||||||
|
fmt("not a type or analyzer: %s",
|
||||||
|
context_id_->Name()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( helper_type_ == HEADER )
|
||||||
|
code_->GenCode(out_h, env);
|
||||||
|
else if ( helper_type_ == CODE )
|
||||||
|
code_->GenCode(out_cc, env);
|
||||||
|
else if ( helper_type_ == EXTERN )
|
||||||
|
; // do nothing
|
||||||
|
else
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
81
aux/binpac/src/pac_decl.h
Normal file
81
aux/binpac/src/pac_decl.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#ifndef pac_decl_h
|
||||||
|
#define pac_decl_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
|
||||||
|
class Decl : public Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Note: ANALYZER is not for AnalyzerDecl (which is an
|
||||||
|
// abstract class) , but for AnalyzerContextDecl.
|
||||||
|
enum DeclType { ENUM, LET, TYPE, FUNC, CONN, FLOW, ANALYZER, HELPER, REGEX };
|
||||||
|
|
||||||
|
Decl(ID *id, DeclType decl_type);
|
||||||
|
virtual ~Decl();
|
||||||
|
|
||||||
|
const ID *id() const { return id_; }
|
||||||
|
DeclType decl_type() const { return decl_type_; }
|
||||||
|
AnalyzerContextDecl *analyzer_context() const
|
||||||
|
{ return analyzer_context_; }
|
||||||
|
|
||||||
|
// NULL except for TypeDecl or AnalyzerDecl
|
||||||
|
virtual Env *env() const { return 0; }
|
||||||
|
|
||||||
|
virtual void Prepare() = 0;
|
||||||
|
|
||||||
|
// Generate declarations out of the "binpac" namespace
|
||||||
|
virtual void GenExternDeclaration(Output *out_h) { /* do nothing */ }
|
||||||
|
|
||||||
|
// Generate declarations before definition of classes
|
||||||
|
virtual void GenForwardDeclaration(Output *out_h) = 0;
|
||||||
|
|
||||||
|
virtual void GenCode(Output *out_h, Output *out_cc) = 0;
|
||||||
|
|
||||||
|
void TakeExprList();
|
||||||
|
void AddAttrs(AttrList *attrlist);
|
||||||
|
void SetAnalyzerContext();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void ProcessAttr(Attr *a);
|
||||||
|
|
||||||
|
ID *id_;
|
||||||
|
DeclType decl_type_;
|
||||||
|
AttrList *attrlist_;
|
||||||
|
ExprList *expr_list_;
|
||||||
|
AnalyzerContextDecl *analyzer_context_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void ProcessDecls(Output *out_h, Output *out_cc);
|
||||||
|
static Decl *LookUpDecl(const ID *id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static DeclList *decl_list_;
|
||||||
|
typedef map<const ID *, Decl*, ID_ptr_cmp> DeclMap;
|
||||||
|
static DeclMap decl_map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HelperDecl : public Decl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum HelperType {
|
||||||
|
HEADER, CODE, EXTERN,
|
||||||
|
};
|
||||||
|
HelperDecl(HelperType type, ID *context_id, EmbeddedCode *code);
|
||||||
|
~HelperDecl();
|
||||||
|
|
||||||
|
void Prepare();
|
||||||
|
void GenExternDeclaration(Output *out_h);
|
||||||
|
void GenForwardDeclaration(Output *out_h) { /* do nothing */ }
|
||||||
|
void GenCode(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
HelperType helper_type_;
|
||||||
|
ID *context_id_;
|
||||||
|
ID *helper_id_;
|
||||||
|
EmbeddedCode *code_;
|
||||||
|
|
||||||
|
static int helper_id_seq;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_decl_h
|
82
aux/binpac/src/pac_embedded.cc
Normal file
82
aux/binpac/src/pac_embedded.cc
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_primitive.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
|
||||||
|
#include "pac_embedded.h"
|
||||||
|
|
||||||
|
EmbeddedCodeSegment::EmbeddedCodeSegment(const string &s)
|
||||||
|
: s_(s), primitive_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbeddedCodeSegment::EmbeddedCodeSegment(PacPrimitive *primitive)
|
||||||
|
: s_(""), primitive_(primitive)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbeddedCodeSegment::~EmbeddedCodeSegment()
|
||||||
|
{
|
||||||
|
delete primitive_;
|
||||||
|
}
|
||||||
|
|
||||||
|
string EmbeddedCodeSegment::ToCode(Env *env)
|
||||||
|
{
|
||||||
|
if ( primitive_ && s_.empty() )
|
||||||
|
s_ = primitive_->ToCode(env);
|
||||||
|
return s_;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbeddedCode::EmbeddedCode()
|
||||||
|
{
|
||||||
|
segments_ = new EmbeddedCodeSegmentList();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbeddedCode::~EmbeddedCode()
|
||||||
|
{
|
||||||
|
delete_list(EmbeddedCodeSegmentList, segments_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmbeddedCode::Append(int atom)
|
||||||
|
{
|
||||||
|
current_segment_ += static_cast<char>(atom);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmbeddedCode::Append(const char *str)
|
||||||
|
{
|
||||||
|
current_segment_ += str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmbeddedCode::Append(PacPrimitive *primitive)
|
||||||
|
{
|
||||||
|
if ( ! current_segment_.empty() )
|
||||||
|
{
|
||||||
|
segments_->push_back(new EmbeddedCodeSegment(current_segment_));
|
||||||
|
current_segment_ = "";
|
||||||
|
}
|
||||||
|
segments_->push_back(new EmbeddedCodeSegment(primitive));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmbeddedCode::GenCode(Output *out, Env *env)
|
||||||
|
{
|
||||||
|
if ( ! current_segment_.empty() )
|
||||||
|
{
|
||||||
|
segments_->push_back(new EmbeddedCodeSegment(current_segment_));
|
||||||
|
current_segment_ = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: return to the generated file after embedded code
|
||||||
|
// out->print("#line %d \"%s\"\n", line_num, filename.c_str());
|
||||||
|
|
||||||
|
// Allow use of RValue for undefined ID, in which case the
|
||||||
|
// ID's name is used as its RValue
|
||||||
|
env->set_allow_undefined_id(true);
|
||||||
|
|
||||||
|
foreach(i, EmbeddedCodeSegmentList, segments_)
|
||||||
|
{
|
||||||
|
EmbeddedCodeSegment *segment = *i;
|
||||||
|
out->print("%s", segment->ToCode(env).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
env->set_allow_undefined_id(false);
|
||||||
|
out->print("\n");
|
||||||
|
}
|
42
aux/binpac/src/pac_embedded.h
Normal file
42
aux/binpac/src/pac_embedded.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef pac_embedded_h
|
||||||
|
#define pac_embedded_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
|
||||||
|
class EmbeddedCodeSegment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit EmbeddedCodeSegment(const string &s);
|
||||||
|
explicit EmbeddedCodeSegment(PacPrimitive *primitive);
|
||||||
|
~EmbeddedCodeSegment();
|
||||||
|
|
||||||
|
string ToCode(Env *env);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string s_;
|
||||||
|
PacPrimitive *primitive_;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef vector<EmbeddedCodeSegment *> EmbeddedCodeSegmentList;
|
||||||
|
|
||||||
|
class EmbeddedCode : public Object
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EmbeddedCode();
|
||||||
|
~EmbeddedCode();
|
||||||
|
|
||||||
|
// Append a character
|
||||||
|
void Append(int atom);
|
||||||
|
void Append(const char *str);
|
||||||
|
|
||||||
|
// Append a PAC primitive
|
||||||
|
void Append(PacPrimitive *primitive);
|
||||||
|
|
||||||
|
void GenCode(Output *out, Env *env);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string current_segment_;
|
||||||
|
EmbeddedCodeSegmentList *segments_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_embedded_h
|
70
aux/binpac/src/pac_enum.cc
Normal file
70
aux/binpac/src/pac_enum.cc
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_enum.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
#include "pac_exttype.h"
|
||||||
|
#include "pac_output.h"
|
||||||
|
#include "pac_typedecl.h"
|
||||||
|
|
||||||
|
Enum::Enum(ID* id, Expr* expr)
|
||||||
|
: id_(id), expr_(expr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum::~Enum()
|
||||||
|
{
|
||||||
|
delete id_;
|
||||||
|
delete expr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enum::GenHeader(Output* out_h, int *pval)
|
||||||
|
{
|
||||||
|
ASSERT(pval);
|
||||||
|
if ( expr_ )
|
||||||
|
{
|
||||||
|
if ( ! expr_->ConstFold(global_env(), pval) )
|
||||||
|
throw ExceptionNonConstExpr(expr_);
|
||||||
|
out_h->println("%s = %d,", id_->Name(), *pval);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out_h->println("%s,", id_->Name());
|
||||||
|
global_env()->AddConstID(id_, *pval);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumDecl::EnumDecl(ID *id, EnumList *enumlist)
|
||||||
|
: Decl(id, ENUM), enumlist_(enumlist)
|
||||||
|
{
|
||||||
|
ID *type_id = id->clone();
|
||||||
|
datatype_ = new ExternType(type_id, ExternType::NUMBER);
|
||||||
|
extern_typedecl_ = new TypeDecl(type_id, 0, datatype_);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumDecl::~EnumDecl()
|
||||||
|
{
|
||||||
|
delete_list(EnumList, enumlist_);
|
||||||
|
delete extern_typedecl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumDecl::Prepare()
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumDecl::GenForwardDeclaration(Output *out_h)
|
||||||
|
{
|
||||||
|
out_h->println("enum %s {", id_->Name());
|
||||||
|
out_h->inc_indent();
|
||||||
|
int c = 0;
|
||||||
|
foreach(i, EnumList, enumlist_)
|
||||||
|
{
|
||||||
|
(*i)->GenHeader(out_h, &c);
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
out_h->dec_indent();
|
||||||
|
out_h->println("};");
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnumDecl::GenCode(Output* out_h, Output* /* out_cc */)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
37
aux/binpac/src/pac_enum.h
Normal file
37
aux/binpac/src/pac_enum.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef pac_enum_h
|
||||||
|
#define pac_enum_h
|
||||||
|
|
||||||
|
#include "pac_decl.h"
|
||||||
|
|
||||||
|
class Enum
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Enum(ID *id, Expr *expr = 0);
|
||||||
|
~Enum();
|
||||||
|
|
||||||
|
void GenHeader(Output *out_h, int *pval);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ID *id_;
|
||||||
|
Expr *expr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EnumDecl : public Decl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EnumDecl(ID *id, EnumList *enumlist);
|
||||||
|
~EnumDecl();
|
||||||
|
|
||||||
|
Type *DataType() const { return datatype_; }
|
||||||
|
|
||||||
|
void Prepare();
|
||||||
|
void GenForwardDeclaration(Output *out_h);
|
||||||
|
void GenCode(Output *out_h, Output *out_cc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
EnumList *enumlist_;
|
||||||
|
Type *datatype_;
|
||||||
|
TypeDecl *extern_typedecl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_enum_h
|
70
aux/binpac/src/pac_exception.cc
Normal file
70
aux/binpac/src/pac_exception.cc
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "pac_exception.h"
|
||||||
|
#include "pac_expr.h"
|
||||||
|
#include "pac_id.h"
|
||||||
|
#include "pac_utils.h"
|
||||||
|
|
||||||
|
Exception::Exception(const Object* o, const char* msg)
|
||||||
|
{
|
||||||
|
if ( o )
|
||||||
|
{
|
||||||
|
msg_ = o->Location();
|
||||||
|
msg_ += ": error : ";
|
||||||
|
}
|
||||||
|
if ( msg )
|
||||||
|
msg_ += msg;
|
||||||
|
if ( FLAGS_pac_debug )
|
||||||
|
{
|
||||||
|
DEBUG_MSG("Exception: %s\n", msg_.c_str());
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionIDNotFound::ExceptionIDNotFound(const ID* id)
|
||||||
|
: Exception(id), id_(id)
|
||||||
|
{
|
||||||
|
append(fmt("`%s' undeclared", id_->Name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionIDRedefinition::ExceptionIDRedefinition(const ID* id)
|
||||||
|
: Exception(id), id_(id)
|
||||||
|
{
|
||||||
|
append(fmt("`%s' redefined", id_->Name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionIDNotEvaluated::ExceptionIDNotEvaluated(const ID* id)
|
||||||
|
: Exception(id), id_(id)
|
||||||
|
{
|
||||||
|
append(fmt("ID `%s' not evaluated before used", id->Name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionIDNotField::ExceptionIDNotField(const ID* id)
|
||||||
|
: Exception(id), id_(id)
|
||||||
|
{
|
||||||
|
append(fmt("ID `%s' is not a field", id_->Name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionMemberNotFound::ExceptionMemberNotFound(const ID* type_id,
|
||||||
|
const ID *member_id)
|
||||||
|
: Exception(member_id), type_id_(type_id), member_id_(member_id)
|
||||||
|
{
|
||||||
|
append(fmt("type %s does not have member `%s'",
|
||||||
|
type_id_->Name(), member_id_->Name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionCyclicDependence::ExceptionCyclicDependence(const ID* id)
|
||||||
|
: Exception(id), id_(id)
|
||||||
|
{
|
||||||
|
append(fmt("cyclic dependence through `%s'", id_->Name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionPaddingError::ExceptionPaddingError(const Object* o, const char* msg)
|
||||||
|
: Exception(o)
|
||||||
|
{
|
||||||
|
append(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExceptionNonConstExpr::ExceptionNonConstExpr(const Expr* expr)
|
||||||
|
: Exception(expr)
|
||||||
|
{
|
||||||
|
append(fmt("Expression `%s' is not constant", expr->orig()));
|
||||||
|
}
|
97
aux/binpac/src/pac_exception.h
Normal file
97
aux/binpac/src/pac_exception.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
// $Id: pac_exception.h 3225 2006-06-08 00:00:01Z vern $
|
||||||
|
|
||||||
|
#ifndef pac_exception_h
|
||||||
|
#define pac_exception_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
|
||||||
|
class Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Exception(const Object* o, const char* msg = 0);
|
||||||
|
|
||||||
|
const char* msg() const { return msg_.c_str(); }
|
||||||
|
void append(const char* s) { msg_ += s; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
string msg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionIDNotFound : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionIDNotFound(const ID* id);
|
||||||
|
const ID* id() const { return id_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ID* id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionIDRedefinition : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionIDRedefinition(const ID* id);
|
||||||
|
const ID* id() const { return id_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ID* id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionIDNotEvaluated : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionIDNotEvaluated(const ID* id);
|
||||||
|
const ID* id() const { return id_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ID* id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionCyclicDependence : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionCyclicDependence(const ID* id);
|
||||||
|
const ID* id() const { return id_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ID* id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionPaddingError : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionPaddingError(const Object* o, const char* msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionIDNotField : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionIDNotField(const ID* id);
|
||||||
|
const ID* id() const { return id_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ID* id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionMemberNotFound : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionMemberNotFound(const ID* type_id, const ID *member_id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ID *type_id_, *member_id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ExceptionNonConstExpr : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ExceptionNonConstExpr(const Expr* expr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Expr *expr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* pac_exception_h */
|
1041
aux/binpac/src/pac_expr.cc
Normal file
1041
aux/binpac/src/pac_expr.cc
Normal file
File diff suppressed because it is too large
Load diff
34
aux/binpac/src/pac_expr.def
Normal file
34
aux/binpac/src/pac_expr.def
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
EXPR_DEF(EXPR_ID, 0, "%s")
|
||||||
|
EXPR_DEF(EXPR_NUM, 0, "%s")
|
||||||
|
EXPR_DEF(EXPR_CSTR, 0, "%s")
|
||||||
|
EXPR_DEF(EXPR_REGEX, 0, "REGEX(%s)")
|
||||||
|
EXPR_DEF(EXPR_SUBSCRIPT, 2, "@element@(%s[%s])")
|
||||||
|
EXPR_DEF(EXPR_MEMBER, 2, "@%s->%s@")
|
||||||
|
EXPR_DEF(EXPR_PAREN, 1, " ( %s ) ")
|
||||||
|
EXPR_DEF(EXPR_CALL, 1, "%s(%s)")
|
||||||
|
EXPR_DEF(EXPR_CALLARGS, -1, "@custom@")
|
||||||
|
EXPR_DEF(EXPR_SIZEOF, 1, "@sizeof(%s)@")
|
||||||
|
EXPR_DEF(EXPR_OFFSETOF, 1, "@offsetof(%s)@")
|
||||||
|
EXPR_DEF(EXPR_NEG, 1, "-%s")
|
||||||
|
EXPR_DEF(EXPR_PLUS, 2, "%s + %s")
|
||||||
|
EXPR_DEF(EXPR_MINUS, 2, "%s - %s")
|
||||||
|
EXPR_DEF(EXPR_TIMES, 2, "%s * %s")
|
||||||
|
EXPR_DEF(EXPR_DIV, 2, "%s / %s")
|
||||||
|
EXPR_DEF(EXPR_MOD, 2, "%s %% %s")
|
||||||
|
EXPR_DEF(EXPR_BITNOT, 1, "~%s")
|
||||||
|
EXPR_DEF(EXPR_BITAND, 2, "%s & %s")
|
||||||
|
EXPR_DEF(EXPR_BITOR, 2, "%s | %s")
|
||||||
|
EXPR_DEF(EXPR_BITXOR, 2, "%s ^ %s")
|
||||||
|
EXPR_DEF(EXPR_LSHIFT, 2, "%s << %s")
|
||||||
|
EXPR_DEF(EXPR_RSHIFT, 2, "%s >> %s")
|
||||||
|
EXPR_DEF(EXPR_EQUAL, 2, "%s == %s")
|
||||||
|
EXPR_DEF(EXPR_NEQ, 2, "%s != %s")
|
||||||
|
EXPR_DEF(EXPR_GE, 2, "%s >= %s")
|
||||||
|
EXPR_DEF(EXPR_LE, 2, "%s <= %s")
|
||||||
|
EXPR_DEF(EXPR_GT, 2, "%s > %s")
|
||||||
|
EXPR_DEF(EXPR_LT, 2, "%s < %s")
|
||||||
|
EXPR_DEF(EXPR_NOT, 1, "! %s")
|
||||||
|
EXPR_DEF(EXPR_AND, 2, "%s && %s")
|
||||||
|
EXPR_DEF(EXPR_OR, 2, "%s || %s")
|
||||||
|
EXPR_DEF(EXPR_COND, 3, "%s ? %s : %s")
|
||||||
|
EXPR_DEF(EXPR_CASE, -1, "@custom@")
|
139
aux/binpac/src/pac_expr.h
Normal file
139
aux/binpac/src/pac_expr.h
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
#ifndef pac_expr_h
|
||||||
|
#define pac_expr_h
|
||||||
|
|
||||||
|
#include "pac_common.h"
|
||||||
|
#include "pac_datadep.h"
|
||||||
|
|
||||||
|
class CaseExpr;
|
||||||
|
|
||||||
|
class Expr : public Object, public DataDepElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ExprType {
|
||||||
|
# define EXPR_DEF(type, x, y) type,
|
||||||
|
# include "pac_expr.def"
|
||||||
|
# undef EXPR_DEF
|
||||||
|
};
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
Expr(ID *id);
|
||||||
|
Expr(Number *num);
|
||||||
|
Expr(ConstString *s);
|
||||||
|
Expr(RegEx *regex);
|
||||||
|
Expr(ExprList *args); // for EXPR_CALLARGS
|
||||||
|
Expr(Expr *index, CaseExprList *cases);
|
||||||
|
|
||||||
|
Expr(ExprType type, Expr *op1);
|
||||||
|
Expr(ExprType type, Expr *op1, Expr *op2);
|
||||||
|
Expr(ExprType type, Expr *op1, Expr *op2, Expr *op3);
|
||||||
|
|
||||||
|
virtual ~Expr();
|
||||||
|
|
||||||
|
const char *orig() const { return orig_.c_str(); }
|
||||||
|
const ID *id() const { return id_; }
|
||||||
|
const char *str() const { return str_.c_str(); }
|
||||||
|
ExprType expr_type() const { return expr_type_; }
|
||||||
|
|
||||||
|
void AddCaseExpr(CaseExpr *case_expr);
|
||||||
|
|
||||||
|
// Returns the data "type" of the expression. Here we only
|
||||||
|
// do a serious job for the EXPR_MEMBER and EXPR_SUBSCRIPT
|
||||||
|
// operators. For arithmetic operations, we fall back
|
||||||
|
// to "int".
|
||||||
|
Type *DataType(Env *env) const;
|
||||||
|
string DataTypeStr(Env *env) const;
|
||||||
|
|
||||||
|
// Note: EvalExpr() may generate C++ statements in order to evaluate
|
||||||
|
// variables in the expression, so the following is wrong:
|
||||||
|
//
|
||||||
|
// out->print("int x = ");
|
||||||
|
// out->println("%s", expr->EvalExpr(out, env));
|
||||||
|
//
|
||||||
|
// While putting them together is right:
|
||||||
|
//
|
||||||
|
// out->println("int x = %s", expr->EvalExpr(out, env));
|
||||||
|
//
|
||||||
|
const char *EvalExpr(Output *out, Env *env);
|
||||||
|
|
||||||
|
// force evaulation of IDs contained in this expression;
|
||||||
|
// necessary with case expr and conditional let fields (&if)
|
||||||
|
// for correct parsing of fields
|
||||||
|
void ForceIDEval(Output *out_cc, Env *env);
|
||||||
|
|
||||||
|
// Returns the set_* function of the expression.
|
||||||
|
// The expression must be of form ID or x.ID.
|
||||||
|
string SetFunc(Output *out, Env *env);
|
||||||
|
|
||||||
|
// Returns true if the expression folds to an integer
|
||||||
|
// constant with env, and puts the constant in *pn.
|
||||||
|
//
|
||||||
|
bool ConstFold(Env *env, int *pn) const;
|
||||||
|
|
||||||
|
// Whether id is referenced in the expression
|
||||||
|
bool HasReference(const ID *id) const;
|
||||||
|
|
||||||
|
// Suppose the data for type might be incomplete, what is
|
||||||
|
// the minimal number of bytes from data head required to
|
||||||
|
// compute the expression? For example, how many bytes of frame
|
||||||
|
// header do we need to determine the length of the frame?
|
||||||
|
//
|
||||||
|
// The parameter <env> points to the Env of a type.
|
||||||
|
//
|
||||||
|
// Returns -1 if the number is not a constant.
|
||||||
|
//
|
||||||
|
int MinimalHeaderSize(Env *env);
|
||||||
|
|
||||||
|
// Whether evaluation of the expression requires the analyzer context
|
||||||
|
bool RequiresAnalyzerContext() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool DoTraverse(DataDepVisitor *visitor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ExprType expr_type_;
|
||||||
|
|
||||||
|
int num_operands_;
|
||||||
|
Expr *operand_[3];
|
||||||
|
|
||||||
|
ID *id_; // EXPR_ID
|
||||||
|
Number *num_; // EXPR_NUM
|
||||||
|
ConstString *cstr_; // EXPR_CSTR
|
||||||
|
RegEx *regex_; // EXPR_REGEX
|
||||||
|
ExprList *args_; // EXPR_CALLARGS
|
||||||
|
CaseExprList *cases_; // EXPR_CASE
|
||||||
|
|
||||||
|
string str_; // value string
|
||||||
|
string orig_; // original string for debugging info
|
||||||
|
|
||||||
|
void GenStrFromFormat(Env *env);
|
||||||
|
void GenEval(Output *out, Env *env);
|
||||||
|
void GenCaseEval(Output *out_cc, Env *env);
|
||||||
|
};
|
||||||
|
|
||||||
|
string OrigExprList(ExprList *exprlist);
|
||||||
|
string EvalExprList(ExprList *exprlist, Output *out, Env *env);
|
||||||
|
|
||||||
|
// An entry of the case expression, consisting of one or more constant
|
||||||
|
// expressions for the case index and a value expression.
|
||||||
|
class CaseExpr : public Object, public DataDepElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CaseExpr(ExprList *index, Expr *value);
|
||||||
|
virtual ~CaseExpr();
|
||||||
|
|
||||||
|
ExprList *index() const { return index_; }
|
||||||
|
Expr *value() const { return value_; }
|
||||||
|
|
||||||
|
bool HasReference(const ID *id) const;
|
||||||
|
bool RequiresAnalyzerContext() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool DoTraverse(DataDepVisitor *visitor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ExprList *index_;
|
||||||
|
Expr *value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // pac_expr_h
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue