Merge branch 'master' into topic/seth/ssl-analyzer-work

This commit is contained in:
Seth Hall 2011-01-19 10:49:19 -05:00
commit 7ffbac68a4
857 changed files with 3251 additions and 217166 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
build

12
.gitmodules vendored Normal file
View file

@ -0,0 +1,12 @@
[submodule "aux/bro-aux"]
path = aux/bro-aux
url = git://git.icir.org/bro-aux
[submodule "aux/binpac"]
path = aux/binpac
url = git://git.icir.org/binpac
[submodule "aux/broccoli"]
path = aux/broccoli
url = git://git.icir.org/broccoli
[submodule "aux/broctl"]
path = aux/broctl
url = git://git.icir.org/broctl

View file

77
CHANGES
View file

@ -2,6 +2,83 @@
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1.6-dev.4 Sat Jan 15 14:14:21 PST 2011
- Updates to the build system (Jonathan Siwek)
* ``make dist`` is now available to be used with the top-level
Makefile for creating source packages according to #344.
* ``make-rpm-packages`` and ``make-mac-packages`` scripts can
now generate binary packages according to #295.
* Additional configure options to change packaging behavior.
* OS X builds will now prefer to link static libraries of
optional dependencies that don't come with the vanilla
operating system.
* Fix for OS X 10.5 compile error dealing with the llabs()
function from stdlib.
* Installing as a different user than the one that
configured/built now works (although, a harmless error message
about not being able to write the install manifest may occur).
1.6-dev.3 Wed Dec 8 04:09:38 PST 2010
- Merge with Subversion repository as of r7137. Incorporated change:
* Fix for packet processing resumption when a remote Bro dies
during state synchronization (Robin Sommer).
1.6-dev.2 Wed Dec 8 03:57:03 PST 2010
- Compatibility fix for OpenSSL 1.0.0 (Christian Kreibich, Gregor
Maier).
1.6-dev.1 Sat Nov 27 12:19:47 PST 2010
- Merge with Subversion repository as of r7098. Incorporated changes:
* Rotation post-processors are now passed an additional argument
indicating whether Bro is terminating (Robin Sommer).
* Bro now consistently generates a file_opened event for all
fopen() calls. (Robin Sommer).
* You can now redefine the email_notice_to function (Robin
Sommer).
1.6-dev.0 Fri Nov 26 13:48:11 PST 2010
- The Bro source code is now developed in the new git repositories.
See the developer pages at http://www.bro-ids.org for more
information on the new development process.
- Bro's build and installation setup has been moved from GNU
autotools to CMake. As a result of that, layout and specifics of
the distribution has changed significantly.
- Lots of pieces have been removed from the distribution that are
either now unnecessary or are no longer maintained.
- As part of the cleanup, a numbef of Bro configure options and
their corresponding functionality have been removed, including:
* --disable-select-loop
* --with-dag
* --disable-nbdns
* --enable-activemapping
* --enable-activemapping
* --enable-shippedpcap
- The previous configure option --enable-int64 is now enabled by default,
and can no longer be disabled.
- ClamAV support has been removed, which has been non-functional for
a while already.
1.5.2.7 Sun Sep 12 19:39:49 PDT 2010
- Addressed a number of lint nits (Vern Paxson).

238
CMakeLists.txt Normal file
View file

@ -0,0 +1,238 @@
project(Bro)
########################################################################
## CMake Configuration
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
# Prohibit in-source builds.
if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "In-source builds are not allowed. Please use "
"./configure to choose a build directory and "
"initialize the build configuration.")
endif ()
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
# uninstall target
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
@ONLY)
add_custom_target(uninstall COMMAND
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif ()
########################################################################
## Project/Build Configuration
set(BRO_ROOT_DIR ${CMAKE_INSTALL_PREFIX})
if (NOT POLICYDIR)
# set the default policy installation path (user did not specify one)
set(POLICYDIR ${BRO_ROOT_DIR}/share/bro)
endif ()
# sanitize the policy install directory into an absolute path
# (CMake is confused by ~ as a representation of home directory)
get_filename_component(POLICYDIR ${POLICYDIR} ABSOLUTE)
configure_file(bro-path-dev.in ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev)
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)
set(EXTRA_COMPILE_FLAGS "-Wall -Wno-unused")
if (ENABLE_DEBUG)
set(CMAKE_BUILD_TYPE Debug)
set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DDEBUG")
else ()
set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif ()
# Compiler flags may already exist in CMake cache (e.g. when specifying
# CFLAGS environment variable before running cmake for the the first time)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_COMPILE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_COMPILE_FLAGS}")
########################################################################
## Dependency Configuration
include(FindRequiredPackage)
# Check cache value first to avoid displaying "Found sed" messages everytime
if (NOT SED_EXE)
find_program(SED_EXE sed)
if (NOT SED_EXE)
message(FATAL_ERROR "Could not find required dependency: sed")
else ()
message(STATUS "Found sed: ${SED_EXE}")
endif ()
endif ()
FindRequiredPackage(Perl)
FindRequiredPackage(FLEX)
FindRequiredPackage(BISON)
FindRequiredPackage(PCAP)
FindRequiredPackage(OpenSSL)
FindRequiredPackage(BIND)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/aux/binpac/CMakeLists.txt)
add_subdirectory(aux/binpac)
endif ()
FindRequiredPackage(BinPAC)
if (MISSING_PREREQS)
foreach (prereq ${MISSING_PREREQ_DESCS})
message(SEND_ERROR ${prereq})
endforeach ()
message(FATAL_ERROR "Configuration aborted due to missing prerequisites")
endif ()
include_directories(BEFORE
${PCAP_INCLUDE_DIR}
${OpenSSL_INCLUDE_DIR}
${BIND_INCLUDE_DIR}
${BinPAC_INCLUDE_DIR}
)
# Optional Dependencies
set(HAVE_LIBMAGIC false)
find_package(LibMagic)
if (LIBMAGIC_FOUND)
set(HAVE_LIBMAGIC true)
include_directories(BEFORE ${LibMagic_INCLUDE_DIR})
list(APPEND OPTLIBS ${LibMagic_LIBRARY})
endif ()
set(HAVE_LIBZ false)
find_package(ZLIB)
if (ZLIB_FOUND)
set(HAVE_LIBZ true)
include_directories(BEFORE ${ZLIB_INCLUDE_DIR})
list(APPEND OPTLIBS ${ZLIB_LIBRARY})
endif ()
set(USE_GEOIP false)
find_package(LibGeoIP)
if (LIBGEOIP_FOUND)
set(USE_GEOIP true)
include_directories(BEFORE ${LibGeoIP_INCLUDE_DIR})
list(APPEND OPTLIBS ${LibGeoIP_LIBRARY})
endif ()
set(USE_PERFTOOLS false)
if (ENABLE_PERFTOOLS)
find_package(GooglePerftools)
if (GOOGLEPERFTOOLS_FOUND)
set(USE_PERFTOOLS true)
include_directories(BEFORE ${GooglePerftools_INCLUDE_DIR})
list(APPEND OPTLIBS ${GooglePerftools_LIBRARIES})
endif ()
endif ()
########################################################################
## System Introspection
include(TestBigEndian)
test_big_endian(WORDS_BIGENDIAN)
include(OSSpecific)
include(CheckTypes)
include(CheckHeaders)
include(CheckFunctions)
include(MiscTests)
include(PCAPTests)
include(OpenSSLTests)
include(CheckNameserCompat)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
########################################################################
## Recurse on sub-directories
add_subdirectory(src)
add_subdirectory(policy)
#add_subdirectory(scripts)
#add_subdirectory(doc)
include(CheckOptionalBuildSources)
CheckOptionalBuildSources(aux/broctl Broctl INSTALL_BROCTL)
CheckOptionalBuildSources(aux/bro-aux Bro-Aux INSTALL_AUX_TOOLS)
CheckOptionalBuildSources(aux/broccoli Broccoli INSTALL_BROCCOLI)
########################################################################
## Packaging Setup
if (INSTALL_BROCTL)
# CPack RPM Generator may not automatically detect this
set(CPACK_RPM_PACKAGE_REQUIRES "python >= 2.4.0")
endif ()
# If this CMake project is a sub-project of another, we will not
# configure the generic packaging because CPack will fail in the case
# that the parent project has already configured packaging
if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
include(ConfigurePackaging)
ConfigurePackaging(${VERSION})
endif ()
########################################################################
## Build Summary
if (CMAKE_BUILD_TYPE)
string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType)
endif ()
if (INSTALL_BROCTL)
if (STANDALONE)
set(BROCTL_INSTALL_MODE "standalone")
else ()
set(BROCTL_INSTALL_MODE "cluster")
endif ()
else ()
set(BROCTL_INSTALL_MODE "false")
endif ()
message(
"\n====================| Bro Build Summary |====================="
"\n"
"\nInstall prefix: ${CMAKE_INSTALL_PREFIX}"
"\nPolicy dir: ${POLICYDIR}"
"\nDebug mode: ${ENABLE_DEBUG}"
"\n"
"\nCC: ${CMAKE_C_COMPILER}"
"\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}"
"\nCXX: ${CMAKE_CXX_COMPILER}"
"\nCXXFLAGS: ${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BuildType}}"
"\nCPP: ${CMAKE_CXX_COMPILER}"
"\n"
"\nBroccoli: ${INSTALL_BROCCOLI}"
"\nBroctl: ${BROCTL_INSTALL_MODE}"
"\nAux. Tools: ${INSTALL_AUX_TOOLS}"
"\n"
"\nGeoIP: ${USE_GEOIP}"
"\nlibz: ${HAVE_LIBZ}"
"\nlibmagic: ${HAVE_LIBMAGIC}"
"\nGoogle perftools: ${USE_PERFTOOLS}"
"\n"
"\n================================================================\n"
)
########################################################################
## Show warning when installing user is different from the one that configured
install(CODE "
if (NOT $ENV{USER} STREQUAL \$ENV{USER})
message(STATUS \"ATTENTION: Install is being performed by user \"
\"'\$ENV{USER}', but the build directory was configured by \"
\"user '$ENV{USER}'. This may result in a permissions error \"
\"when writing the install manifest, but you can ignore it \"
\"and consider the installation as successful if you don't \"
\"care about the install manifest.\")
endif ()
")

View file

@ -1,4 +1,4 @@
Copyright (c) 1995-2008, The Regents of the University of California,
Copyright (c) 1995-2010, 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
@ -31,7 +31,7 @@ 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:
noted below) and the source files in src/, other than:
policy/sigs/p0fsyn.osf
src/H3.h
@ -44,6 +44,5 @@ noted below) and the source files in src/ , other than:
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/ .
In addition, other components, such as the build system, may have
separate copyrights.

View file

View file

@ -1,3 +1,6 @@
TODO: Needs update. -Robin
- Make sure BroV6 works.
- Make sure --enable-int64 builds w/o warnings.

View file

@ -1,3 +0,0 @@
README
VERSION
bro

135
INSTALL
View file

@ -1,104 +1,97 @@
==============
Installing Bro
==============
Prerequisites
=============
Bro relies on the following libraries and tools, which need to be installed
before you begin with the installation:
before you begin:
* 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.
* Libpcap headers and libraries
Network traffic capture library
* Flex
Flex is already installed on most systems, so with luck you can
skip having to install it yourself.
* Flex (Fast Lexical Analyzer)
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.
* Bison (GNU Parser Generator)
This comes with many systems, but if you get errors compiling
parse.y, you will need to install it.
* Perl
Used only during the Bro build process
* sed
Used only during the Bro build process
* BIND8 headers and libraries
These are usually already installed as well.
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.
* OpenSSL headers and libraries
For analysis of SSL certificates by the HTTP analyzer, and
for encrypted Bro-to-Bro communication. These are likely installed,
though some platforms may require installation of a 'devel' package
for the headers.
* CMake 2.8 or greater
CMake is a cross-platform, open-source build system, typically
not installed by default. See http://www.cmake.org for more
information regarding CMake and the installation steps below for
how to use it to build this distribution. CMake generates native
Makefiles that depend on GNU Make by default.
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).
For identifying file types (e.g., in FTP transfers).
* LibGeoIP
For geo-locating IP addresses.
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.
For decompressing HTTP bodies by the HTTP analyzer, and for
compressed Bro-to-Bro communication.
Installation
============
To build and install into /usr/local:
To build and install into /usr/local/bro:
> ./configure
> make
> make install
> ./configure
> cd build
> make
> make install
This will install the Bro binary into /usr/local/bin/bro and the policy
files into /usr/local/share/bro.
This will perform an out-of-source build into a directory called
build/, using default build options. It then installs the Bro binary
into /usr/local/bro/bin. Depending on the Bro package you
downloaded, there may be auxiliary tools and libraries available in
the aux/ directory. If so, they will be installed by default as well
if not explicitly disabled via configure options and may also have
additional installation/configuration instructions that you can
find in their source directories.
As usual you can specify a different installation directory with
You can specify a different installation directory with
> ./configure --prefix=<dir>".
> ./configure --prefix=<dir>
Run "./configure --help" for more options.
Note that "/usr" and "/opt/bro" are standard prefixes for binary
packages to be installed, so those are typically not good choices
unless you are creating such a package.
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.
with it. In the following we give a few simple examples. See the
quickstart guide at http://www.bro-ids.org for more information; you
can the source that in doc/quick-start.
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.
For developers that wish to run Bro after performing "make", but
without performing "make install", see build/bro-path-dev for
an example.

71
Makefile Normal file
View file

@ -0,0 +1,71 @@
#
# A simple static wrapper for a number of standard Makefile targets,
# mostly just forwarding to build/Makefile. This is provided only for
# convenience and supports only a subset of what CMake's Makefile
# to offer. For more, execute that one directly.
#
BUILD=build
BROCCOLI=aux/broccoli
BROCTL=aux/broctl
# CMake/CPack versions before 2.8.2 have bugs that can create bad packages
CMAKE_PACK_REQ=2.8.2
CMAKE_VER=`cmake -version`
OSX_VER_CMD=sw_vers | sed -n 's/ProductVersion://p' | cut -d . -f 2
all: configured
( cd $(BUILD) && make )
install: configured
( cd $(BUILD) && make install )
clean: configured
( cd $(BUILD) && make clean )
dist: cmake_version
# Minimum Bro source package
( \
./configure --ignore-dirs='aux/broctl;aux/broccoli' --pkg-name-prefix=Bro && \
cd $(BUILD) && \
make package_source \
)
# Full Bro source package
( \
./configure --pkg-name-prefix=Bro-all && \
cd $(BUILD) && \
make package_source \
)
# Broccoli source package
( \
cd $(BROCCOLI) && \
./configure && \
cd $(BUILD) && \
make package_source && \
mv Broccoli*.tar.gz ../../../$(BUILD)/ && \
cd .. && \
rm -r $(BUILD) \
)
# Broctl source package
( \
cd $(BROCTL) && \
./configure && \
cd $(BUILD) && \
make package_source && \
mv Broctl*.tar.gz ../../../$(BUILD)/ && \
cd .. && \
rm -r $(BUILD) \
)
distclean:
rm -rf $(BUILD)
configured:
@test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 )
@test -e $(BUILD)/Makefile || ( echo "Error: No build/Makefile found. Did you run configure?" && exit 1 )
cmake_version:
@test "$(CMAKE_VER)" \> "cmake version $(CMAKE_PACK_REQ)" || ( echo "Error: please use a CMake version greater than $(CMAKE_PACK_REQ)" && exit 1 )
.PHONY : all install clean distclean configured cmake_version

View file

@ -1,64 +0,0 @@
## 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
View file

29
README
View file

@ -1,29 +1,24 @@
This is release 1.5 of Bro, a system for detecting network intruders in
This is release 1.6 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:
Please see the file INSTALL for installation instructions and
pointers for getting started. For more documentation, see the
documentation on Bro's home page:
http://www.bro-ids.org/wiki/index.php/User_Manual
http://www.bro-ids.org/docs
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/).
The main parts of Bro's documentation are also available in the doc/
directory of the distribution. (Please note that the documentation
is still a work in progress; there will be more in future releases.)
Numerous other Bro-related publications, including a paper describing the
system, can be found at
http://www.bro-ids.org/publications.html
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.
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

View file

@ -1,9 +0,0 @@
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.

View file

@ -1 +1 @@
1.5.2.7
1.6-dev.4

File diff suppressed because it is too large Load diff

View file

@ -1,143 +0,0 @@
#!/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

View file

@ -1,77 +0,0 @@
## 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

View file

@ -1,61 +0,0 @@
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

View file

@ -1,10 +0,0 @@
## 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

View file

@ -1,92 +0,0 @@
#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);
}

View file

@ -1,59 +0,0 @@
/* @(#) $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

View file

@ -1,122 +0,0 @@
/*
* 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

View file

@ -1,159 +0,0 @@
/* @(#) $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 */

View file

@ -1,4 +0,0 @@
## Process this file with automake to produce Makefile.in
noinst_PROGRAMS = bdcat
bdcat_SOURCES = bdcat.cc

View file

@ -1,175 +0,0 @@
// $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;
}
}
}

1
aux/binpac Submodule

@ -0,0 +1 @@
Subproject commit 7bbd3b14c02321ff2a63d7267e9ae022bda4f5bc

View file

View file

View file

@ -1,18 +0,0 @@
// 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.

View file

View file

@ -1,231 +0,0 @@
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.

View file

@ -1,4 +0,0 @@
## Process this file with automake to produce Makefile.in
EXTRA_DIST = README VERSION CHANGES TODO depcomp shtool autogen.sh
SUBDIRS = lib src

View file

View file

View file

@ -1,34 +0,0 @@
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?

View file

@ -1 +0,0 @@
0.1

View file

@ -1,114 +0,0 @@
#!/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

View file

@ -1,55 +0,0 @@
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

View file

@ -1,8 +0,0 @@
## 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

View file

@ -1,3 +0,0 @@
This directory contains a library needed by generated C++ code from
binpac. Note that the library is not needed by the binpac compiler
itself.

View file

@ -1,142 +0,0 @@
// $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 */

View file

@ -1,27 +0,0 @@
#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

View file

@ -1,465 +0,0 @@
#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

View file

@ -1,148 +0,0 @@
#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

View file

@ -1,24 +0,0 @@
#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

View file

@ -1,199 +0,0 @@
#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

View file

@ -1,112 +0,0 @@
#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

View file

@ -1,43 +0,0 @@
#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

View file

@ -1,31 +0,0 @@
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;

View file

@ -1,97 +0,0 @@
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();

View file

@ -1,37 +0,0 @@
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_)

View file

@ -1,12 +0,0 @@
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() )

View file

@ -1,66 +0,0 @@
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() )
{

View file

@ -1,28 +0,0 @@
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("{");

View file

@ -1,21 +0,0 @@
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));

View file

@ -1,190 +0,0 @@
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;

View file

@ -1,87 +0,0 @@
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

View file

@ -1,172 +0,0 @@
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();

View file

@ -1,716 +0,0 @@
#!/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##

View file

@ -1,62 +0,0 @@
## 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

View file

@ -1,119 +0,0 @@
#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()));
}

View file

@ -1,74 +0,0 @@
#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

View file

@ -1,358 +0,0 @@
#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_;
}

View file

@ -1,168 +0,0 @@
#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

View file

@ -1,700 +0,0 @@
#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;
}

View file

@ -1,92 +0,0 @@
#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

View file

@ -1,57 +0,0 @@
#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;
}

View file

@ -1,61 +0,0 @@
#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

View file

@ -1,144 +0,0 @@
#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;
}
}

View file

@ -1,52 +0,0 @@
#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

View file

@ -1,391 +0,0 @@
#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();
}

View file

@ -1,99 +0,0 @@
#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

View file

@ -1,81 +0,0 @@
#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

View file

@ -1,134 +0,0 @@
#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

View file

@ -1,169 +0,0 @@
#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("");
}

View file

@ -1,34 +0,0 @@
#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

View file

@ -1,120 +0,0 @@
#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();
}

View file

@ -1,97 +0,0 @@
#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

View file

@ -1,127 +0,0 @@
#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());
}
}

View file

@ -1,23 +0,0 @@
#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

View file

@ -1,21 +0,0 @@
#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());
}

View file

@ -1,23 +0,0 @@
#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

View file

@ -1,76 +0,0 @@
#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_;
}

View file

@ -1,71 +0,0 @@
#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

View file

@ -1,66 +0,0 @@
#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();
}

View file

@ -1,47 +0,0 @@
#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

View file

@ -1,60 +0,0 @@
#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);
}

View file

@ -1,49 +0,0 @@
#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

View file

@ -1,14 +0,0 @@
/* $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 */

View file

@ -1,6 +0,0 @@
#ifndef pac_decl_inl_h
#define pac_decl_inl_h
#include "pac_id.h"
#endif // pac_decl_inl_h

View file

@ -1,191 +0,0 @@
#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);
}

View file

@ -1,81 +0,0 @@
#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

View file

@ -1,82 +0,0 @@
#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");
}

View file

@ -1,42 +0,0 @@
#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

View file

@ -1,70 +0,0 @@
#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
}

View file

@ -1,37 +0,0 @@
#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

Some files were not shown because too many files have changed in this diff Show more