Import Upstream version 4.0.2

This commit is contained in:
su-fang 2022-09-28 10:50:04 +08:00
commit 5025ac6627
5673 changed files with 662375 additions and 0 deletions

536
.travis.yml Normal file
View File

@ -0,0 +1,536 @@
language: cpp
matrix:
include:
- compiler: clang
os: linux
env: SWIGLANG=
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=4.4
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=4.6
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=4.7
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=4.8
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=4.9
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=6
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=7
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=8
sudo: required
dist: xenial
- os: linux
env: SWIGLANG= GCC=9
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=csharp
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=d VER=2.066.0
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=d VER=2.086.1
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=go VER=1.3
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=go VER=1.8
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=go VER=1.12
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=guile
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=java
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=javascript ENGINE=node VER=0.10
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=javascript ENGINE=node VER=4 CPP11=1
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=javascript ENGINE=node VER=6 CPP11=1
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=javascript ENGINE=node VER=8 CPP11=1
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=javascript ENGINE=node VER=10 CPP11=1
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=javascript ENGINE=jsc
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=javascript ENGINE=v8
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=lua
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=lua VER=5.3
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=mzscheme
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ocaml
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=octave SWIGJOBS=-j2
sudo: required
dist: xenial # Octave v4.0.0
- compiler: gcc
os: linux
env: SWIGLANG=octave SWIGJOBS=-j2 CPP11=1
sudo: required
dist: bionic # Octave v4.2.2
- compiler: gcc
os: linux
env: SWIGLANG=perl5
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=php VER=7.0
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=php VER=7.1
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=php VER=7.2
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=php VER=7.3
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python # 2.7
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python PY3=3 VER=3.2
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python PY3=3 VER=3.3
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python PY3=3 VER=3.4
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python PY3=3 VER=3.5
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python PY3=3 VER=3.6
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python PY3=3 VER=3.7
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python PY3=3 VER=3.8
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES=-builtin
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES="-builtin -O"
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=python SWIG_FEATURES=-builtin GCC=6 CPP11=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=python SWIG_FEATURES=-builtin GCC=6 CPP11=1 PY3=3 VER=3.8
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.4
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.5
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.7
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.8
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES="-builtin -O" PY3=3 VER=3.8
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES=-builtin PY3=3 VER=3.8 SWIGOPTPY3=
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES=-O
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=python SWIG_FEATURES=-O PY3=3 VER=3.8
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=r
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=1.9
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=2.0
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=2.1
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=2.2
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=2.3
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=2.4
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=2.5
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=2.6
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ruby VER=2.7
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=scilab
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=tcl
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=csharp CPP11=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=go VER=1.6 CPP11=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=java CPP11=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=python CPP11=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=r CPP11=1 # Note: making 'R CMD SHLIB' use a different compiler is non-trivial
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=ruby CPP11=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=tcl CPP11=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=csharp GCC=6 CPP14=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=go VER=1.6 GCC=6 CPP14=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=java GCC=6 CPP14=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=python GCC=6 CPP14=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=ruby GCC=6 CPP14=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=tcl GCC=6 CPP14=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=java GCC=7 CPP14=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=python GCC=7 CPP14=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=csharp GCC=8 CPP17=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=java GCC=8 CPP17=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=python GCC=8 CPP17=1 PY3=3 VER=3.8
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=csharp GCC=9 CPP17=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=java GCC=9 CPP17=1
sudo: required
dist: xenial
- os: linux
env: SWIGLANG=python GCC=9 CPP17=1 PY3=3 VER=3.8
sudo: required
dist: xenial
- os: linux
arch: s390x
env: SWIGLANG=ruby CPP11=1
sudo: required
dist: xenial
- compiler: gcc
os: osx
env: SWIGLANG=
- compiler: clang
os: osx
env: SWIGLANG=
- compiler: clang
os: osx
env: SWIGLANG=csharp
- compiler: clang
os: osx
env: SWIGLANG=go
- compiler: clang
os: osx
env: SWIGLANG=guile CSTD=c11
- compiler: clang
os: osx
env: SWIGLANG=java
- compiler: clang
os: osx
env: SWIGLANG=lua
- compiler: clang
os: osx
env: SWIGLANG=octave SWIGJOBS=-j2 CPP11=1
- compiler: clang
os: osx
env: SWIGLANG=perl5
- compiler: clang
os: osx
env: SWIGLANG=python
- compiler: clang
os: osx
env: SWIGLANG=python PY3=3
- compiler: clang
os: osx
env: SWIGLANG=ruby
- compiler: clang
os: osx
env: SWIGLANG=tcl
- compiler: clang
os: osx
env: SWIGLANG=java CPP17=1
osx_image: xcode10.2
- compiler: clang
os: osx
env: SWIGLANG=python PY3=3 CPP17=1
osx_image: xcode10.2
allow_failures:
# Newer version of D not yet working/supported
- compiler: gcc
os: linux
env: SWIGLANG=d VER=2.086.1
sudo: required
dist: xenial
# seg fault in director_basic testcase
- compiler: gcc
os: linux
env: SWIGLANG=php VER=7.2
sudo: required
dist: xenial
# Experimental languages
- compiler: gcc
os: linux
env: SWIGLANG=mzscheme
sudo: required
dist: xenial
- compiler: gcc
os: linux
env: SWIGLANG=ocaml
sudo: required
dist: xenial
before_install:
- date -u
- uname -a
- if test "$TRAVIS_OS_NAME" = "linux"; then lscpu; grep "model name" /proc/cpuinfo || echo 'Unknown CPU model'; grep "MemTotal" /proc/meminfo || echo 'Unknown system memory amount'; fi
- if test "$TRAVIS_OS_NAME" = "osx"; then sysctl -a | grep brand_string; fi
# Travis overrides CC environment with compiler predefined values
- if test -n "$GCC"; then export CC="gcc-$GCC" && export CXX="g++-$GCC"; fi
install:
- if test "$TRAVIS_OS_NAME" = "linux"; then source Tools/travis-linux-install.sh; fi
- if test "$TRAVIS_OS_NAME" = "osx"; then source Tools/travis-osx-install.sh; fi
- ls -la $(which $CC) $(which $CXX) && $CC --version && $CXX --version
script:
- echo 'Configuring...' && echo -en 'travis_fold:start:script.1\\r'
- if test -n "$CPP11"; then CONFIGOPTS+=(--enable-cpp11-testing --without-maximum-compile-warnings "CXXFLAGS=-std=c++11 -Wall -Wextra" "CFLAGS=-std=c11 -Wall -Wextra") && export CSTD=c11 && export CPPSTD=c++11; fi
- if test -n "$CPP14"; then CONFIGOPTS+=(--enable-cpp11-testing --without-maximum-compile-warnings "CXXFLAGS=-std=c++14 -Wall -Wextra" "CFLAGS=-std=c11 -Wall -Wextra") && export CSTD=c11 && export CPPSTD=c++14; fi
- if test -n "$CPP17"; then CONFIGOPTS+=(--enable-cpp11-testing --without-maximum-compile-warnings "CXXFLAGS=-std=c++17 -Wall -Wextra" "CFLAGS=-std=c17 -Wall -Wextra") && export CSTD=c17 && export CPPSTD=c++17; fi
- if test -n "$SWIGLANG"; then CONFIGOPTS+=(--without-alllang --with-$WITHLANG); fi
- echo "${CONFIGOPTS[@]}"
- ./autogen.sh && mkdir -p build/build && cd build/build && ../../configure "${CONFIGOPTS[@]}"
- echo -en 'travis_fold:end:script.1\\r'
- make -s $SWIGJOBS
- ./swig -version && ./swig -pcreversion
- if test -z "$SWIGLANG"; then make -s $SWIGJOBS check-ccache; fi
- if test -z "$SWIGLANG"; then make -s $SWIGJOBS check-errors-test-suite; fi
- echo 'Installing...' && echo -en 'travis_fold:start:script.2\\r'
- if test -z "$SWIGLANG"; then sudo make -s install && swig -version && ccache-swig -V; fi
- echo -en 'travis_fold:end:script.2\\r'
# Stricter compile flags for examples. Various headers and SWIG generated code prevents full use of -pedantic.
- if test -n "$SWIGLANG"; then cflags=$($TRAVIS_BUILD_DIR/Tools/testflags.py --language $SWIGLANG --cflags --std=$CSTD --compiler=$CC) && echo $cflags; fi
- if test -n "$SWIGLANG"; then cxxflags=$($TRAVIS_BUILD_DIR/Tools/testflags.py --language $SWIGLANG --cxxflags --std=$CPPSTD --compiler=$CC) && echo $cxxflags; fi
- if test -n "$SWIGLANG"; then make -s check-$SWIGLANG-version; fi
- if test -n "$SWIGLANG"; then make check-$SWIGLANG-enabled; fi
- if test -n "$SWIGLANG"; then make $SWIGJOBS check-$SWIGLANG-examples CFLAGS="$cflags" CXXFLAGS="$cxxflags"; fi
- if test -n "$SWIGLANG"; then make $SWIGJOBS check-$SWIGLANG-test-suite CFLAGS="$cflags" CXXFLAGS="$cxxflags"; fi
- echo 'Cleaning...' && echo -en 'travis_fold:start:script.3\\r'
- make check-maintainer-clean && ../../configure $CONFIGOPTS
- echo -en 'travis_fold:end:script.3\\r'

38
ANNOUNCE Normal file
View File

@ -0,0 +1,38 @@
*** ANNOUNCE: SWIG 4.0.2 (8 Jun 2020) ***
http://www.swig.org
We're pleased to announce SWIG-4.0.2, the latest SWIG release.
What is SWIG?
=============
SWIG is a software development tool that reads C/C++ header files and
generates the wrapper code needed to make C and C++ code accessible
from other programming languages including Perl, Python, Tcl, Ruby,
PHP, C#, Go, Java, Javascript, Lua, Scheme (Guile, MzScheme), D,
Ocaml, Octave, R, Scilab. SWIG can also export its parse tree in
the form of XML. Major applications of SWIG include generation of
scripting language extension modules, rapid prototyping, testing,
and user interface development for large C/C++ systems.
Release Notes
=============
Detailed release notes are available with the release and are also
published on the SWIG web site at http://swig.org/release.html.
Availability
============
The release is available for download on Sourceforge at
http://prdownloads.sourceforge.net/swig/swig-4.0.2.tar.gz
A Windows version is also available at
http://prdownloads.sourceforge.net/swig/swigwin-4.0.2.zip
Please report problems with this release to the swig-devel mailing list,
details at http://www.swig.org/mail.html.
--- The SWIG Developers

339
CCache/COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

84
CCache/Makefile.in Normal file
View File

@ -0,0 +1,84 @@
datarootdir = @datarootdir@
srcdir=@srcdir@
VPATH=@srcdir@
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
mandir=@mandir@
INSTALLCMD=@INSTALL@
PACKAGE_NAME=@PACKAGE_NAME@
PROGRAM_NAME=@PROGRAM_NAME@
# Soft link test can be skipped on systems that don't support soft linking
NOSOFTLINKSTEST=
CC=@CC@
CFLAGS=@CFLAGS@ -I.
SWIG=swig
SWIG_LIB=../$(srcdir)/../Lib
EXEEXT=@EXEEXT@
LIBS= @LIBS@
OBJS= ccache.o mdfour.o hash.o execute.o util.o args.o stats.o \
cleanup.o snprintf.o unify.o
HEADERS = ccache.h mdfour.h config.h config_win32.h
all: $(PACKAGE_NAME)$(EXEEXT)
# Regenerate Makefile if Makefile.in or config.status have changed.
Makefile: $(srcdir)/Makefile.in ./config.status
$(SHELL) ./config.status
# Note that HTML documentation is actually generated and used from the main SWIG documentation Makefile
docs: $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html
$(PACKAGE_NAME)$(EXEEXT): $(OBJS) $(HEADERS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
$(srcdir)/$(PACKAGE_NAME).1: $(srcdir)/ccache.yo
-yodl2man -o $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/ccache.yo
$(srcdir)/web/$(PACKAGE_NAME)-man.html: $(srcdir)/ccache.yo
yodl2html -o $(srcdir)/web/$(PACKAGE_NAME)-man.html $(srcdir)/ccache.yo
install: $(PACKAGE_NAME)$(EXEEXT)
@echo "Installing $(PACKAGE_NAME)"
@echo "Installing $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT)"
${INSTALLCMD} -d $(DESTDIR)${bindir}
${INSTALLCMD} -m 755 $(PACKAGE_NAME)$(EXEEXT) $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT)
install-docs: $(srcdir)/$(PACKAGE_NAME).1
@echo "Installing $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1"
${INSTALLCMD} -d $(DESTDIR)${mandir}/man1
${INSTALLCMD} -m 644 $(srcdir)/$(PACKAGE_NAME).1 $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1
uninstall: $(PACKAGE_NAME)$(EXEEXT)
rm -f $(DESTDIR)${bindir}/$(PROGRAM_NAME)$(EXEEXT)
uninstall-docs: $(srcdir)/$(PACKAGE_NAME).1
rm -f $(DESTDIR)${mandir}/man1/$(PROGRAM_NAME).1
clean: clean-docs
/bin/rm -f $(OBJS) *~ $(PACKAGE_NAME)$(EXEEXT)
clean-docs:
rm -f $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html
test: test.sh
SWIG_LIB='$(SWIG_LIB)' PATH=../..:$$PATH SWIG='$(SWIG)' CC='$(CC)' NOSOFTLINKSTEST='$(NOSOFTLINKSTEST)' CCACHE='../$(PACKAGE_NAME)' CCACHE_PROG=$(PROGRAM_NAME) $(srcdir)/test.sh
check: test
distclean: clean
/bin/rm -f Makefile config.h config.sub config.log build-stamp config.status ccache_swig_config.h config_win32.h
/bin/rm -rf autom4te.cache
maintainer-clean: distclean
/bin/rm -f $(srcdir)/$(PACKAGE_NAME).1 $(srcdir)/web/$(PACKAGE_NAME)-man.html
# FIXME: To fix this, test.sh needs to be able to take ccache from the
# installed prefix, not from the source dir.
installcheck:
@echo "WARNING! This is not really \"installcheck\" yet."
$(MAKE) check

31
CCache/README Normal file
View File

@ -0,0 +1,31 @@
This is a re-implementation of "compilercache" in C
The original compilercache scripts were by Erik Thiele
(erikyyy@erikyyy.de) and I would like to thank him for an excellent
piece of work. See http://www.erikyyy.de/compilercache/ for the
original shell scripts.
I wrote ccache because I wanted to get a bit more speed out of a
compiler cache and I wanted to remove some of the limitations of the
shell-script version.
Please see the manual page and documentation at
http://ccache.samba.org/
INSTALLATION
------------
Please run:
./configure
make
make install
then read the ccache manual page
-----------
Andrew Tridgell
http://samba.org/~tridge/
bugs@ccache.samba.org

8
CCache/README.swig Normal file
View File

@ -0,0 +1,8 @@
This directory contains a version of ccache. The initial version was based on ccache-2.4 plus
debian patches 01-02, 04-14, see the debian/patches subdirectory. The ccache-win32-2.4 modifications
to ccache-2.4 have also been merged in.
Changes have been made to support cacheing the output from SWIG. The ability to cache c/c++ compiler
output has been retained.
Additional features added are the CCACHE_VERBOSE and CCACHE_SWIG environment variables, see docs.

91
CCache/args.c Normal file
View File

@ -0,0 +1,91 @@
/*
convenient routines for argument list handling
Copyright (C) Andrew Tridgell 2002
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "ccache.h"
ARGS *args_init(int init_argc, char **init_args)
{
ARGS *args;
int i;
args = (ARGS *)x_malloc(sizeof(ARGS));
args->argc = 0;
args->argv = (char **)x_malloc(sizeof(char *));
args->argv[0] = NULL;
for (i=0;i<init_argc;i++) {
args_add(args, init_args[i]);
}
return args;
}
void args_add(ARGS *args, const char *s)
{
args->argv = (char**)x_realloc(args->argv, (args->argc + 2) * sizeof(char *));
args->argv[args->argc] = x_strdup(s);
args->argc++;
args->argv[args->argc] = NULL;
}
/* pop the last element off the args list */
void args_pop(ARGS *args, int n)
{
while (n--) {
args->argc--;
free(args->argv[args->argc]);
args->argv[args->argc] = NULL;
}
}
/* remove the first element of the argument list */
void args_remove_first(ARGS *args)
{
free(args->argv[0]);
memmove(&args->argv[0],
&args->argv[1],
args->argc * sizeof(args->argv[0]));
args->argc--;
}
/* add an argument into the front of the argument list */
void args_add_prefix(ARGS *args, const char *s)
{
args->argv = (char**)x_realloc(args->argv, (args->argc + 2) * sizeof(char *));
memmove(&args->argv[1], &args->argv[0],
(args->argc+1) * sizeof(args->argv[0]));
args->argv[0] = x_strdup(s);
args->argc++;
}
/* strip any arguments beginning with the specified prefix */
void args_strip(ARGS *args, const char *prefix)
{
int i;
for (i=0; i<args->argc; ) {
if (strncmp(args->argv[i], prefix, strlen(prefix)) == 0) {
free(args->argv[i]);
memmove(&args->argv[i],
&args->argv[i+1],
args->argc * sizeof(args->argv[i]));
args->argc--;
} else {
i++;
}
}
}

1400
CCache/ccache.c Normal file

File diff suppressed because it is too large Load Diff

209
CCache/ccache.h Normal file
View File

@ -0,0 +1,209 @@
#include "ccache_swig_config.h"
#define CCACHE_VERSION SWIG_VERSION
#ifndef _WIN32
#include "config.h"
#else
#include <sys/locking.h>
#include "config_win32.h"
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifndef _WIN32
#include <sys/wait.h>
#include <sys/mman.h>
#else
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
#include <shlobj.h>
#endif
#include <sys/file.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <utime.h>
#include <stdarg.h>
#include <dirent.h>
#include <limits.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef ENABLE_ZLIB
#include <zlib.h>
#endif
#define STATUS_NOTFOUND 3
#define STATUS_FATAL 4
#define STATUS_NOCACHE 5
#define MYNAME PROGRAM_NAME
#define LIMIT_MULTIPLE 0.8
/* default maximum cache size */
#ifndef DEFAULT_MAXSIZE
#define DEFAULT_MAXSIZE (1000*1000)
#endif
/* file copy mode */
#ifdef ENABLE_ZLIB
#define COPY_UNCOMPRESSED 0
#define COPY_FROM_CACHE 1
#define COPY_TO_CACHE 2
#endif
enum stats {
STATS_NONE=0,
STATS_STDOUT,
STATS_STATUS,
STATS_ERROR,
STATS_TOCACHE,
STATS_PREPROCESSOR,
STATS_COMPILER,
STATS_MISSING,
STATS_CACHED,
STATS_ARGS,
STATS_LINK,
STATS_NUMFILES,
STATS_TOTALSIZE,
STATS_MAXFILES,
STATS_MAXSIZE,
STATS_NOTC,
STATS_DEVICE,
STATS_NOINPUT,
STATS_ENVIRONMMENT,
STATS_MULTIPLE,
STATS_CONFTEST,
STATS_UNSUPPORTED,
STATS_OUTSTDOUT,
STATS_END
};
typedef unsigned uint32;
#include "mdfour.h"
void hash_start(void);
void hash_string(const char *s);
void hash_int(int x);
void hash_file(const char *fname);
char *hash_result(void);
void hash_buffer(const char *s, int len);
void cc_log(const char *format, ...);
void fatal(const char *msg);
void copy_fd(int fd_in, int fd_out);
int safe_rename(const char* oldpath, const char* newpath);
int move_file(const char *src, const char *dest);
int test_if_compressed(const char *filename);
int commit_to_cache(const char *src, const char *dest, int hardlink);
int retrieve_from_cache(const char *src, const char *dest, int hardlink);
int create_dir(const char *dir);
int create_cachedirtag(const char *dir);
void x_asprintf(char **ptr, const char *format, ...);
char *x_strdup(const char *s);
void *x_realloc(void *ptr, size_t size);
void *x_malloc(size_t size);
void traverse(const char *dir, void (*fn)(const char *, struct stat *));
char *str_basename(const char *s);
char *dirname(char *s);
int lock_fd(int fd);
size_t file_size(struct stat *st);
int safe_open(const char *fname);
char *x_realpath(const char *path);
char *gnu_getcwd(void);
int create_empty_file(const char *fname);
const char *get_home_directory(void);
int x_utimes(const char *filename);
#ifdef _WIN32
void perror_win32(LPTSTR pszFunction);
#endif
void stats_update(enum stats stat);
void stats_zero(void);
void stats_summary(void);
void stats_tocache(size_t size, size_t numfiles);
void stats_read(const char *stats_file, unsigned counters[STATS_END]);
int stats_set_limits(long maxfiles, long maxsize);
size_t value_units(const char *s);
void display_size(unsigned v);
void stats_set_sizes(const char *dir, size_t num_files, size_t total_size);
int unify_hash(const char *fname);
#ifndef HAVE_VASPRINTF
int vasprintf(char **, const char *, va_list );
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format, ...);
#endif
#ifndef HAVE_SNPRINTF
int snprintf(char *,size_t ,const char *, ...);
#endif
void cleanup_dir(const char *dir, size_t maxfiles, size_t maxsize, size_t minfiles);
void cleanup_all(const char *dir);
void wipe_all(const char *dir);
#ifdef _WIN32
char *argvtos(char **argv);
#endif
int execute(char **argv,
const char *path_stdout,
const char *path_stderr);
char *find_executable(const char *name, const char *exclude_name);
void display_execute_args(char **argv);
typedef struct {
char **argv;
int argc;
} ARGS;
ARGS *args_init(int , char **);
void args_add(ARGS *args, const char *s);
void args_add_prefix(ARGS *args, const char *s);
void args_pop(ARGS *args, int n);
void args_strip(ARGS *args, const char *prefix);
void args_remove_first(ARGS *args);
extern int ccache_verbose;
#if HAVE_COMPAR_FN_T
#define COMPAR_FN_T __compar_fn_t
#else
typedef int (*COMPAR_FN_T)(const void *, const void *);
#endif
/* work with silly DOS binary open */
#ifndef O_BINARY
#define O_BINARY 0
#endif
/* mkstemp() on some versions of cygwin don't handle binary files, so
override */
/* Seems okay in Cygwin 1.7.0
#ifdef __CYGWIN__
#undef HAVE_MKSTEMP
#endif
*/

422
CCache/ccache.yo Normal file
View File

@ -0,0 +1,422 @@
whenman(
COMMENT(html output not great if included when using html2doc)
manpage(ccache-swig)(1)()()()
)
whenhtml(htmlcommand(
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>ccache-swig(1) manpage</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body bgcolor="#ffffff">
<H1><a name="CCache"></a>Using SWIG with ccache - ccache-swig(1) manpage</H1>
<!-- INDEX -->
<div class="sectiontoc">
<!-- INDEX -->
))
manpagename(ccache-swig)(a fast compiler cache)
whenhtml(htmlcommand(
ccache-swig - a fast compiler cache
))
manpagesynopsis()
ccache-swig [OPTION]
ccache-swig <compiler> [COMPILER OPTIONS]
<compiler> [COMPILER OPTIONS]
manpagedescription()
ccache-swig is a compiler cache. It speeds up re-compilation of C/C++/SWIG code
by caching previous compiles and detecting when the same compile is
being done again. ccache-swig is ccache plus support for SWIG. ccache
and ccache-swig are used interchangeably in this document.
manpagesection(OPTIONS SUMMARY)
Here is a summary of the options to ccache-swig.
verb(
-s show statistics summary
-z zero statistics
-c run a cache cleanup
-C clear the cache completely
-F <n> set maximum files in cache
-M <n> set maximum size of cache (use G, M or K)
-h this help page
-V print version number
)
manpageoptions()
These options only apply when you invoke ccache as "ccache-swig". When
invoked as a compiler none of these options apply. In that case your
normal compiler options apply and you should refer to your compilers
documentation.
startdit()
dit(bf(-h)) Print a options summary page
dit(bf(-s)) Print the current statistics summary for the cache. The
statistics are stored spread across the subdirectories of the
cache. Using "ccache-swig -s" adds up the statistics across all
subdirectories and prints the totals.
dit(bf(-z)) Zero the cache statistics.
dit(bf(-V)) Print the ccache version number
dit(bf(-c)) Clean the cache and re-calculate the cache file count and
size totals. Normally the -c option should not be necessary as ccache
keeps the cache below the specified limits at runtime and keeps
statistics up to date on each compile. This option is mostly useful
if you manually modify the cache contents or believe that the cache
size statistics may be inaccurate.
dit(bf(-C)) Clear the entire cache, removing all cached files.
dit(bf(-F <maxfiles>)) This sets the maximum number of files allowed in
the cache. The value is stored inside the cache directory and applies
to all future compiles. Due to the way the value is stored the actual
value used is always rounded down to the nearest multiple of 16.
dit(bf(-M <maxsize>)) This sets the maximum cache size. You can specify
a value in gigabytes, megabytes or kilobytes by appending a G, M or K
to the value. The default is gigabytes. The actual value stored is
rounded down to the nearest multiple of 16 kilobytes.
enddit()
manpagesection(INSTALLATION)
There are two ways to use ccache. You can either prefix your compile
commands with "ccache-swig" or you can create a symbolic link between
ccache-swig and the names of your compilers. The first method is most
convenient if you just want to try out ccache or wish to use it for
some specific projects. The second method is most useful for when you
wish to use ccache for all your compiles.
To install for usage by the first method just copy ccache-swig to somewhere
in your path.
To install for the second method do something like this:
verb(
cp ccache-swig /usr/local/bin/
ln -s /usr/local/bin/ccache-swig /usr/local/bin/gcc
ln -s /usr/local/bin/ccache-swig /usr/local/bin/g++
ln -s /usr/local/bin/ccache-swig /usr/local/bin/cc
ln -s /usr/local/bin/ccache-swig /usr/local/bin/swig
)
This will work as long as /usr/local/bin comes before the path to gcc
(which is usually in /usr/bin). After installing you may wish to run
"which gcc" to make sure that the correct link is being used.
Note! Do not use a hard link, use a symbolic link. A hardlink will
cause "interesting" problems.
manpagesection(EXTRA OPTIONS)
When run as a compiler front end ccache usually just takes the same
command line options as the compiler you are using. The only exception
to this is the option '--ccache-skip'. That option can be used to tell
ccache that the next option is definitely not a input filename, and
should be passed along to the compiler as-is.
The reason this can be important is that ccache does need to parse the
command line and determine what is an input filename and what is a
compiler option, as it needs the input filename to determine the name
of the resulting object file (among other things). The heuristic
ccache uses in this parse is that any string on the command line that
exists as a file is treated as an input file name (usually a C
file). By using --ccache-skip you can force an option to not be
treated as an input file name and instead be passed along to the
compiler as a command line option.
manpagesection(ENVIRONMENT VARIABLES)
ccache uses a number of environment variables to control operation. In
most cases you won't need any of these as the defaults will be fine.
startdit()
dit(bf(CCACHE_DIR)) the CCACHE_DIR environment variable specifies
where ccache will keep its cached compiler output. The default is
"$HOME/.ccache".
dit(bf(CCACHE_TEMPDIR)) the CCACHE_TEMPDIR environment variable specifies
where ccache will put temporary files. The default is the same as
CCACHE_DIR. Note that the CCACHE_TEMPDIR path must be on the same
filesystem as the CCACHE_DIR path, so that renames of files between
the two directories can work.
dit(bf(CCACHE_LOGFILE)) If you set the CCACHE_LOGFILE environment
variable then ccache will write some log information on cache hits
and misses in that file. This is useful for tracking down problems.
dit(bf(CCACHE_VERBOSE)) If you set the CCACHE_VERBOSE environment
variable then ccache will display on stdout all the compiler invocations
that it makes. This can useful for debugging unexpected problems.
dit(bf(CCACHE_PATH)) You can optionally set CCACHE_PATH to a colon
separated path where ccache will look for the real compilers. If you
don't do this then ccache will look for the first executable matching
the compiler name in the normal PATH that isn't a symbolic link to
ccache itself.
dit(bf(CCACHE_CC)) You can optionally set CCACHE_CC to force the name
of the compiler to use. If you don't do this then ccache works it out
from the command line.
dit(bf(CCACHE_PREFIX)) This option adds a prefix to the command line
that ccache runs when invoking the compiler. Also see the section
below on using ccache with distcc.
dit(bf(CCACHE_DISABLE)) If you set the environment variable
CCACHE_DISABLE then ccache will just call the real compiler,
bypassing the cache completely.
dit(bf(CCACHE_READONLY)) the CCACHE_READONLY environment variable
tells ccache to attempt to use existing cached object files, but not
to try to add anything new to the cache. If you are using this because
your CCACHE_DIR is read-only, then you may find that you also need to
set CCACHE_TEMPDIR as otherwise ccache will fail to create the
temporary files.
dit(bf(CCACHE_CPP2)) If you set the environment variable CCACHE_CPP2
then ccache will not use the optimisation of avoiding the 2nd call to
the pre-processor by compiling the pre-processed output that was used
for finding the hash in the case of a cache miss. This is primarily a
debugging option, although it is possible that some unusual compilers
will have problems with the intermediate filename extensions used in
this optimisation, in which case this option could allow ccache to be
used.
dit(bf(CCACHE_NOCOMPRESS)) If you set the environment variable
CCACHE_NOCOMPRESS then there is no compression used on files that go
into the cache. However, this setting has no effect on how files are
retrieved from the cache, compressed results will still be usable.
dit(bf(CCACHE_NOSTATS)) If you set the environment variable
CCACHE_NOSTATS then ccache will not update the statistics files on
each compile.
dit(bf(CCACHE_NLEVELS)) The environment variable CCACHE_NLEVELS allows
you to choose the number of levels of hash in the cache directory. The
default is 2. The minimum is 1 and the maximum is 8.
dit(bf(CCACHE_HARDLINK)) If you set the environment variable
CCACHE_HARDLINK then ccache will attempt to use hard links from the
cache directory when creating the compiler output rather than using a
file copy. Using hard links is faster, but can confuse programs like
'make' that rely on modification times. Hard links are never made for
compressed cache files.
dit(bf(CCACHE_RECACHE)) This forces ccache to not use any cached
results, even if it finds them. New results are still cached, but
existing cache entries are ignored.
dit(bf(CCACHE_UMASK)) This sets the umask for ccache and all child
processes (such as the compiler). This is mostly useful when you wish
to share your cache with other users. Note that this also affects the
file permissions set on the object files created from your
compilations.
dit(bf(CCACHE_HASHDIR)) This tells ccache to hash the current working
directory when calculating the hash that is used to distinguish two
compiles. This prevents a problem with the storage of the current
working directory in the debug info of a object file, which can lead
ccache to give a cached object file that has the working directory in
the debug info set incorrectly. This option is off by default as the
incorrect setting of this debug info rarely causes problems. If you
strike problems with gdb not using the correct directory then enable
this option.
dit(bf(CCACHE_UNIFY)) If you set the environment variable CCACHE_UNIFY
then ccache will use the C/C++ unifier when hashing the pre-processor
output if -g is not used in the compile. The unifier is slower than a
normal hash, so setting this environment variable loses a little bit
of speed, but it means that ccache can take advantage of not
recompiling when the changes to the source code consist of
reformatting only. Note that using CCACHE_UNIFY changes the hash, so
cached compiles with CCACHE_UNIFY set cannot be used when
CCACHE_UNIFY is not set and vice versa. The reason the unifier is off
by default is that it can give incorrect line number information in
compiler warning messages.
dit(bf(CCACHE_EXTENSION)) Normally ccache tries to automatically
determine the extension to use for intermediate C pre-processor files
based on the type of file being compiled. Unfortunately this sometimes
doesn't work, for example when using the aCC compiler on HP-UX. On
systems like this you can use the CCACHE_EXTENSION option to override
the default. On HP-UX set this environment variable to "i" if you use
the aCC compiler.
dit(bf(CCACHE_STRIPC)) If you set the environment variable
CCACHE_STRIPC then ccache will strip the -c option when invoking
the preprocessor. This option is primarily for the Sun Workshop
C++ compiler as without this option an unwarranted warning is displayed:
CC: Warning: "-E" redefines product from "object" to "source (stdout)"
when -E and -c is used together.
dit(bf(CCACHE_SWIG)) When using SWIG as the compiler and it does not
have 'swig' in the executable name, then the CCACHE_SWIG environment
variable needs to be set in order for ccache to work correctly with
SWIG. The use of CCACHE_CPP2 is also recommended for SWIG due to some
preprocessor quirks, however, use of CCACHE_CPP2 can often be skipped
-- check your generated code with and without this option set. Known
problems are using preprocessor directives within %inline blocks and
the use of '#pragma SWIG'.
enddit()
manpagesection(CACHE SIZE MANAGEMENT)
By default ccache has a one gigabyte limit on the cache size and no
maximum number of files. You can set a different limit using the
"ccache -M" and "ccache -F" options, which set the size and number of
files limits.
When these limits are reached ccache will reduce the cache to 20%
below the numbers you specified in order to avoid doing the cache
clean operation too often.
manpagesection(CACHE COMPRESSION)
By default on most platforms ccache will compress all files it puts
into the cache
using the zlib compression. While this involves a negligible
performance slowdown, it significantly increases the number of files
that fit in the cache. You can turn off compression setting the
CCACHE_NOCOMPRESS environment variable.
manpagesection(HOW IT WORKS)
The basic idea is to detect when you are compiling exactly the same
code a 2nd time and use the previously compiled output. You detect
that it is the same code by forming a hash of:
itemization(
it() the pre-processor output from running the compiler with -E
it() the command line options
it() the real compilers size and modification time
it() any stderr output generated by the compiler
)
These are hashed using md4 (a strong hash) and a cache file is formed
based on that hash result. When the same compilation is done a second
time ccache is able to supply the correct compiler output (including
all warnings etc) from the cache.
ccache has been carefully written to always produce exactly the same
compiler output that you would get without the cache. If you ever
discover a case where ccache changes the output of your compiler then
please let me know.
manpagesection(USING CCACHE WITH DISTCC)
distcc is a very useful program for distributing compilation across a
range of compiler servers. It is often useful to combine distcc with
ccache, so that compiles that are done are sped up by distcc, but that
ccache avoids the compile completely where possible.
To use distcc with ccache I recommend using the CCACHE_PREFIX
option. You just need to set the environment variable CCACHE_PREFIX to
'distcc' and ccache will prefix the command line used with the
compiler with the command 'distcc'.
manpagesection(SHARING A CACHE)
A group of developers can increase the cache hit rate by sharing a
cache directory. The hard links however cause unwanted side effects,
as all links to a cached file share the file's modification timestamp.
This results in false dependencies to be triggered by timestamp-based
build systems whenever another user links to an existing
file. Typically, users will see that their libraries and binaries are
relinked without reason. To share a cache without side effects, the
following conditions need to be met:
itemization(
it() Use the same bf(CCACHE_DIR) environment variable setting
it() Unset the bf(CCACHE_HARDLINK) environment variable
it() Make sure everyone sets the CCACHE_UMASK environment variable
to 002, this ensures that cached files are accessible to everyone in
the group.
it() Make sure that all users have write permission in the entire
cache directory (and that you trust all users of the shared cache).
it() Make sure that the setgid bit is set on all directories in the
cache. This tells the filesystem to inherit group ownership for new
directories. The command "chmod g+s `find $CCACHE_DIR -type d`" might
be useful for this.
it() Set bf(CCACHE_NOCOMPRESS) for all users, if there are users with
versions of ccache that do not support compression.
)
manpagesection(HISTORY)
ccache was inspired by the compilercache shell script script written
by Erik Thiele and I would like to thank him for an excellent piece of
work. See
url(http://www.erikyyy.de/compilercache/)(http://www.erikyyy.de/compilercache/)
for the Erik's scripts.
ccache-swig is a port of the original ccache with support added for use
with SWIG.
I wrote ccache because I wanted to get a bit more speed out of a
compiler cache and I wanted to remove some of the limitations of the
shell-script version.
manpagesection(DIFFERENCES FROM COMPILERCACHE)
The biggest differences between Erik's compilercache script and ccache
are:
itemization(
it() ccache is written in C, which makes it a bit faster (calling out to
external programs is mostly what slowed down the scripts).
it() ccache can automatically find the real compiler
it() ccache keeps statistics on hits/misses
it() ccache can do automatic cache management
it() ccache can cache compiler output that includes warnings. In many
cases this gives ccache a much higher cache hit rate.
it() ccache can handle a much wider ranger of compiler options
it() ccache avoids a double call to cpp on a cache miss
)
manpagesection(CREDITS)
Thanks to the following people for their contributions to ccache
itemization(
it() Erik Thiele for the original compilercache script
it() Luciano Rocha for the idea of compiling the pre-processor output
to avoid a 2nd cpp pass
it() Paul Russell for many suggestions and the debian packaging
)
manpageauthor()
ccache was written by Andrew Tridgell
url(http://samba.org/~tridge/)(http://samba.org/~tridge/).
ccache was adapted to create ccache-swig for use with SWIG by William Fulton.
If you wish to report a problem or make a suggestion then please email
the SWIG developers on the swig-devel mailing list, see
url(http://www.swig.org/mail.html)(http://www.swig.org/mail.html)
ccache is released under the GNU General Public License version 2 or
later. Please see the file COPYING for license details.
whenhtml(htmlcommand(
</body>
</html>
))

View File

@ -0,0 +1 @@
#define SWIG_VERSION "@PACKAGE_VERSION@"

213
CCache/cleanup.c Normal file
View File

@ -0,0 +1,213 @@
/*
Copyright (C) Andrew Tridgell 2002
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
functions to cleanup the cache directory when it gets too large
*/
#include "ccache.h"
static struct files {
char *fname;
time_t mtime;
size_t size;
} **files;
static unsigned allocated;
static unsigned num_files;
static size_t total_size;
static size_t total_files;
static size_t size_threshold;
static size_t files_threshold;
/* file comparison function to try to delete the oldest files first */
static int files_compare(struct files **f1, struct files **f2)
{
if ((*f2)->mtime == (*f1)->mtime) {
return strcmp((*f2)->fname, (*f1)->fname);
}
if ((*f2)->mtime > (*f1)->mtime) {
return -1;
}
return 1;
}
/* this builds the list of files in the cache */
static void traverse_fn(const char *fname, struct stat *st)
{
char *p;
if (!S_ISREG(st->st_mode)) return;
p = str_basename(fname);
if (strcmp(p, "stats") == 0) {
free(p);
return;
}
free(p);
if (num_files == allocated) {
allocated = 10000 + num_files*2;
files = (struct files **)x_realloc(files,
sizeof(struct files *)*allocated);
}
files[num_files] = (struct files *)x_malloc(sizeof(struct files));
files[num_files]->fname = x_strdup(fname);
files[num_files]->mtime = st->st_mtime;
files[num_files]->size = file_size(st) / 1024;
total_size += files[num_files]->size;
num_files++;
}
/* sort the files we've found and delete the oldest ones until we are
below the thresholds */
static void sort_and_clean(size_t minfiles)
{
unsigned i;
size_t adjusted_minfiles = minfiles;
if (num_files > 1) {
/* sort in ascending data order */
qsort(files, num_files, sizeof(struct files *),
(COMPAR_FN_T)files_compare);
}
/* ensure newly cached files (minfiles) are kept - instead of matching
the filenames of those newly cached, a faster and simpler approach
assumes these are the most recent in the cache and if any other
cached files have an identical time stamp, they will also be kept -
this approach would not be needed if the cleanup was done at exit. */
if (minfiles != 0 && minfiles < num_files) {
unsigned minfiles_index = num_files - minfiles;
time_t minfiles_time = files[minfiles_index]->mtime;
for (i=1; i<=minfiles_index; i++) {
if (files[minfiles_index-i]->mtime == minfiles_time)
adjusted_minfiles++;
else
break;
}
}
/* delete enough files to bring us below the threshold */
for (i=0;i<num_files; i++) {
if ((size_threshold==0 || total_size < size_threshold) &&
(files_threshold==0 || (num_files-i) < files_threshold)) break;
if (adjusted_minfiles != 0 && num_files-i <= adjusted_minfiles)
break;
if (unlink(files[i]->fname) != 0 && errno != ENOENT) {
fprintf(stderr, "unlink %s - %s\n",
files[i]->fname, strerror(errno));
continue;
}
total_size -= files[i]->size;
}
total_files = num_files - i;
}
/* cleanup in one cache subdir */
void cleanup_dir(const char *dir, size_t maxfiles, size_t maxsize, size_t minfiles)
{
unsigned i;
size_threshold = maxsize * LIMIT_MULTIPLE;
files_threshold = maxfiles * LIMIT_MULTIPLE;
num_files = 0;
total_size = 0;
/* build a list of files */
traverse(dir, traverse_fn);
/* clean the cache */
sort_and_clean(minfiles);
stats_set_sizes(dir, total_files, total_size);
/* free it up */
for (i=0;i<num_files;i++) {
free(files[i]->fname);
free(files[i]);
files[i] = NULL;
}
if (files) free(files);
allocated = 0;
files = NULL;
num_files = 0;
total_size = 0;
}
/* cleanup in all cache subdirs */
void cleanup_all(const char *dir)
{
unsigned counters[STATS_END];
char *dname, *sfile;
int i;
for (i=0;i<=0xF;i++) {
x_asprintf(&dname, "%s/%1x", dir, i);
x_asprintf(&sfile, "%s/%1x/stats", dir, i);
memset(counters, 0, sizeof(counters));
stats_read(sfile, counters);
cleanup_dir(dname,
counters[STATS_MAXFILES],
counters[STATS_MAXSIZE],
0);
free(dname);
free(sfile);
}
}
/* traverse function for wiping files */
static void wipe_fn(const char *fname, struct stat *st)
{
char *p;
if (!S_ISREG(st->st_mode)) return;
p = str_basename(fname);
if (strcmp(p, "stats") == 0) {
free(p);
return;
}
free(p);
unlink(fname);
}
/* wipe all cached files in all subdirs */
void wipe_all(const char *dir)
{
char *dname;
int i;
for (i=0;i<=0xF;i++) {
x_asprintf(&dname, "%s/%1x", dir, i);
traverse(dir, wipe_fn);
free(dname);
}
/* and fix the counters */
cleanup_all(dir);
}

121
CCache/config.h.in Normal file
View File

@ -0,0 +1,121 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you would like to have zlib compression for ccache. */
#undef ENABLE_ZLIB
/* Define to 1 if you have the `asprintf' function. */
#undef HAVE_ASPRINTF
/* */
#undef HAVE_C99_VSNPRINTF
/* */
#undef HAVE_COMPAR_FN_T
/* Define to 1 if you have the <ctype.h> header file. */
#undef HAVE_CTYPE_H
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#undef HAVE_DIRENT_H
/* Define to 1 if you have the `gethostname' function. */
#undef HAVE_GETHOSTNAME
/* Define to 1 if you have the `getpwuid' function. */
#undef HAVE_GETPWUID
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mkstemp' function. */
#undef HAVE_MKSTEMP
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
/* Define to 1 if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_DIR_H
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
#undef HAVE_SYS_NDIR_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `utimes' function. */
#undef HAVE_UTIMES
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define my program name */
#undef PROGRAM_NAME
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define _GNU_SOURCE so that we get all necessary prototypes */
#undef _GNU_SOURCE

3
CCache/config_win32.h.in Normal file
View File

@ -0,0 +1,3 @@
#if !defined(PROGRAM_NAME)
#define PROGRAM_NAME "@PROGRAM_NAME@.exe"
#endif

5175
CCache/configure vendored Executable file

File diff suppressed because it is too large Load Diff

102
CCache/configure.ac Normal file
View File

@ -0,0 +1,102 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([ccache-swig], [0.0]) # Get version from SWIG in ccache_swig_config.h.in
AC_PREREQ(2.52)
AC_CONFIG_SRCDIR([ccache.h])
AC_MSG_NOTICE([Configuring ccache])
AC_CONFIG_HEADER(config.h)
AC_CONFIG_FILES([config_win32.h])
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_ARG_PROGRAM # for program_transform_name
AC_SUBST(PROGRAM_NAME)
if test "x$program_prefix" != "xNONE" -a "x$program_prefix" != "x"
then
PROGRAM_NAME="$program_prefix$PACKAGE_NAME"
else
PROGRAM_NAME="$PACKAGE_NAME"
fi
if test "x$program_suffix" != "xNONE" -a "x$program_suffix" != "x"
then
PROGRAM_NAME="$PROGRAM_NAME$program_suffix"
fi
AC_DEFINE_UNQUOTED(PROGRAM_NAME, "$PROGRAM_NAME", [Define my program name])
AC_DEFINE([_GNU_SOURCE], 1,
[Define _GNU_SOURCE so that we get all necessary prototypes])
# If GCC, turn on warnings.
if test "x$GCC" = "xyes"
then
CFLAGS="$CFLAGS -Wall -W"
else
CFLAGS="$CFLAGS -O"
fi
AC_HEADER_DIRENT
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(ctype.h strings.h stdlib.h string.h pwd.h sys/time.h)
AC_CHECK_FUNCS(realpath snprintf vsnprintf vasprintf asprintf mkstemp)
AC_CHECK_FUNCS(gethostname getpwuid)
AC_CHECK_FUNCS(utimes)
AC_CACHE_CHECK([for compar_fn_t in stdlib.h],ccache_cv_COMPAR_FN_T, [
AC_TRY_COMPILE(
[#include <stdlib.h>],
[
void test_fn(void) { qsort(NULL, 0, 0, (__compar_fn_t)NULL); }
],
ccache_cv_COMPAR_FN_T=yes,ccache_cv_COMPAR_FN_T=no)])
if test x"$ccache_cv_COMPAR_FN_T" = x"yes"; then
AC_DEFINE(HAVE_COMPAR_FN_T, 1, [ ])
fi
dnl Note: This could be replaced by AC_FUNC_SNPRINTF() in the autoconf macro archive
AC_CACHE_CHECK([for C99 vsnprintf],ccache_cv_HAVE_C99_VSNPRINTF,[
AC_TRY_RUN([
#include <sys/types.h>
#include <stdarg.h>
void foo(const char *format, ...) {
va_list ap;
int len;
char buf[5];
va_start(ap, format);
len = vsnprintf(0, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1);
exit(0);
}
main() { foo("hello"); }
],
ccache_cv_HAVE_C99_VSNPRINTF=yes,ccache_cv_HAVE_C99_VSNPRINTF=no,ccache_cv_HAVE_C99_VSNPRINTF=cross)])
if test x"$ccache_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [ ])
fi
dnl Check for zlib.
dnl Note: This could be replaced by CHECK_ZLIB() in the autoconf macro archive
AC_ARG_ENABLE([zlib],
AS_HELP_STRING([--enable-zlib], [enable zlib support for ccache compression]),,
[enable_zlib=yes])
if test x"$enable_zlib" = x"yes"; then
AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, gzdopen, [LIBS="-lz $LIBS"
AC_DEFINE([ENABLE_ZLIB], 1, [Define to 1 if you would like to have zlib compression for ccache.]) ] ))
fi
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

22
CCache/debian/NEWS Normal file
View File

@ -0,0 +1,22 @@
ccache (2.4-8) unstable; urgency=high
zlib compression is now enabled by default in order to increase the amount
of object files that can fit in the cache.
The impact on performance is supposed to be almost negligible
(see http://www.gustaebel.de/lars/ccache/). If you do want to disable
it however, simply export the CCACHE_NOCOMPRESS environment variable.
Note that a zlib-enabled ccache will still read your existing
uncompressed cache. If you want to compress/uncompress your cache,
see the manage-cache.sh script under /usr/share/doc/ccache/examples/.
-- Francois Marier <francois@debian.org> Sun, 20 May 2007 19:45:07 +1200
ccache (2.4-1) unstable; urgency=low
* This release changes the hash input slighly, so you will probably find
that you will not get any hits against your existing cache when you
upgrade.
-- Francois Marier <francois@debian.org> Sat, 11 Jun 2005 13:54:33 -0400

View File

@ -0,0 +1,59 @@
Installing ccache
-----------------
The recommended way to use this with Debian is to either create "cc"
and "gcc" symlinks to /usr/bin/ccache in your private bin directory
(which must be before the real cc and gcc in your path), or use
CC="ccache gcc" on the make command line.
Another option is to just prepend /usr/lib/ccache in your PATH
environment variable, like
export PATH="/usr/lib/ccache:$PATH"
Note that ccache works with both native and cross compilers.
Ignoring whitespace
-------------------
If you wish to set up ccache so that it ignores blank lines, have a
look at the CCACHE_UNIFY option. However, please note that this
option is off by default since the reported line numbers may not
match the source files anymore.
NFS Issues
----------
(from John Coiner <john.coiner@amd.com> on the ccache mailing list)
When CCache creates a hardlinked output file, it calls utime() to update
the timestamp on the object, so that Make realizes that the object has
changed.
On NFS, utime() has no coherency guarantee, AFAIK. When utime() runs on
host A, and our parallel implementation of Make is running on host B,
sometimes Make doesn't see the new timestamp soon enough -- and neglects
to relink the final binary. That's a one-way ticket to Silent Mysterious
Failure Town.
Instead of relying on the object file timestamp, we create a dummy file
with a reliable timestamp:
objs/foo.o objs/foo.o.built :
if ( ccache gcc -o foo.o -c foo.c ) ; \
then touch objs/foo.o.built ; \
else exit 1; \
fi
binary : objs/foo.o.built
gcc -o binary objs/foo.o
NFS does make a coherency guarantee, that if a file is written and
close()d on host A, and subsequently open()ed on host B, that the second
open() will reflect all modifications and attributes from the close().
Since Make does open() when checking timestamps, and the dummy file is
close()d when it's created, the binary will always relink after the
object is recompiled.
-- Francois Marier <francois@debian.org> Sun, 20 May 2007 17:35:36 +1200

221
CCache/debian/changelog Normal file
View File

@ -0,0 +1,221 @@
ccache (2.4-15) unstable; urgency=low
* Add a new patch which improve the consistency of timestamps on cached
objects to make sure clean-up is based on least recently used objects.
* Patch the set_limit call so that non-writable cache directories return
an error when attempting to size the max(files|size) (closes: #332527)
-- Francois Marier <francois@debian.org> Sun, 13 Apr 2008 15:07:05 +1200
ccache (2.4-14) unstable; urgency=low
* Mention the long options everywhere in the manpage
* Merge Gentoo patches:
- respect user's LDFLAGS
- use utimes() for timestamp if possible
-- Francois Marier <francois@debian.org> Sun, 23 Mar 2008 16:30:11 +1300
ccache (2.4-13) unstable; urgency=low
* Update CACHEDIR.TAG patch to avoid creating the tag file when the
CCACHE_READONLY environment variable is set. (closes: #464356)
* Mention the GNU-style long options in the manpage
-- Francois Marier <francois@debian.org> Thu, 07 Feb 2008 10:50:42 +1300
ccache (2.4-12) unstable; urgency=low
* Add symlink for gcc 4.3 (closes: #463590)
* Add support for the CACHEDIR.TAG spec, thanks to Karl Chen.
(see http://www.brynosaurus.com/cachedir/)
* Fix hyphens in manpage (lintian notice)
* Bump Standards-Version up to 3.7.3 (no changes)
* Bump debhelper compatibility to 6
-- Francois Marier <francois@debian.org> Sat, 02 Feb 2008 10:37:22 +1300
ccache (2.4-11) unstable; urgency=low
* Add the collab-maint repo to debian/control
-- Francois Marier <francois@debian.org> Tue, 20 Nov 2007 15:26:37 +1300
ccache (2.4-10) unstable; urgency=low
* Document where the patches are from in debian/patches/CREDITS
* debian/rules:
- Fixed "make distclean" lintian warning
- Removed commented-out entries
* Set debhelper compatibility to 5
* Add homepage field in debian/control
* Add symlinks for MinGW (closes: #445782)
* Bump the version to 5 in the debhelper dependency
-- Francois Marier <francois@debian.org> Fri, 19 Oct 2007 16:04:37 +1300
ccache (2.4-9) unstable; urgency=low
* Add a symlink for gcc 4.2 (closes: #431007)
* Fix dependencies when using -o (closes: #217713)
-- Francois Marier <francois@debian.org> Sat, 30 Jun 2007 17:58:44 +1200
ccache (2.4-8) unstable; urgency=low
* Enable zlib compression of the cache by default (closes: #409848).
Thanks to Sami Liedes for suggesting this.
* Disable ccache when profiling (closes: #215849).
Thanks to Ted Percival for the Patch.
* Fix NFS renaming issues and add instructions to the README.
Thanks to John Coiner and instructions.
* Put all patches in debian/patches and apply them at build time.
-- Francois Marier <francois@debian.org> Sun, 20 May 2007 19:42:34 +1200
ccache (2.4-7) unstable; urgency=low
* Use the real compiler when HOME is not set (closes: #396350)
* Include user script under doc/examples (closes: #392435)
Thanks to Behan Webster!
* Add support for GNU --long options (closes: #297126)
-- Francois Marier <francois@debian.org> Sat, 18 Nov 2006 00:50:59 -0500
ccache (2.4-6) unstable; urgency=low
* Include symlinks for gcc 4.1 (closes: #372838)
* Update watch file
-- Francois Marier <francois@debian.org> Tue, 13 Jun 2006 22:17:37 -0400
ccache (2.4-5) unstable; urgency=low
* Document the fact that cross-compiling is supported (closes: #349221)
* Bump Standards-Version up to 3.7.2 (no changes)
-- Francois Marier <francois@debian.org> Sun, 4 Jun 2006 01:20:07 -0400
ccache (2.4-4) unstable; urgency=low
* Mention another way to use ccache in README.Debian (thanks to Benjamin
Drieu for the suggestion) (closes: #267632)
* Update FSF address
* Fix watch file
-- Francois Marier <francois@debian.org> Sat, 26 Nov 2005 00:15:13 -0500
ccache (2.4-3) unstable; urgency=low
* Actually use the configuration flags in debian/rules
* Bump Standards-Version up to 3.6.2 (no changes)
-- Francois Marier <francois@debian.org> Sun, 26 Jun 2005 13:33:19 -0400
ccache (2.4-2) unstable; urgency=low
* Add gcc and g++ symlinks to /usr/lib/ccache (closes: #313490)
* Remove invalid entry from Depends
-- Francois Marier <francois@debian.org> Wed, 15 Jun 2005 20:51:03 -0400
ccache (2.4-1) unstable; urgency=low
* New maintainer (closes: #312867)
* New upstream version: (closes: #273753, #239640)
- New CCACHE_READONLY and CCACHE_TEMPDIR options
- Fixed handling of hard-linked compilers on AIX
- Fixed handling of HOME environment variable (closes: #299880)
- Show cache directory in stats output
* Fix copyright file
* Add 'distcc' to Suggests (closes: #269158)
* Add a note about whitespace in README.Debian (closes: #229116)
* Update rules to add symmlinks for gcc 3.4 & 4.0 (closes: #261177)
* Acknowledge NMUs (closes: #200185, #177129, #174417)
-- Francois Marier <francois@debian.org> Sun, 12 Jun 2005 12:05:34 -0400
ccache (2.3-1.1) unstable; urgency=low
* Non-maintainer upload during BSP
* Re-apply patch for
#200185 ccache: Incorrect symlinks in /usr/lib/ccache
(Closes: #200185)
-- Frank Lichtenheld <djpig@debian.org> Fri, 19 Mar 2004 11:14:50 +0100
ccache (2.3-1) unstable; urgency=low
* New upstream release: obsoletes existing caches.
* Tweak package description in arbitrary way (closes: #181721)
-- Paul Russell <prussell@debian.org> Mon, 29 Sep 2003 02:53:20 +0200
ccache (2.2-2) unstable; urgency=low
* Insert more symlinks in ccache dir (closes: #197468)
-- Paul Russell <prussell@debian.org> Mon, 16 Jun 2003 10:52:50 +0100
ccache (2.2-1) unstable; urgency=low
* New upstream release (closes: #150755)
* Insert more symlinks in ccache dir (closes: #144462)
-- Paul Russell <prussell@debian.org> Mon, 17 Feb 2003 07:19:36 +0100
ccache (2.1.1-2) unstable; urgency=low
* Restored /usr/lib/ccache symlinks (closes: #179393)
* Fixed manpage typo (closes: #179564)
* With thanks to Andreas Rottmann.
-- Paul Russell <prussell@debian.org> Wed, 5 Feb 2003 10:01:10 +0100
ccache (2.1.1-1) unstable; urgency=low
* NMU (with maintainer consent).
* New upstream release (closes: #174417, #177129).
* debian/control:
+ Build-Depend on and use dephelper 4 (DH_COMPAT = 4).
+ Bumped Standards-Version to 3.5.8.
+ No full stop on short package description (fixes linda warning).
* debian/copright:
+ Make lintian feel comfortable; fixes warnings:
- copyright-should-refer-to-common-license-file-for-gpl
- copyright-lists-upstream-authors-with-dh_make-boilerplate
* Built with g++ 3.2 :-).
-- Andreas Rottmann <rotty@debian.org> Thu, 16 Jan 2003 11:42:38 +0100
ccache (1.9-1) unstable; urgency=low
* New upstream release (closes: #144920)
-- Paul Russell <prussell@debian.org> Mon, 13 May 2002 10:01:09 +0200
ccache (1.8-1) unstable; urgency=low
* New upstream release (closes: #145401)
-- Paul Russell <prussell@debian.org> Fri, 3 May 2002 02:26:32 +0200
ccache (1.7-1) unstable; urgency=low
* New upstream release
* Install symlinks in /usr/lib/ccache (closes: #141337)
-- Paul Russell <prussell@debian.org> Wed, 10 Apr 2002 17:51:21 +0200
ccache (1.4-1) unstable; urgency=low
* New upstream release
-- Paul Russell <prussell@debian.org> Wed, 3 Apr 2002 03:41:46 +0200
ccache (1.2-1) unstable; urgency=low
* Initial Release.
-- Paul Russell <prussell@debian.org> Sun, 31 Mar 2002 14:08:57 +0200

1
CCache/debian/compat Normal file
View File

@ -0,0 +1 @@
6

20
CCache/debian/control Normal file
View File

@ -0,0 +1,20 @@
Source: ccache
Section: devel
Priority: optional
Maintainer: Francois Marier <francois@debian.org>
Build-Depends: debhelper (>> 6), autotools-dev, zlib1g-dev
Standards-Version: 3.7.3
Homepage: http://ccache.samba.org
Vcs-Svn: svn://svn.debian.org/svn/collab-maint/deb-maint/ccache/
Vcs-Browser: http://svn.debian.org/wsvn/collab-maint/deb-maint/ccache/
Package: ccache
Architecture: any
Depends: ${shlibs:Depends}
Suggests: distcc
Description: Compiler results cacher, for fast recompiles
ccache is a compiler cache. It speeds up re-compilation of C/C++ code
by caching previous compiles and detecting when the same compile is
being done again.
.
This is similar to, but faster than, the compilercache package.

29
CCache/debian/copyright Normal file
View File

@ -0,0 +1,29 @@
This package was debianized by Paul Russell <prussell@debian.org> on
Sun, 31 Mar 2002 14:08:57 +0200.
It was downloaded from http://ccache.samba.org/ftp/ccache/
The ccache-zlib patch was downloaded from http://www.gustaebel.de/lars/ccache/
Upstream Author: Andrew Tridgell <tridge@samba.org>
Copyright: 2002-2005 Andrew Tridgell <tridge@samba.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA
You are free to distribute this software under the terms of the GNU General
Public License. On Debian systems, the complete text of the GNU General
Public License can be found in /usr/share/common-licenses/GPL file.

3
CCache/debian/dirs Normal file
View File

@ -0,0 +1,3 @@
usr/bin
usr/lib/ccache
usr/share/man/man1

1
CCache/debian/docs Normal file
View File

@ -0,0 +1 @@
README

2
CCache/debian/examples Normal file
View File

@ -0,0 +1,2 @@
debian/update-ccache
manage-cache.sh

View File

@ -0,0 +1,100 @@
--- ccache.c
+++ ccache.c
@@ -836,6 +836,13 @@
{
/* find the real compiler */
find_compiler(argc, argv);
+
+ /* use the real compiler if HOME is not set */
+ if (!cache_dir) {
+ cc_log("Unable to determine home directory\n");
+ cc_log("ccache is disabled\n");
+ failed();
+ }
/* we might be disabled */
if (getenv("CCACHE_DISABLE")) {
@@ -895,6 +902,13 @@
printf("-V print version number\n");
}
+static void check_cache_dir(void)
+{
+ if (!cache_dir) {
+ fatal("Unable to determine home directory");
+ }
+}
+
/* the main program when not doing a compile */
static int ccache_main(int argc, char *argv[])
{
@@ -914,31 +928,37 @@
exit(0);
case 's':
+ check_cache_dir();
stats_summary();
break;
case 'c':
+ check_cache_dir();
cleanup_all(cache_dir);
printf("Cleaned cache\n");
break;
case 'C':
+ check_cache_dir();
wipe_all(cache_dir);
printf("Cleared cache\n");
break;
case 'z':
+ check_cache_dir();
stats_zero();
printf("Statistics cleared\n");
break;
case 'F':
+ check_cache_dir();
v = atoi(optarg);
stats_set_limits(v, -1);
printf("Set cache file limit to %u\n", (unsigned)v);
break;
case 'M':
+ check_cache_dir();
v = value_units(optarg);
stats_set_limits(-1, v);
printf("Set cache size limit to %uk\n", (unsigned)v);
@@ -983,7 +1003,10 @@
cache_dir = getenv("CCACHE_DIR");
if (!cache_dir) {
- x_asprintf(&cache_dir, "%s/.ccache", get_home_directory());
+ const char *home_directory = get_home_directory();
+ if (home_directory) {
+ x_asprintf(&cache_dir, "%s/.ccache", home_directory);
+ }
}
temp_dir = getenv("CCACHE_TEMPDIR");
@@ -1023,7 +1046,7 @@
}
/* make sure the cache dir exists */
- if (create_dir(cache_dir) != 0) {
+ if (cache_dir && (create_dir(cache_dir) != 0)) {
fprintf(stderr,"ccache: failed to create %s (%s)\n",
cache_dir, strerror(errno));
exit(1);
--- util.c
+++ util.c
@@ -448,7 +448,7 @@
}
}
#endif
- fatal("Unable to determine home directory");
+ cc_log("Unable to determine home directory");
return NULL;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
Index: ccache.c
===================================================================
--- ccache.c (révision 7695)
+++ ccache.c (copie de travail)
@@ -22,6 +22,7 @@
*/
#include "ccache.h"
+#include <getopt.h>
/* the base cache directory */
char *cache_dir = NULL;
@@ -885,14 +886,14 @@
printf("\tcompiler [compile options] (via symbolic link)\n");
printf("\nOptions:\n");
- printf("-s show statistics summary\n");
- printf("-z zero statistics\n");
- printf("-c run a cache cleanup\n");
- printf("-C clear the cache completely\n");
- printf("-F <maxfiles> set maximum files in cache\n");
- printf("-M <maxsize> set maximum size of cache (use G, M or K)\n");
- printf("-h this help page\n");
- printf("-V print version number\n");
+ printf("-s, --show-stats show statistics summary\n");
+ printf("-z, --zero-stats zero statistics\n");
+ printf("-c, --cleanup run a cache cleanup\n");
+ printf("-C, --clear clear the cache completely\n");
+ printf("-F <n>, --max-files=<n> set maximum files in cache\n");
+ printf("-M <n>, --max-size=<n> set maximum size of cache (use G, M or K)\n");
+ printf("-h, --help this help page\n");
+ printf("-V, --version print version number\n");
}
/* the main program when not doing a compile */
@@ -901,7 +902,21 @@
int c;
size_t v;
- while ((c = getopt(argc, argv, "hszcCF:M:V")) != -1) {
+ static struct option long_options[] =
+ {
+ {"show-stats", no_argument, 0, 's'},
+ {"zero-stats", no_argument, 0, 'z'},
+ {"cleanup", no_argument, 0, 'c'},
+ {"clear", no_argument, 0, 'C'},
+ {"max-files", required_argument, 0, 'F'},
+ {"max-size", required_argument, 0, 'M'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {0, 0, 0, 0}
+ };
+ int option_index = 0;
+
+ while ((c = getopt_long(argc, argv, "hszcCF:M:V", long_options, &option_index)) != -1) {
switch (c) {
case 'V':
printf("ccache version %s\n", CCACHE_VERSION);
Index: ccache.1
===================================================================
--- ccache.1 (révision 7695)
+++ ccache.1 (copie de travail)
@@ -23,14 +23,14 @@
.nf
--s show statistics summary
--z zero statistics
--c run a cache cleanup
--C clear the cache completely
--F <maxfiles> set maximum files in cache
--M <maxsize> set maximum size of cache (use G, M or K)
--h this help page
--V print version number
+\-s, \-\-show-stats show statistics summary
+\-z, \-\-zero-stats zero statistics
+\-c, \-\-cleanup run a cache cleanup
+\-C, \-\-clear clear the cache completely
+\-F <n>, \-\-max-files=<n> set maximum files in cache
+\-M <n>, \-\-max-size=<n> set maximum size of cache (use G, M or K)
+\-h, \-\-help this help page
+\-V, \-\-version print version number
.fi
@@ -43,22 +43,22 @@
normal compiler options apply and you should refer to your compilers
documentation\&.
.PP
-.IP "\fB-h\fP"
+.IP "\fB-h, --help\fP"
Print a options summary page
.IP
-.IP "\fB-s\fP"
+.IP "\fB-s, --show-stats\fP"
Print the current statistics summary for the cache\&. The
statistics are stored spread across the subdirectories of the
cache\&. Using "ccache -s" adds up the statistics across all
subdirectories and prints the totals\&.
.IP
-.IP "\fB-z\fP"
+.IP "\fB-z, --zero-stats\fP"
Zero the cache statistics\&.
.IP
-.IP "\fB-V\fP"
+.IP "\fB-V, --version\fP"
Print the ccache version number
.IP
-.IP "\fB-c\fP"
+.IP "\fB-c, --cleanup\fP"
Clean the cache and re-calculate the cache file count and
size totals\&. Normally the -c option should not be necessary as ccache
keeps the cache below the specified limits at runtime and keeps
@@ -66,16 +66,16 @@
if you manually modify the cache contents or believe that the cache
size statistics may be inaccurate\&.
.IP
-.IP "\fB-C\fP"
+.IP "\fB-C, --clear\fP"
Clear the entire cache, removing all cached files\&.
.IP
-.IP "\fB-F maxfiles\fP"
+.IP "\fB-F <maxfiles>, --max-files=<maxfiles>\fP"
This sets the maximum number of files allowed in
the cache\&. The value is stored inside the cache directory and applies
to all future compiles\&. Due to the way the value is stored the actual
value used is always rounded down to the nearest multiple of 16\&.
.IP
-.IP "\fB-M maxsize\fP"
+.IP "\fB-M <maxsize>, --max-size=<maxsize>\fP"
This sets the maximum cache size\&. You can specify
a value in gigabytes, megabytes or kilobytes by appending a G, M or K
to the value\&. The default is gigabytes\&. The actual value stored is

View File

@ -0,0 +1,13 @@
diff -ru ccache-2.4/ccache.c ccache-2.4-tp/ccache.c
--- ccache.c 2007-05-20 03:14:19.000000000 +1000
+++ ccache.c 2007-05-20 03:17:54.000000000 +1000
@@ -641,6 +641,9 @@
/* these are too hard */
if (strcmp(argv[i], "-fbranch-probabilities")==0 ||
+ strcmp(argv[i], "-fprofile-arcs") == 0 ||
+ strcmp(argv[i], "-ftest-coverage") == 0 ||
+ strcmp(argv[i], "--coverage") == 0 ||
strcmp(argv[i], "-M") == 0 ||
strcmp(argv[i], "-MM") == 0 ||
strcmp(argv[i], "-x") == 0) {

View File

@ -0,0 +1,45 @@
--- ccache.1.orig 2007-05-20 17:30:57.000000000 +1200
+++ ccache.1 2007-05-20 17:31:27.000000000 +1200
@@ -367,12 +367,6 @@
.IP o
ccache avoids a double call to cpp on a cache miss
.PP
-.SH "BUGS"
-.PP
-When the cache is stored on an NFS filesystem, the filesystem must be
-exported with the \fBno_subtree_check\fP option to make renames between
-directories reliable\&.
-.PP
.SH "CREDITS"
.PP
Thanks to the following people for their contributions to ccache
--- util.c.patched 2007-05-20 18:19:11.000000000 +1200
+++ util.c 2007-05-20 18:20:55.000000000 +1200
@@ -58,9 +58,26 @@
}
}
+static int safe_rename(const char* oldpath, const char* newpath)
+{
+ /* safe_rename is for creating entries in the cache.
+
+ Works like rename(), but it never overwrites an existing
+ cache entry. This avoids corruption on NFS. */
+ int status = link( oldpath, newpath );
+ if( status == 0 || errno == EEXIST )
+ {
+ return unlink( oldpath );
+ }
+ else
+ {
+ return -1;
+ }
+}
+
/* move a file using rename */
int move_file(const char *src, const char *dest) {
- return rename(src, dest);
+ return safe_rename(src, dest);
}
/* copy a file - used when hard links don't work

View File

@ -0,0 +1,77 @@
--- ccache.c Mon Sep 13 11:38:30 2004
+++ ccache.c Thu Jun 21 22:17:32 2007
@@ -627,6 +627,13 @@ static void process_args(int argc, char
int found_S_opt = 0;
struct stat st;
char *e;
+ /* is gcc being asked to output dependencies? */
+ int generating_dependencies = 0;
+ /* is the dependency makefile name overridden with -MF? */
+ int dependency_filename_specified = 0;
+ /* is the dependency makefile target name specified with -MQ or -MF? */
+ int dependency_target_specified = 0;
+
stripped_args = args_init(0, NULL);
@@ -702,6 +709,18 @@ static void process_args(int argc, char
continue;
}
+ /* These options require special handling, because they
+ behave differently with gcc -E, when the output
+ file is not specified. */
+
+ if (strcmp(argv[i], "-MD") == 0 || strcmp(argv[i], "-MMD") == 0) {
+ generating_dependencies = 1;
+ } else if (strcmp(argv[i], "-MF") == 0) {
+ dependency_filename_specified = 1;
+ } else if (strcmp(argv[i], "-MQ") == 0 || strcmp(argv[i], "-MT") == 0) {
+ dependency_target_specified = 1;
+ }
+
/* options that take an argument */
{
const char *opts[] = {"-I", "-include", "-imacros", "-iprefix",
@@ -812,6 +831,41 @@ static void process_args(int argc, char
}
p[1] = found_S_opt ? 's' : 'o';
p[2] = 0;
+ }
+
+ /* If dependencies are generated, configure the preprocessor */
+
+ if (generating_dependencies && output_file) {
+ if (!dependency_filename_specified) {
+ char *default_depfile_name = x_strdup(output_file);
+ char *p = strrchr(default_depfile_name, '.');
+
+ if (p) {
+ if (strlen(p) < 2) {
+ stats_update(STATS_ARGS);
+ failed();
+ return;
+ }
+ *p = 0;
+ }
+ else {
+ int len = p - default_depfile_name;
+
+ p = x_malloc(len + 3);
+ strncpy(default_depfile_name, p, len - 1);
+ free(default_depfile_name);
+ default_depfile_name = p;
+ }
+
+ strcat(default_depfile_name, ".d");
+ args_add(stripped_args, "-MF");
+ args_add(stripped_args, default_depfile_name);
+ }
+
+ if (!dependency_target_specified) {
+ args_add(stripped_args, "-MT");
+ args_add(stripped_args, output_file);
+ }
}
/* cope with -o /dev/null */

View File

@ -0,0 +1,75 @@
Index: ccache.c
===================================================================
--- ccache.c (révision 7695)
+++ ccache.c (copie de travail)
@@ -1029,6 +1029,14 @@
exit(1);
}
+ if (!getenv("CCACHE_READONLY")) {
+ if (create_cachedirtag(cache_dir) != 0) {
+ fprintf(stderr,"ccache: failed to create %s/CACHEDIR.TAG (%s)\n",
+ cache_dir, strerror(errno));
+ exit(1);
+ }
+ }
+
ccache(argc, argv);
return 1;
}
Index: ccache.h
===================================================================
--- ccache.h (révision 7695)
+++ ccache.h (copie de travail)
@@ -81,6 +81,7 @@
int copy_file(const char *src, const char *dest);
int create_dir(const char *dir);
+int create_cachedirtag(const char *dir);
void x_asprintf(char **ptr, const char *format, ...);
char *x_strdup(const char *s);
void *x_realloc(void *ptr, size_t size);
Index: util.c
===================================================================
--- util.c (révision 7695)
+++ util.c (copie de travail)
@@ -138,6 +138,39 @@
return 0;
}
+char const CACHEDIR_TAG[] =
+ "Signature: 8a477f597d28d172789f06886806bc55\n"
+ "# This file is a cache directory tag created by ccache.\n"
+ "# For information about cache directory tags, see:\n"
+ "# http://www.brynosaurus.com/cachedir/\n";
+
+int create_cachedirtag(const char *dir)
+{
+ char *filename;
+ struct stat st;
+ FILE *f;
+ x_asprintf(&filename, "%s/CACHEDIR.TAG", dir);
+ if (stat(filename, &st) == 0) {
+ if (S_ISREG(st.st_mode)) {
+ goto success;
+ }
+ errno = EEXIST;
+ goto error;
+ }
+ f = fopen(filename, "w");
+ if (!f) goto error;
+ if (fwrite(CACHEDIR_TAG, sizeof(CACHEDIR_TAG)-1, 1, f) != 1) {
+ goto error;
+ }
+ if (fclose(f)) goto error;
+success:
+ free(filename);
+ return 0;
+error:
+ free(filename);
+ return 1;
+}
+
/*
this is like asprintf() but dies if the malloc fails
note that we use vsnprintf in a rather poor way to make this more portable

View File

@ -0,0 +1,89 @@
Index: ccache.1
===================================================================
--- ccache.1 (révision 7695)
+++ ccache.1 (copie de travail)
@@ -49,7 +49,7 @@
.IP "\fB-s\fP"
Print the current statistics summary for the cache\&. The
statistics are stored spread across the subdirectories of the
-cache\&. Using "ccache -s" adds up the statistics across all
+cache\&. Using "ccache \-s" adds up the statistics across all
subdirectories and prints the totals\&.
.IP
.IP "\fB-z\fP"
@@ -60,7 +60,7 @@
.IP
.IP "\fB-c\fP"
Clean the cache and re-calculate the cache file count and
-size totals\&. Normally the -c option should not be necessary as ccache
+size totals\&. Normally the \-c option should not be necessary as ccache
keeps the cache below the specified limits at runtime and keeps
statistics up to date on each compile\&. This option is mostly useful
if you manually modify the cache contents or believe that the cache
@@ -100,9 +100,9 @@
cp ccache /usr/local/bin/
- ln -s /usr/local/bin/ccache /usr/local/bin/gcc
- ln -s /usr/local/bin/ccache /usr/local/bin/g++
- ln -s /usr/local/bin/ccache /usr/local/bin/cc
+ ln \-s /usr/local/bin/ccache /usr/local/bin/gcc
+ ln \-s /usr/local/bin/ccache /usr/local/bin/g++
+ ln \-s /usr/local/bin/ccache /usr/local/bin/cc
.fi
@@ -118,7 +118,7 @@
.PP
When run as a compiler front end ccache usually just takes the same
command line options as the compiler you are using\&. The only exception
-to this is the option \&'--ccache-skip\&'\&. That option can be used to tell
+to this is the option \&'\-\-ccache-skip\&'\&. That option can be used to tell
ccache that the next option is definitely not a input filename, and
should be passed along to the compiler as-is\&.
.PP
@@ -128,7 +128,7 @@
of the resulting object file (among other things)\&. The heuristic
ccache uses in this parse is that any string on the command line that
exists as a file is treated as an input file name (usually a C
-file)\&. By using --ccache-skip you can force an option to not be
+file)\&. By using \-\-ccache-skip you can force an option to not be
treated as an input file name and instead be passed along to the
compiler as a command line option\&.
.PP
@@ -238,7 +238,7 @@
.IP "\fBCCACHE_UNIFY\fP"
If you set the environment variable CCACHE_UNIFY
then ccache will use the C/C++ unifier when hashing the pre-processor
-output if -g is not used in the compile\&. The unifier is slower than a
+output if \-g is not used in the compile\&. The unifier is slower than a
normal hash, so setting this environment variable loses a little bit
of speed, but it means that ccache can take advantage of not
recompiling when the changes to the source code consist of
@@ -262,7 +262,7 @@
.PP
By default ccache has a one gigabyte limit on the cache size and no
maximum number of files\&. You can set a different limit using the
-"ccache -M" and "ccache -F" options, which set the size and number of
+"ccache \-M" and "ccache \-F" options, which set the size and number of
files limits\&.
.PP
When these limits are reached ccache will reduce the cache to 20%
@@ -276,7 +276,7 @@
that it is the same code by forming a hash of:
.PP
.IP o
-the pre-processor output from running the compiler with -E
+the pre-processor output from running the compiler with \-E
.IP o
the command line options
.IP o
@@ -331,7 +331,7 @@
.IP o
Make sure that the setgid bit is set on all directories in the
cache\&. This tells the filesystem to inherit group ownership for new
-directories\&. The command "chmod g+s `find $CCACHE_DIR -type d`" might
+directories\&. The command "chmod g+s `find $CCACHE_DIR \-type d`" might
be useful for this\&.
.PP
.SH "HISTORY"

View File

@ -0,0 +1,11 @@
--- Makefile.in.orig 2008-03-23 17:01:19.000000000 +1300
+++ Makefile.in 2008-03-23 17:03:03.000000000 +1300
@@ -21,7 +21,7 @@
docs: ccache.1 web/ccache-man.html
ccache$(EXEEXT): $(OBJS) $(HEADERS)
- $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
ccache.1: ccache.yo
-yodl2man -o ccache.1 ccache.yo

View File

@ -0,0 +1,23 @@
--- ccache.c (révision 8804)
+++ ccache.c (copie de travail)
@@ -481,6 +481,9 @@
return;
}
+ /* update timestamps for LRU cleanup
+ also gives output_file a sensible mtime when hard-linking (for make) */
+ utime(hashname, NULL);
utime(stderr_file, NULL);
if (strcmp(output_file, "/dev/null") == 0) {
@@ -513,10 +516,6 @@
failed();
}
}
- if (ret == 0) {
- /* update the mtime on the file so that make doesn't get confused */
- utime(output_file, NULL);
- }
/* get rid of the intermediate preprocessor file */
if (i_tmpfile) {

View File

@ -0,0 +1,85 @@
--- ccache.c 2004-09-13 03:38:30.000000000 -0700
+++ ccache.c 2006-06-09 16:29:16.695117780 -0700
@@ -481,8 +481,13 @@
/* update timestamps for LRU cleanup
also gives output_file a sensible mtime when hard-linking (for make) */
+#ifdef HAVE_UTIMES
+ utimes(hashname, NULL);
+ utimes(stderr_file, NULL);
+#else
utime(hashname, NULL);
utime(stderr_file, NULL);
+#endif
if (strcmp(output_file, "/dev/null") == 0) {
ret = 0;
--- ccache.h 2004-09-13 03:38:30.000000000 -0700
+++ ccache.h 2006-06-09 16:28:16.601658626 -0700
@@ -22,6 +22,9 @@
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
#define STATUS_NOTFOUND 3
#define STATUS_FATAL 4
--- config.h.in 2003-09-27 21:48:17.000000000 -0700
+++ config.h.in 2006-06-09 16:25:43.000000000 -0700
@@ -19,6 +19,9 @@
/* Define to 1 if you have the `gethostname' function. */
#undef HAVE_GETHOSTNAME
+/* Define to 1 if you have the `getpwuid' function. */
+#undef HAVE_GETPWUID
+
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
@@ -31,6 +34,9 @@
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
+/* Define to 1 if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
@@ -60,6 +66,9 @@
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
@@ -69,6 +78,9 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define to 1 if you have the `utimes' function. */
+#undef HAVE_UTIMES
+
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
--- configure.in 2004-09-13 03:38:30.000000000 -0700
+++ configure.in 2006-06-09 16:25:15.541288184 -0700
@@ -27,10 +27,11 @@
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS(ctype.h strings.h stdlib.h string.h pwd.h)
+AC_CHECK_HEADERS(ctype.h strings.h stdlib.h string.h pwd.h sys/time.h)
AC_CHECK_FUNCS(realpath snprintf vsnprintf vasprintf asprintf mkstemp)
AC_CHECK_FUNCS(gethostname getpwuid)
+AC_CHECK_FUNCS(utimes)
AC_CACHE_CHECK([for compar_fn_t in stdlib.h],ccache_cv_COMPAR_FN_T, [
AC_TRY_COMPILE(

View File

@ -0,0 +1,83 @@
--- stats.c (révision 8804)
+++ stats.c (copie de travail)
@@ -286,7 +286,7 @@
/* set the per directory limits */
-void stats_set_limits(long maxfiles, long maxsize)
+int stats_set_limits(long maxfiles, long maxsize)
{
int dir;
unsigned counters[STATS_END];
@@ -298,7 +298,9 @@
maxsize /= 16;
}
- create_dir(cache_dir);
+ if (create_dir(cache_dir) != 0) {
+ return 1;
+ }
/* set the limits in each directory */
for (dir=0;dir<=0xF;dir++) {
@@ -306,7 +308,9 @@
int fd;
x_asprintf(&cdir, "%s/%1x", cache_dir, dir);
- create_dir(cdir);
+ if (create_dir(cdir) != 0) {
+ return 1;
+ }
x_asprintf(&fname, "%s/stats", cdir);
free(cdir);
@@ -326,6 +330,8 @@
}
free(fname);
}
+
+ return 0;
}
/* set the per directory sizes */
--- ccache.c (révision 8804)
+++ ccache.c (copie de travail)
@@ -935,15 +934,23 @@
case 'F':
check_cache_dir();
v = atoi(optarg);
- stats_set_limits(v, -1);
- printf("Set cache file limit to %u\n", (unsigned)v);
+ if (stats_set_limits(v, -1) == 0) {
+ printf("Set cache file limit to %u\n", (unsigned)v);
+ } else {
+ printf("Could not set cache file limit.\n");
+ exit(1);
+ }
break;
case 'M':
check_cache_dir();
v = value_units(optarg);
- stats_set_limits(-1, v);
- printf("Set cache size limit to %uk\n", (unsigned)v);
+ if (stats_set_limits(-1, v) == 0) {
+ printf("Set cache size limit to %uk\n", (unsigned)v);
+ } else {
+ printf("Could not set cache size limit.\n");
+ exit(1);
+ }
break;
default:
--- ccache.h (révision 8804)
+++ ccache.h (copie de travail)
@@ -101,7 +101,7 @@
void stats_summary(void);
void stats_tocache(size_t size);
void stats_read(const char *stats_file, unsigned counters[STATS_END]);
-void stats_set_limits(long maxfiles, long maxsize);
+int stats_set_limits(long maxfiles, long maxsize);
size_t value_units(const char *s);
void display_size(unsigned v);
void stats_set_sizes(const char *dir, size_t num_files, size_t total_size);

View File

@ -0,0 +1,33 @@
--- web/index.html~ 2004-09-13 13:38:30.000000000 +0300
+++ web/index.html 2004-09-26 01:04:38.458008118 +0300
@@ -29,10 +29,10 @@
<li>fixed handling of HOME environment variable
</ul>
-See the <a href="/ccache/ccache-man.html">manual page</a> for details
+See the <a href="ccache-man.html">manual page</a> for details
on the new options.<p>
-You can get this release from the <a href="/ftp/ccache/">download directory</a>
+You can get this release from the <a href="http://ccache.samba.org/ftp/ccache/">download directory</a>
<p>NOTE! This release changes the hash input slighly, so you will
probably find that you will not get any hits against your existing
@@ -87,7 +87,7 @@
<h2>Documentation</h2>
-See the <a href="/ccache/ccache-man.html">manual page</a>
+See the <a href="ccache-man.html">manual page</a>
<h2>Performance</h2>
@@ -116,7 +116,7 @@
<h2>Download</h2>
You can download the latest release from the <a
-href="/ftp/ccache/">download directory</a>.<p>
+href="http://ccache.samba.org/ftp/ccache/">download directory</a>.<p>
For the bleeding edge, you can fetch ccache via CVS or
rsync. To fetch via cvs use the following command:

View File

@ -0,0 +1,48 @@
Index: ccache.1
===================================================================
RCS file: /cvsroot/ccache/ccache.1,v
retrieving revision 1.26
diff -u -r1.26 ccache.1
--- ccache.1 24 Nov 2005 21:10:08 -0000 1.26
+++ ccache.1 21 Jul 2007 21:03:32 -0000
@@ -330,7 +330,7 @@
.IP o
Use the same \fBCCACHE_DIR\fP environment variable setting
.IP o
-Set the \fBCCACHE_NOLINK\fP environment variable
+Unset the \fBCCACHE_HARDLINK\fP environment variable
.IP o
Make sure everyone sets the CCACHE_UMASK environment variable
to 002, this ensures that cached files are accessible to everyone in
Index: ccache.yo
===================================================================
RCS file: /cvsroot/ccache/ccache.yo,v
retrieving revision 1.27
diff -u -r1.27 ccache.yo
--- ccache.yo 24 Nov 2005 21:54:09 -0000 1.27
+++ ccache.yo 21 Jul 2007 21:03:32 -0000
@@ -289,7 +289,7 @@
itemize(
it() Use the same bf(CCACHE_DIR) environment variable setting
- it() Set the bf(CCACHE_NOLINK) environment variable
+ it() Unset the bf(CCACHE_HARDLINK) environment variable
it() Make sure everyone sets the CCACHE_UMASK environment variable
to 002, this ensures that cached files are accessible to everyone in
the group.
Index: web/ccache-man.html
===================================================================
RCS file: /cvsroot/ccache/web/ccache-man.html,v
retrieving revision 1.25
diff -u -r1.25 ccache-man.html
--- web/ccache-man.html 13 Sep 2004 10:38:17 -0000 1.25
+++ web/ccache-man.html 21 Jul 2007 21:03:32 -0000
@@ -256,7 +256,7 @@
following conditions need to be met:
<p><ul>
<li > Use the same <strong>CCACHE_DIR</strong> environment variable setting
- <li > Set the <strong>CCACHE_NOLINK</strong> environment variable
+ <li > Unset the <strong>CCACHE_HARDLINK</strong> environment variable
<li > Make sure everyone sets the CCACHE_UMASK environment variable
to 002, this ensures that cached files are accessible to everyone in
the group.

View File

@ -0,0 +1,47 @@
01_no_home.diff:
Francois Marier <francois@debian.org>
Made especially for the Debian package.
02_ccache_compressed.diff:
Lars Gustäbel <lars@gustaebel.de>
http://www.gustaebel.de/lars/ccache/ (downloaded on 2007-05-20)
03_long_options.diff:
Francois Marier <francois@debian.org>
Made especially for the Debian package.
04_ignore_profile.diff:
Ted Percival <ted@midg3t.net>
http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=20;filename=ccache-profile.patch;att=1;bug=215849
05_nfs_fix.diff:
John Coiner <john.coiner@amd.com>
http://lists.samba.org/archive/ccache/2007q1/000265.html
06_md.diff:
Andrea Bittau <a.bittau@cs.ucl.ac.uk>
http://darkircop.org/ccache/ccache-2.4-md.patch (downloaded on 2007-06-30)
07_cachedirtag.diff:
Karl Chen <quarl@cs.berkeley.edu>
http://lists.samba.org/archive/ccache/2008q1/000316.html (downloaded on 2008-02-02)
08_manpage_hyphens.diff:
Francois Marier <francois@debian.org>
Made especially for the Debian package.
09_respect_ldflags.diff:
Lisa Seelye <lisa@gentoo.org>
http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-util/ccache/files/ccache-2.4-respectflags.patch?rev=1.1&view=markup
10_lru_cleanup.diff:
RW <fbsd06@mlists.homeunix.com>
http://lists.samba.org/archive/ccache/2008q2/000339.html (downloaded on 2008-04-11)
11_utimes.diff:
Robin H. Johnson <robbat2@gentoo.org>
http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-util/ccache/files/ccache-2.4-utimes.patch?rev=1.1&view=markup
12_cachesize_permissions.diff:
Francois Marier <francois@debian.org>
Made especially for the Debian package to fix http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=332527

141
CCache/debian/rules Normal file
View File

@ -0,0 +1,141 @@
#!/usr/bin/make -f
# Sample debian/rules that uses debhelper.
# GNU copyright 1997 to 1999 by Joey Hess.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
export DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
export DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
confflags += --build $(DEB_HOST_GNU_TYPE)
else
confflags += --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
endif
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
CFLAGS += -g
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
config.status: configure
dh_testdir
# Apply Debian specific patches
cp $(CURDIR)/ccache.c $(CURDIR)/ccache.c.unpatched
cp $(CURDIR)/util.c $(CURDIR)/util.c.unpatched
cp $(CURDIR)/ccache.1 $(CURDIR)/ccache.1.unpatched
cp $(CURDIR)/ccache.h $(CURDIR)/ccache.h.unpatched
cp $(CURDIR)/ccache.yo $(CURDIR)/ccache.yo.unpatched
cp $(CURDIR)/config.h.in $(CURDIR)/config.h.in.unpatched
cp $(CURDIR)/configure $(CURDIR)/configure.unpatched
cp $(CURDIR)/configure.in $(CURDIR)/configure.in.unpatched
cp $(CURDIR)/Makefile.in $(CURDIR)/Makefile.in.unpatched
if test ! -f patch-stamp; then \
for patch in $(CURDIR)/debian/patches/*.diff ;\
do \
echo APPLYING PATCH\: $${patch##*/};\
patch -p0 < $$patch ;\
done ;\
touch patch-stamp ;\
fi
chmod +x $(CURDIR)/manage-cache.sh
./configure $(confflags) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
build: build-stamp
build-stamp: config.status
dh_testdir
$(MAKE)
touch build-stamp
clean:
dh_testdir
dh_testroot
rm -f build-stamp
# Unapply patches
-test -r $(CURDIR)/ccache.c.unpatched && mv $(CURDIR)/ccache.c.unpatched $(CURDIR)/ccache.c
-test -r $(CURDIR)/util.c.unpatched && mv $(CURDIR)/util.c.unpatched $(CURDIR)/util.c
-test -r $(CURDIR)/ccache.1.unpatched && mv $(CURDIR)/ccache.1.unpatched $(CURDIR)/ccache.1
-test -r $(CURDIR)/ccache.h.unpatched && mv $(CURDIR)/ccache.h.unpatched $(CURDIR)/ccache.h
-test -r $(CURDIR)/ccache.yo.unpatched && mv $(CURDIR)/ccache.yo.unpatched $(CURDIR)/ccache.yo
-test -r $(CURDIR)/config.h.in.unpatched && mv $(CURDIR)/config.h.in.unpatched $(CURDIR)/config.h.in
-test -r $(CURDIR)/configure.unpatched && mv $(CURDIR)/configure.unpatched $(CURDIR)/configure
-test -r $(CURDIR)/configure.in.unpatched && mv $(CURDIR)/configure.in.unpatched $(CURDIR)/configure.in
-test -r $(CURDIR)/Makefile.in.unpatched && mv $(CURDIR)/Makefile.in.unpatched $(CURDIR)/Makefile.in
-rm -f $(CURDIR)/manage-cache.sh
-rm -f patch-stamp
[ ! -f Makefile ] || $(MAKE) distclean
dh_clean
# Update config.sub and config.guess
-test -r /usr/share/misc/config.sub && \
cp -f /usr/share/misc/config.sub config.sub
-test -r /usr/share/misc/config.guess && \
cp -f /usr/share/misc/config.guess config.guess
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/ccache.
$(MAKE) install prefix=$(CURDIR)/debian/ccache/usr
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/$(DEB_BUILD_GNU_TYPE)-gcc
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/$(DEB_BUILD_GNU_TYPE)-g++
set -e; for ver in 2.95 3.0 3.2 3.3 3.4 4.0 4.1 4.2 4.3; do \
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/$(DEB_BUILD_GNU_TYPE)-gcc-$$ver; \
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/gcc-$$ver; \
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/$(DEB_BUILD_GNU_TYPE)-g++-$$ver; \
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/g++-$$ver; \
done
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/cc
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/c++
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/gcc
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/g++
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/i586-mingw32msvc-c++
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/i586-mingw32msvc-cc
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/i586-mingw32msvc-g++
ln -s ../../bin/ccache $(CURDIR)/debian/ccache/usr/lib/ccache/i586-mingw32msvc-gcc
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installdocs
dh_installexamples
dh_installmenu
dh_installcron
dh_installman
dh_installinfo
dh_installchangelogs
dh_link
dh_strip
dh_compress
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

View File

@ -0,0 +1,43 @@
#!/bin/sh
#
# Update compiler links to ccache (in /usr/local/bin)
#
# The idea is that /usr/local/bin is ahead of /usr/bin in your PATH, so adding
# the link /usr/local/bin/cc -> /usr/bin/ccache means that it is run instead of
# /usr/bin/cc
#
# Written by: Behan Webster <behanw@websterwood.com>
#
DIRECTORY=/usr/local/bin
CCACHE=/usr/bin/ccache
CCDIR=/usr/lib/ccache
usage() {
echo "Usage: `basename $0` [--directory <dir>] [--remove]"
exit 0
}
while [ $# -gt 0 ] ; do
case "$1" in
-d*|--d*|--directory) DIRECTORY=$2; shift; shift;;
-h*|--h*|--help) usage;;
-r*|--r*|--remove) REMOVE=1; shift;;
-t*|--t*|--test) TEST=echo; shift;;
esac
done
for FILE in `cd $CCDIR; ls` ; do
LINK=$DIRECTORY/$FILE
if [ -z "$REMOVE" ] ; then
# Add link
$TEST ln -fs $CCACHE $LINK
else
# Remove link
if [ -L "$LINK" ] ; then
$TEST rm -f $LINK
fi
fi
done
# vim: sw=4 ts=4

2
CCache/debian/watch Normal file
View File

@ -0,0 +1,2 @@
version=2
http://samba.org/ftp/ccache/ccache-(.*)\.tar\.gz

287
CCache/execute.c Normal file
View File

@ -0,0 +1,287 @@
/*
Copyright (C) Andrew Tridgell 2002
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "ccache.h"
#ifdef _WIN32
char *argvtos(char **argv)
{
int i, len;
char *ptr, *str;
for (i = 0, len = 0; argv[i]; i++) {
len += strlen(argv[i]) + 3;
}
str = ptr = (char *)malloc(len + 1);
if (str == NULL)
return NULL;
for (i = 0; argv[i]; i++) {
len = strlen(argv[i]);
*ptr++ = '"';
memcpy(ptr, argv[i], len);
ptr += len;
*ptr++ = '"';
*ptr++ = ' ';
}
*ptr = 0;
return str;
}
#endif
/*
execute a compiler backend, capturing all output to the given paths
the full path to the compiler to run is in argv[0]
*/
int execute(char **argv,
const char *path_stdout,
const char *path_stderr)
{
#ifdef _WIN32
#if 1
PROCESS_INFORMATION pinfo;
STARTUPINFO sinfo;
BOOL ret;
DWORD exitcode;
char *args;
HANDLE fd_out, fd_err;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
/* TODO: needs moving after possible exit() below, but before stdout is redirected */
if (ccache_verbose) {
display_execute_args(argv);
}
fd_out = CreateFile(path_stdout, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (fd_out == INVALID_HANDLE_VALUE) {
return STATUS_NOCACHE;
}
fd_err = CreateFile(path_stderr, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (fd_err == INVALID_HANDLE_VALUE) {
return STATUS_NOCACHE;
}
ZeroMemory(&pinfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&sinfo, sizeof(STARTUPINFO));
sinfo.cb = sizeof(STARTUPINFO);
sinfo.hStdError = fd_err;
sinfo.hStdOutput = fd_out;
sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
sinfo.dwFlags |= STARTF_USESTDHANDLES;
args = argvtos(argv);
ret = CreateProcessA(argv[0], args, NULL, NULL, TRUE, 0, NULL, NULL,
&sinfo, &pinfo);
free(args);
CloseHandle(fd_out);
CloseHandle(fd_err);
if (ret == 0)
return -1;
WaitForSingleObject(pinfo.hProcess, INFINITE);
GetExitCodeProcess(pinfo.hProcess, &exitcode);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
return exitcode;
#else /* possibly slightly faster */
/* needs fixing to quote commandline options to handle spaces in CCACHE_DIR etc */
int status = -2;
int fd, std_od = -1, std_ed = -1;
/* TODO: needs moving after possible exit() below, but before stdout is redirected */
if (ccache_verbose) {
display_execute_args(argv);
}
unlink(path_stdout);
std_od = _dup(1);
fd = _open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666);
if (fd == -1) {
exit(STATUS_NOCACHE);
}
_dup2(fd, 1);
_close(fd);
unlink(path_stderr);
fd = _open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666);
std_ed = _dup(2);
if (fd == -1) {
exit(STATUS_NOCACHE);
}
_dup2(fd, 2);
_close(fd);
/* Spawn process (_exec* familly doesn't return) */
status = _spawnv(_P_WAIT, argv[0], (const char **)argv);
/* Restore descriptors */
if (std_od != -1) _dup2(std_od, 1);
if (std_ed != -1) _dup2(std_ed, 2);
_flushall();
return (status>0);
#endif
#else
pid_t pid;
int status;
pid = fork();
if (pid == -1) fatal("Failed to fork");
if (pid == 0) {
int fd;
/* TODO: needs moving after possible exit() below, but before stdout is redirected */
if (ccache_verbose) {
display_execute_args(argv);
}
unlink(path_stdout);
fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666);
if (fd == -1) {
exit(STATUS_NOCACHE);
}
dup2(fd, 1);
close(fd);
unlink(path_stderr);
fd = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666);
if (fd == -1) {
exit(STATUS_NOCACHE);
}
dup2(fd, 2);
close(fd);
exit(execv(argv[0], argv));
}
if (waitpid(pid, &status, 0) != pid) {
fatal("waitpid failed");
}
if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) {
return -1;
}
return WEXITSTATUS(status);
#endif
}
/*
find an executable by name in $PATH. Exclude any that are links to exclude_name
*/
char *find_executable(const char *name, const char *exclude_name)
{
#if _WIN32
(void)exclude_name;
DWORD ret;
char namebuf[MAX_PATH];
ret = SearchPathA(getenv("CCACHE_PATH"), name, ".exe",
sizeof(namebuf), namebuf, NULL);
if (ret != 0) {
return x_strdup(namebuf);
}
return NULL;
#else
char *path;
char *tok;
struct stat st1, st2;
if (*name == '/') {
return x_strdup(name);
}
path = getenv("CCACHE_PATH");
if (!path) {
path = getenv("PATH");
}
if (!path) {
cc_log("no PATH variable!?\n");
stats_update(STATS_ENVIRONMMENT);
return NULL;
}
path = x_strdup(path);
/* search the path looking for the first compiler of the right name
that isn't us */
for (tok=strtok(path,":"); tok; tok = strtok(NULL, ":")) {
char *fname;
x_asprintf(&fname, "%s/%s", tok, name);
/* look for a normal executable file */
if (access(fname, X_OK) == 0 &&
lstat(fname, &st1) == 0 &&
stat(fname, &st2) == 0 &&
S_ISREG(st2.st_mode)) {
/* if its a symlink then ensure it doesn't
point at something called exclude_name */
if (S_ISLNK(st1.st_mode)) {
char *buf = x_realpath(fname);
if (buf) {
char *p = str_basename(buf);
if (strcmp(p, exclude_name) == 0) {
/* its a link to "ccache" ! */
free(p);
free(buf);
continue;
}
free(buf);
free(p);
}
}
/* found it! */
free(path);
return fname;
}
free(fname);
}
free(path);
return NULL;
#endif
}
void display_execute_args(char **argv)
{
if (argv) {
printf("ccache executing: ");
while (*argv) {
printf("%s ", *argv);
++argv;
}
printf("\n");
fflush(stdout);
}
}

80
CCache/hash.c Normal file
View File

@ -0,0 +1,80 @@
/*
Copyright (C) Andrew Tridgell 2002
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
simple front-end functions to mdfour code
*/
#include "ccache.h"
static struct mdfour md;
void hash_buffer(const char *s, int len)
{
mdfour_update(&md, (unsigned char *)s, len);
}
void hash_start(void)
{
mdfour_begin(&md);
}
void hash_string(const char *s)
{
hash_buffer(s, strlen(s));
}
void hash_int(int x)
{
hash_buffer((char *)&x, sizeof(x));
}
/* add contents of a file to the hash */
void hash_file(const char *fname)
{
char buf[1024];
int fd, n;
fd = open(fname, O_RDONLY|O_BINARY);
if (fd == -1) {
cc_log("Failed to open %s\n", fname);
fatal("hash_file");
}
while ((n = read(fd, buf, sizeof(buf))) > 0) {
hash_buffer(buf, n);
}
close(fd);
}
/* return the hash result as a static string */
char *hash_result(void)
{
unsigned char sum[16];
static char ret[53];
int i;
hash_buffer(NULL, 0);
mdfour_result(&md, sum);
for (i=0;i<16;i++) {
sprintf(&ret[i*2], "%02x", (unsigned)sum[i]);
}
sprintf(&ret[i*2], "-%u", (unsigned)md.totalN);
return ret;
}

238
CCache/install-sh Executable file
View File

@ -0,0 +1,238 @@
#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
#
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

284
CCache/mdfour.c Normal file
View File

@ -0,0 +1,284 @@
/*
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "ccache.h"
/* NOTE: This code makes no attempt to be fast!
It assumes that a int is at least 32 bits long
*/
static struct mdfour *m;
#define MASK32 (0xffffffff)
#define F(X,Y,Z) ((((X)&(Y)) | ((~(X))&(Z))))
#define G(X,Y,Z) ((((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))))
#define H(X,Y,Z) (((X)^(Y)^(Z)))
#define lshift(x,s) (((((x)<<(s))&MASK32) | (((x)>>(32-(s)))&MASK32)))
#define ROUND1(a,b,c,d,k,s) a = lshift((a + F(b,c,d) + M[k])&MASK32, s)
#define ROUND2(a,b,c,d,k,s) a = lshift((a + G(b,c,d) + M[k] + 0x5A827999)&MASK32,s)
#define ROUND3(a,b,c,d,k,s) a = lshift((a + H(b,c,d) + M[k] + 0x6ED9EBA1)&MASK32,s)
/* this applies md4 to 64 byte chunks */
static void mdfour64(uint32 *M)
{
uint32 AA, BB, CC, DD;
uint32 A,B,C,D;
A = m->A; B = m->B; C = m->C; D = m->D;
AA = A; BB = B; CC = C; DD = D;
ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
A += AA; B += BB;
C += CC; D += DD;
A &= MASK32; B &= MASK32;
C &= MASK32; D &= MASK32;
m->A = A; m->B = B; m->C = C; m->D = D;
}
static void copy64(uint32 *M, const unsigned char *in)
{
int i;
for (i=0;i<16;i++)
M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
(in[i*4+1]<<8) | (in[i*4+0]<<0);
}
static void copy4(unsigned char *out,uint32 x)
{
out[0] = x&0xFF;
out[1] = (x>>8)&0xFF;
out[2] = (x>>16)&0xFF;
out[3] = (x>>24)&0xFF;
}
void mdfour_begin(struct mdfour *md)
{
md->A = 0x67452301;
md->B = 0xefcdab89;
md->C = 0x98badcfe;
md->D = 0x10325476;
md->totalN = 0;
md->tail_len = 0;
}
static void mdfour_tail(const unsigned char *in, int n)
{
unsigned char buf[128];
uint32 M[16];
uint32 b;
m->totalN += n;
b = m->totalN * 8;
memset(buf, 0, 128);
if (n) memcpy(buf, in, n);
buf[n] = 0x80;
if (n <= 55) {
copy4(buf+56, b);
copy64(M, buf);
mdfour64(M);
} else {
copy4(buf+120, b);
copy64(M, buf);
mdfour64(M);
copy64(M, buf+64);
mdfour64(M);
}
}
void mdfour_update(struct mdfour *md, const unsigned char *in, int n)
{
uint32 M[16];
m = md;
if (in == NULL) {
mdfour_tail(md->tail, md->tail_len);
return;
}
if (md->tail_len) {
int len = 64 - md->tail_len;
if (len > n) len = n;
memcpy(md->tail+md->tail_len, in, len);
md->tail_len += len;
n -= len;
in += len;
if (md->tail_len == 64) {
copy64(M, md->tail);
mdfour64(M);
m->totalN += 64;
md->tail_len = 0;
}
}
while (n >= 64) {
copy64(M, in);
mdfour64(M);
in += 64;
n -= 64;
m->totalN += 64;
}
if (n) {
memcpy(md->tail, in, n);
md->tail_len = n;
}
}
void mdfour_result(struct mdfour *md, unsigned char *out)
{
m = md;
copy4(out, m->A);
copy4(out+4, m->B);
copy4(out+8, m->C);
copy4(out+12, m->D);
}
void mdfour(unsigned char *out, const unsigned char *in, int n)
{
struct mdfour md;
mdfour_begin(&md);
mdfour_update(&md, in, n);
mdfour_update(&md, NULL, 0);
mdfour_result(&md, out);
}
#ifdef TEST_MDFOUR
static void file_checksum1(char *fname)
{
int fd, i;
struct mdfour md;
unsigned char buf[1024], sum[16];
unsigned chunk;
fd = open(fname,O_RDONLY|O_BINARY);
if (fd == -1) {
perror("fname");
exit(1);
}
chunk = 1 + random() % (sizeof(buf) - 1);
mdfour_begin(&md);
while (1) {
int n = read(fd, buf, chunk);
if (n >= 0) {
mdfour_update(&md, buf, n);
}
if (n < chunk) break;
}
close(fd);
mdfour_update(&md, NULL, 0);
mdfour_result(&md, sum);
for (i=0;i<16;i++)
printf("%02x", sum[i]);
printf("\n");
}
#if 0
#include "../md4.h"
static void file_checksum2(char *fname)
{
int fd, i;
MDstruct md;
unsigned char buf[64], sum[16];
fd = open(fname,O_RDONLY|O_BINARY);
if (fd == -1) {
perror("fname");
exit(1);
}
MDbegin(&md);
while (1) {
int n = read(fd, buf, sizeof(buf));
if (n <= 0) break;
MDupdate(&md, buf, n*8);
}
if (!md.done) {
MDupdate(&md, buf, 0);
}
close(fd);
memcpy(sum, md.buffer, 16);
for (i=0;i<16;i++)
printf("%02x", sum[i]);
printf("\n");
}
#endif
int main(int argc, char *argv[])
{
file_checksum1(argv[1]);
#if 0
file_checksum2(argv[1]);
#endif
return 0;
}
#endif

36
CCache/mdfour.h Normal file
View File

@ -0,0 +1,36 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
struct mdfour {
uint32 A, B, C, D;
uint32 totalN;
unsigned char tail[64];
unsigned tail_len;
};
void mdfour_begin(struct mdfour *md);
void mdfour_update(struct mdfour *md, const unsigned char *in, int n);
void mdfour_result(struct mdfour *md, unsigned char *out);
void mdfour(unsigned char *out, const unsigned char *in, int n);

5
CCache/packaging/README Normal file
View File

@ -0,0 +1,5 @@
These packaging files are contributd by users of ccache. I do not
maintain them, and they may well need updating before you use them.
I don't distribute binary packages of ccache myself, but if you wish
to add ccache to a distribution then that's OK

View File

@ -0,0 +1,37 @@
Summary: Compiler Cache
Name: ccache
Version: 2.3
Release: 1
Group: Development/Languages
License: GPL
URL: http://ccache.samba.org/
Source: ccache-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-root
%description
ccache caches gcc output files
%prep
%setup -q
%build
%configure
make
install -d -m 0755 $RPM_BUILD_ROOT%{_bindir}
install -m 0755 ccache $RPM_BUILD_ROOT%{_bindir}
install -d -m 0755 $RPM_BUILD_ROOT%{_mandir}/man1
install -m 0644 ccache.1 $RPM_BUILD_ROOT%{_mandir}/man1
%files
%defattr(-,root,root)
%doc README
%{_mandir}/man1/ccache.1*
%{_bindir}/ccache
%clean
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
%changelog
* Mon Apr 01 2002 Peter Jones <pjones@redhat.com>
- Created the package

965
CCache/snprintf.c Normal file
View File

@ -0,0 +1,965 @@
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
* on all source code distributions
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* More Recently:
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything
* from the normal C string format, at least as far as I can tell from
* the Solaris 2.5 printf(3S) man page.
*
* Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
* Ok, added some minimal floating point support, which means this
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
* which showed it, so that's been fixed. Also, formated the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
*
* Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
* The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
* The original code assumed that both snprintf() and vsnprintf() were
* missing. Some systems only have snprintf() but not vsnprintf(), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* Andrew Tridgell (tridge@samba.org) Oct 1998
* fixed handling of %.0f
* added test for HAVE_LONG_DOUBLE
*
* tridge@samba.org, idra@samba.org, April 2001
* got rid of fcvt code (twas buggy and made testing harder)
* added C99 semantics
*
**************************************************************/
#ifndef NO_CONFIG_H /* for some tests */
#include "config.h"
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
#include <sys/types.h>
#include <stdarg.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF)
/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
#include <stdio.h>
/* make the compiler happy with an empty file */
void dummy_snprintf(void) {}
#else
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
#else
#define LDOUBLE double
#endif
#ifdef HAVE_LONG_LONG
#define LLONG long long
#else
#define LLONG long
#endif
static size_t dopr(char *buffer, size_t maxlen, const char *format,
va_list args);
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
/*
* dopr(): poor man's version of doprintf
*/
/* format read states */
#define DP_S_DEFAULT 0
#define DP_S_FLAGS 1
#define DP_S_MIN 2
#define DP_S_DOT 3
#define DP_S_MAX 4
#define DP_S_MOD 5
#define DP_S_CONV 6
#define DP_S_DONE 7
/* format flags - Bits */
#define DP_F_MINUS (1 << 0)
#define DP_F_PLUS (1 << 1)
#define DP_F_SPACE (1 << 2)
#define DP_F_NUM (1 << 3)
#define DP_F_ZERO (1 << 4)
#define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
#define DP_C_SHORT 1
#define DP_C_LONG 2
#define DP_C_LDOUBLE 3
#define DP_C_LLONG 4
#define char_to_int(p) ((p)- '0')
#ifndef MAX
#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args)
{
char ch;
LLONG value;
LDOUBLE fvalue;
char *strvalue;
int min;
int max;
int state;
int flags;
int cflags;
size_t currlen;
state = DP_S_DEFAULT;
currlen = flags = cflags = min = 0;
max = -1;
ch = *format++;
while (state != DP_S_DONE) {
if (ch == '\0')
state = DP_S_DONE;
switch(state) {
case DP_S_DEFAULT:
if (ch == '%')
state = DP_S_FLAGS;
else
dopr_outch (buffer, &currlen, maxlen, ch);
ch = *format++;
break;
case DP_S_FLAGS:
switch (ch) {
case '-':
flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
flags |= DP_F_ZERO;
ch = *format++;
break;
default:
state = DP_S_MIN;
break;
}
break;
case DP_S_MIN:
if (isdigit((unsigned char)ch)) {
min = 10*min + char_to_int (ch);
ch = *format++;
} else if (ch == '*') {
min = va_arg (args, int);
ch = *format++;
state = DP_S_DOT;
} else {
state = DP_S_DOT;
}
break;
case DP_S_DOT:
if (ch == '.') {
state = DP_S_MAX;
ch = *format++;
} else {
state = DP_S_MOD;
}
break;
case DP_S_MAX:
if (isdigit((unsigned char)ch)) {
if (max < 0)
max = 0;
max = 10*max + char_to_int (ch);
ch = *format++;
} else if (ch == '*') {
max = va_arg (args, int);
ch = *format++;
state = DP_S_MOD;
} else {
state = DP_S_MOD;
}
break;
case DP_S_MOD:
switch (ch) {
case 'h':
cflags = DP_C_SHORT;
ch = *format++;
break;
case 'l':
cflags = DP_C_LONG;
ch = *format++;
if (ch == 'l') { /* It's a long long */
cflags = DP_C_LLONG;
ch = *format++;
}
break;
case 'L':
cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
break;
}
state = DP_S_CONV;
break;
case DP_S_CONV:
switch (ch) {
case 'd':
case 'i':
if (cflags == DP_C_SHORT)
value = va_arg (args, int);
else if (cflags == DP_C_LONG)
value = va_arg (args, long int);
else if (cflags == DP_C_LLONG)
value = va_arg (args, LLONG);
else
value = va_arg (args, int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (long)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
break;
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'X':
flags |= DP_F_UP;
/* FALLTHROUGH */
case 'x':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
break;
case 'f':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
/* um, floating point? */
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'E':
flags |= DP_F_UP;
/* FALLTHROUGH */
case 'e':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
break;
case 'G':
flags |= DP_F_UP;
/* FALLTHROUGH */
case 'g':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
break;
case 'c':
dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
break;
case 's':
strvalue = va_arg (args, char *);
if (!strvalue) strvalue = "(NULL)";
if (max == -1) {
max = strlen(strvalue);
}
if (min > 0 && max >= 0 && min > max) max = min;
fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
break;
case 'p':
strvalue = (char *)va_arg(args, void *);
fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
break;
case 'n':
if (cflags == DP_C_SHORT) {
short int *num;
num = va_arg (args, short int *);
*num = currlen;
} else if (cflags == DP_C_LONG) {
long int *num;
num = va_arg (args, long int *);
*num = (long int)currlen;
} else if (cflags == DP_C_LLONG) {
LLONG *num;
num = va_arg (args, LLONG *);
*num = (LLONG)currlen;
} else {
int *num;
num = va_arg (args, int *);
*num = currlen;
}
break;
case '%':
dopr_outch (buffer, &currlen, maxlen, ch);
break;
case 'w':
/* not supported yet, treat as next char */
ch = *format++;
break;
default:
/* Unknown, skip */
break;
}
ch = *format++;
state = DP_S_DEFAULT;
flags = cflags = min = 0;
max = -1;
break;
case DP_S_DONE:
break;
default:
/* hmm? */
break; /* some picky compilers need this */
}
}
if (maxlen != 0) {
if (currlen < maxlen - 1)
buffer[currlen] = '\0';
else if (maxlen > 0)
buffer[maxlen - 1] = '\0';
}
return currlen;
}
static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max)
{
int padlen, strln; /* amount to pad */
int cnt = 0;
#ifdef DEBUG_SNPRINTF
printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
#endif
if (value == 0) {
value = "<NULL>";
}
for (strln = 0; value[strln]; ++strln); /* strlen */
padlen = min - strln;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
while ((padlen > 0) && (cnt < max)) {
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
++cnt;
}
while (*value && (cnt < max)) {
dopr_outch (buffer, currlen, maxlen, *value++);
++cnt;
}
while ((padlen < 0) && (cnt < max)) {
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
++cnt;
}
}
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags)
{
int signvalue = 0;
unsigned long uvalue;
char convert[20];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
int caps = 0;
if (max < 0)
max = 0;
uvalue = value;
if(!(flags & DP_F_UNSIGNED)) {
if( value < 0 ) {
signvalue = '-';
uvalue = -value;
} else {
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else if (flags & DP_F_SPACE)
signvalue = ' ';
}
}
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
do {
convert[place++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base );
} while(uvalue && (place < 20));
if (place == 20) place--;
convert[place] = 0;
zpadlen = max - place;
spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
if (zpadlen < 0) zpadlen = 0;
if (spadlen < 0) spadlen = 0;
if (flags & DP_F_ZERO) {
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
if (flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
zpadlen, spadlen, min, max, place);
#endif
/* Spaces */
while (spadlen > 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
--spadlen;
}
/* Sign */
if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
/* Zeros */
if (zpadlen > 0) {
while (zpadlen > 0) {
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
}
/* Digits */
while (place > 0)
dopr_outch (buffer, currlen, maxlen, convert[--place]);
/* Left Justified spaces */
while (spadlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++spadlen;
}
}
static LDOUBLE abs_val(LDOUBLE value)
{
LDOUBLE result = value;
if (value < 0)
result = -value;
return result;
}
static LDOUBLE POW10(int exp)
{
LDOUBLE result = 1;
while (exp) {
result *= 10;
exp--;
}
return result;
}
static LLONG ROUND(LDOUBLE value)
{
LLONG intpart;
intpart = (LLONG)value;
value = value - intpart;
if (value >= 0.5) intpart++;
return intpart;
}
/* a replacement for modf that doesn't need the math library. Should
be portable, but slow */
static double my_modf(double x0, double *iptr)
{
int i;
long l;
double x = x0;
double f = 1.0;
for (i=0;i<100;i++) {
l = (long)x;
if (l <= (x+1) && l >= (x-1)) break;
x *= 0.1;
f *= 10.0;
}
if (i == 100) {
/* yikes! the number is beyond what we can handle. What do we do? */
(*iptr) = 0;
return 0;
}
if (i != 0) {
double i2;
double ret;
ret = my_modf(x0-l*f, &i2);
(*iptr) = l*f + i2;
return ret;
}
(*iptr) = l;
return x - (*iptr);
}
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags)
{
int signvalue = 0;
double ufvalue;
char iconvert[311];
char fconvert[311];
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
int caps = 0;
int index;
double intpart;
double fracpart;
double temp;
/*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
if (max < 0)
max = 6;
ufvalue = abs_val (fvalue);
if (fvalue < 0) {
signvalue = '-';
} else {
if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
signvalue = '+';
} else {
if (flags & DP_F_SPACE)
signvalue = ' ';
}
}
#if 0
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif
#if 0
if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
#endif
/*
* Sorry, we only support 16 digits past the decimal because of our
* conversion method
*/
if (max > 16)
max = 16;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
temp = ufvalue;
my_modf(temp, &intpart);
fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
if (fracpart >= POW10(max)) {
intpart++;
fracpart -= POW10(max);
}
/* Convert integer part */
do {
temp = intpart;
my_modf(intpart*0.1, &intpart);
temp = temp*0.1;
index = (int) ((temp -intpart +0.05)* 10.0);
/* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
/* printf ("%llf, %f, %x\n", temp, intpart, index); */
iconvert[iplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[index];
} while (intpart && (iplace < 311));
if (iplace == 311) iplace--;
iconvert[iplace] = 0;
/* Convert fractional part */
if (fracpart)
{
do {
temp = fracpart;
my_modf(fracpart*0.1, &fracpart);
temp = temp*0.1;
index = (int) ((temp -fracpart +0.05)* 10.0);
/* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
/* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
fconvert[fplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[index];
} while(fracpart && (fplace < 311));
if (fplace == 311) fplace--;
}
fconvert[fplace] = 0;
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if (zpadlen < 0) zpadlen = 0;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if ((flags & DP_F_ZERO) && (padlen > 0)) {
if (signvalue) {
dopr_outch (buffer, currlen, maxlen, signvalue);
--padlen;
signvalue = 0;
}
while (padlen > 0) {
dopr_outch (buffer, currlen, maxlen, '0');
--padlen;
}
}
while (padlen > 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
}
if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
while (iplace > 0)
dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
#ifdef DEBUG_SNPRINTF
printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
#endif
/*
* Decimal point. This should probably use locale to find the correct
* char to print out.
*/
if (max > 0) {
dopr_outch (buffer, currlen, maxlen, '.');
while (fplace > 0)
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
}
while (zpadlen > 0) {
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
while (padlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
}
}
static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
{
if (*currlen < maxlen) {
buffer[(*currlen)] = c;
}
(*currlen)++;
}
/* yes this really must be a ||. Don't muck with this (tridge) */
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
}
#endif
/* yes this really must be a ||. Don't muck wiith this (tridge)
*
* The logic for these two is that we need our own definition if the
* OS *either* has no definition of *sprintf, or if it does have one
* that doesn't work properly according to the autoconf test. Perhaps
* these should really be smb_snprintf to avoid conflicts with buggy
* linkers? -- mbp
*/
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_SNPRINTF)
int snprintf(char *str,size_t count,const char *fmt,...)
{
size_t ret;
va_list ap;
va_start(ap, fmt);
ret = vsnprintf(str, count, fmt, ap);
va_end(ap);
return ret;
}
#endif
#endif
#ifndef HAVE_VASPRINTF
int vasprintf(char **ptr, const char *format, va_list ap)
{
int ret;
ret = vsnprintf(0, 0, format, ap);
if (ret <= 0) return ret;
(*ptr) = (char *)malloc(ret+1);
if (!*ptr) return -1;
ret = vsnprintf(*ptr, ret+1, format, ap);
return ret;
}
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format, ...)
{
va_list ap;
int ret;
*ptr = 0;
va_start(ap, format);
ret = vasprintf(ptr, format, ap);
va_end(ap);
return ret;
}
#endif
#ifndef HAVE_VSYSLOG
#ifdef HAVE_SYSLOG
void vsyslog (int facility_priority, char *format, va_list arglist)
{
char *msg = 0;
vasprintf(&msg, format, arglist);
if (!msg)
return;
syslog(facility_priority, "%s", msg);
free(msg);
}
#endif /* HAVE_SYSLOG */
#endif /* HAVE_VSYSLOG */
#ifdef TEST_SNPRINTF
int sprintf(char *str,const char *fmt,...);
int main (void)
{
char buf1[1024];
char buf2[1024];
char *fp_fmt[] = {
"%1.1f",
"%-1.5f",
"%1.5f",
"%123.9f",
"%10.5f",
"% 10.5f",
"%+22.9f",
"%+4.9f",
"%01.3f",
"%4f",
"%3.1f",
"%3.2f",
"%.0f",
"%f",
"-16.16f",
0
};
double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 0};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
"%123.9d",
"%5.5d",
"%10.5d",
"% 10.5d",
"%+22.33d",
"%01.3d",
"%4d",
"%d",
0
};
long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
char *str_fmt[] = {
"10.5s",
"5.10s",
"10.1s",
"0.10s",
"10.0s",
"1.10s",
"%s",
"%.1s",
"%.10s",
"%10s",
0
};
char *str_vals[] = {"hello", "a", "", "a longer string", 0};
int x, y;
int fail = 0;
int num = 0;
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] ; x++) {
for (y = 0; fp_nums[y] != 0 ; y++) {
int l1 = snprintf(0, 0, fp_fmt[x], fp_nums[y]);
int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
sprintf (buf2, fp_fmt[x], fp_nums[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
fp_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]);
fail++;
}
num++;
}
}
for (x = 0; int_fmt[x] ; x++) {
for (y = 0; int_nums[y] != 0 ; y++) {
int l1 = snprintf(0, 0, int_fmt[x], int_nums[y]);
int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
sprintf (buf2, int_fmt[x], int_nums[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
int_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]);
fail++;
}
num++;
}
}
for (x = 0; str_fmt[x] ; x++) {
for (y = 0; str_vals[y] != 0 ; y++) {
int l1 = snprintf(0, 0, str_fmt[x], str_vals[y]);
int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
sprintf (buf2, str_fmt[x], str_vals[y]);
if (strcmp (buf1, buf2)) {
printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
str_fmt[x], buf1, buf2);
fail++;
}
if (l1 != l2) {
printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);
fail++;
}
num++;
}
}
printf ("%d tests failed out of %d.\n", fail, num);
printf("seeing how many digits we support\n");
{
double v0 = 0.12345678901234567890123456789012345678901;
for (x=0; x<100; x++) {
snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x));
sprintf(buf2, "%1.1f", v0*pow(10, x));
if (strcmp(buf1, buf2)) {
printf("we seem to support %d digits\n", x-1);
break;
}
}
}
return 0;
}
#endif /* SNPRINTF_TEST */

365
CCache/stats.c Normal file
View File

@ -0,0 +1,365 @@
/*
Copyright (C) Andrew Tridgell 2002
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
routines to handle the stats files
the stats file is stored one per cache subdirectory to make this more
scalable
*/
#include "ccache.h"
extern char *stats_file;
extern char *cache_dir;
#define STATS_VERSION 1
#define FLAG_NOZERO 1 /* don't zero with the -z option */
#define FLAG_ALWAYS 2 /* always show, even if zero */
static struct {
enum stats stat;
char *message;
void (*fn)(unsigned );
unsigned flags;
} stats_info[] = {
{ STATS_CACHED, "cache hit ", NULL, FLAG_ALWAYS },
{ STATS_TOCACHE, "cache miss ", NULL, FLAG_ALWAYS },
{ STATS_LINK, "called for link ", NULL, 0 },
{ STATS_MULTIPLE, "multiple source files ", NULL, 0 },
{ STATS_STDOUT, "compiler produced stdout ", NULL, 0 },
{ STATS_STATUS, "compile failed ", NULL, 0 },
{ STATS_ERROR, "ccache internal error ", NULL, 0 },
{ STATS_PREPROCESSOR, "preprocessor error ", NULL, 0 },
{ STATS_COMPILER, "couldn't find the compiler ", NULL, 0 },
{ STATS_MISSING, "cache file missing ", NULL, 0 },
{ STATS_ARGS, "bad compiler arguments ", NULL, 0 },
{ STATS_NOTC, "not a C/C++ file ", NULL, 0 },
{ STATS_CONFTEST, "autoconf compile/link ", NULL, 0 },
{ STATS_UNSUPPORTED, "unsupported compiler option ", NULL, 0 },
{ STATS_OUTSTDOUT, "output to stdout ", NULL, 0 },
{ STATS_DEVICE, "output to a non-regular file ", NULL, 0 },
{ STATS_NOINPUT, "no input file ", NULL, 0 },
{ STATS_ENVIRONMMENT, "error due to bad env variable ", NULL, 0 },
{ STATS_NUMFILES, "files in cache ", NULL, FLAG_NOZERO|FLAG_ALWAYS },
{ STATS_TOTALSIZE, "cache size ", display_size , FLAG_NOZERO|FLAG_ALWAYS },
{ STATS_MAXFILES, "max files ", NULL, FLAG_NOZERO },
{ STATS_MAXSIZE, "max cache size ", display_size, FLAG_NOZERO },
{ STATS_NONE, NULL, NULL, 0 }
};
/* parse a stats file from a buffer - adding to the counters */
static void parse_stats(unsigned counters[STATS_END], char *buf)
{
int i;
char *p, *p2;
p = buf;
for (i=0;i<STATS_END;i++) {
counters[i] += strtol(p, &p2, 10);
if (!p2 || p2 == p) break;
p = p2;
}
}
/* write out a stats file */
static void write_stats(int fd, unsigned counters[STATS_END])
{
int i;
int len = 0;
char buf[1024];
for (i=0;i<STATS_END;i++) {
len += snprintf(buf+len, sizeof(buf)-(len+1), "%u ", counters[i]);
if (len >= (int)sizeof(buf)-1) fatal("stats too long?!");
}
len += snprintf(buf+len, sizeof(buf)-(len+1), "\n");
if (len >= (int)sizeof(buf)-1) fatal("stats too long?!");
lseek(fd, 0, SEEK_SET);
if (write(fd, buf, len) == -1) fatal("could not write stats");
}
/* fill in some default stats values */
static void stats_default(unsigned counters[STATS_END])
{
counters[STATS_MAXSIZE] += DEFAULT_MAXSIZE / 16;
}
/* read in the stats from one dir and add to the counters */
static void stats_read_fd(int fd, unsigned counters[STATS_END])
{
char buf[1024];
int len;
len = read(fd, buf, sizeof(buf)-1);
if (len <= 0) {
stats_default(counters);
return;
}
buf[len] = 0;
parse_stats(counters, buf);
}
/* update the stats counter for this compile */
static void stats_update_size(enum stats stat, size_t size, size_t numfiles)
{
int fd;
unsigned counters[STATS_END];
int need_cleanup = 0;
if (getenv("CCACHE_NOSTATS")) return;
if (!stats_file) {
if (!cache_dir) return;
x_asprintf(&stats_file, "%s/stats", cache_dir);
}
/* open safely to try to prevent symlink races */
fd = safe_open(stats_file);
/* still can't get it? don't bother ... */
if (fd == -1) return;
memset(counters, 0, sizeof(counters));
if (lock_fd(fd) != 0) {
close(fd);
return;
}
/* read in the old stats */
stats_read_fd(fd, counters);
/* update them */
counters[stat]++;
/* on a cache miss we up the file count and size */
if (stat == STATS_TOCACHE) {
counters[STATS_NUMFILES] += numfiles;
counters[STATS_TOTALSIZE] += size;
}
/* and write them out */
write_stats(fd, counters);
close(fd);
/* we might need to cleanup if the cache has now got too big */
if (counters[STATS_MAXFILES] != 0 &&
counters[STATS_NUMFILES] > counters[STATS_MAXFILES]) {
need_cleanup = 1;
}
if (counters[STATS_MAXSIZE] != 0 &&
counters[STATS_TOTALSIZE] > counters[STATS_MAXSIZE]) {
need_cleanup = 1;
}
if (need_cleanup) {
char *p = dirname(stats_file);
cleanup_dir(p, counters[STATS_MAXFILES], counters[STATS_MAXSIZE],
numfiles);
free(p);
}
}
/* record a cache miss */
void stats_tocache(size_t size, size_t numfiles)
{
/* convert size to kilobytes */
size = size / 1024;
stats_update_size(STATS_TOCACHE, size, numfiles);
}
/* update a normal stat */
void stats_update(enum stats stat)
{
stats_update_size(stat, 0, 0);
}
/* read in the stats from one dir and add to the counters */
void stats_read(const char *stats_file, unsigned counters[STATS_END])
{
int fd;
fd = open(stats_file, O_RDONLY|O_BINARY);
if (fd == -1) {
stats_default(counters);
return;
}
lock_fd(fd);
stats_read_fd(fd, counters);
close(fd);
}
/* sum and display the total stats for all cache dirs */
void stats_summary(void)
{
int dir, i;
unsigned counters[STATS_END];
memset(counters, 0, sizeof(counters));
/* add up the stats in each directory */
for (dir=-1;dir<=0xF;dir++) {
char *fname;
if (dir == -1) {
x_asprintf(&fname, "%s/stats", cache_dir);
} else {
x_asprintf(&fname, "%s/%1x/stats", cache_dir, dir);
}
stats_read(fname, counters);
free(fname);
/* oh what a nasty hack ... */
if (dir == -1) {
counters[STATS_MAXSIZE] = 0;
}
}
printf("cache directory %s\n", cache_dir);
/* and display them */
for (i=0;stats_info[i].message;i++) {
enum stats stat = stats_info[i].stat;
if (counters[stat] == 0 &&
!(stats_info[i].flags & FLAG_ALWAYS)) {
continue;
}
printf("%s ", stats_info[i].message);
if (stats_info[i].fn) {
stats_info[i].fn(counters[stat]);
printf("\n");
} else {
printf("%8u\n", counters[stat]);
}
}
}
/* zero all the stats structures */
void stats_zero(void)
{
int dir, fd;
unsigned i;
char *fname;
unsigned counters[STATS_END];
x_asprintf(&fname, "%s/stats", cache_dir);
unlink(fname);
free(fname);
for (dir=0;dir<=0xF;dir++) {
x_asprintf(&fname, "%s/%1x/stats", cache_dir, dir);
fd = safe_open(fname);
if (fd == -1) {
free(fname);
continue;
}
memset(counters, 0, sizeof(counters));
lock_fd(fd);
stats_read_fd(fd, counters);
for (i=0;stats_info[i].message;i++) {
if (!(stats_info[i].flags & FLAG_NOZERO)) {
counters[stats_info[i].stat] = 0;
}
}
write_stats(fd, counters);
close(fd);
free(fname);
}
}
/* set the per directory limits */
int stats_set_limits(long maxfiles, long maxsize)
{
int dir;
unsigned counters[STATS_END];
if (maxfiles != -1) {
maxfiles /= 16;
}
if (maxsize != -1) {
maxsize /= 16;
}
if (create_dir(cache_dir) != 0) {
return 1;
}
/* set the limits in each directory */
for (dir=0;dir<=0xF;dir++) {
char *fname, *cdir;
int fd;
x_asprintf(&cdir, "%s/%1x", cache_dir, dir);
if (create_dir(cdir) != 0) {
return 1;
}
x_asprintf(&fname, "%s/stats", cdir);
free(cdir);
memset(counters, 0, sizeof(counters));
fd = safe_open(fname);
if (fd != -1) {
lock_fd(fd);
stats_read_fd(fd, counters);
if (maxfiles != -1) {
counters[STATS_MAXFILES] = maxfiles;
}
if (maxsize != -1) {
counters[STATS_MAXSIZE] = maxsize;
}
write_stats(fd, counters);
close(fd);
}
free(fname);
}
return 0;
}
/* set the per directory sizes */
void stats_set_sizes(const char *dir, size_t num_files, size_t total_size)
{
int fd;
unsigned counters[STATS_END];
char *stats_file;
create_dir(dir);
x_asprintf(&stats_file, "%s/stats", dir);
memset(counters, 0, sizeof(counters));
fd = safe_open(stats_file);
if (fd != -1) {
lock_fd(fd);
stats_read_fd(fd, counters);
counters[STATS_NUMFILES] = num_files;
counters[STATS_TOTALSIZE] = total_size;
write_stats(fd, counters);
close(fd);
}
free(stats_file);
}

491
CCache/test.sh Executable file
View File

@ -0,0 +1,491 @@
#!/bin/sh
# a simple test suite for ccache
# tridge@samba.org
if test -n "$CC"; then
COMPILER="$CC"
else
COMPILER=cc
fi
if test -n "$SWIG"; then
SWIG="$SWIG"
else
SWIG=swig
fi
# fix: Remove ccache from $PATH if it exists
# as it will influence the unit tests
PATH="`echo $PATH | \
sed -e 's!:/usr\(/local\)*/lib\([0-9]\)*/ccache\(/\)*!!g'`"
if test -n "$CCACHE"; then
CCACHE="$CCACHE"
else
CCACHE=../ccache-swig
fi
TESTDIR=test.$$
test_failed() {
reason="$1"
echo $1
$CCACHE -s
cd ..
rm -rf $TESTDIR
echo TEST FAILED
exit 1
}
randcode() {
outfile="$1"
nlines=$2
i=0;
(
while [ $i -lt $nlines ]; do
echo "int foo$nlines$i(int x) { return x; }"
i=`expr $i + 1`
done
) >> "$outfile"
}
genswigcode() {
outfile="$1"
nlines=$2
i=0;
(
echo "%module swigtest$2;"
while [ $i -lt $nlines ]; do
echo "int foo$nlines$i(int x);"
echo "struct Bar$nlines$i { int y; };"
i=`expr $i + 1`
done
) >> "$outfile"
}
getstat() {
stat="$1"
value=`$CCACHE -s | grep "$stat" | cut -c34-40`
echo $value
}
checkstat() {
stat="$1"
expected_value="$2"
value=`getstat "$stat"`
# echo "exp: $expected_value got: $value $testname"
if [ "$expected_value" != "$value" ]; then
test_failed "SUITE: $testsuite TEST: $testname - Expected $stat to be $expected_value got $value"
fi
}
basetests() {
echo "starting testsuite $testsuite"
rm -rf "$CCACHE_DIR"
checkstat 'cache hit' 0
checkstat 'cache miss' 0
j=1
rm -f *.c
while [ $j -lt 32 ]; do
randcode test$j.c $j
j=`expr $j + 1`
done
testname="BASIC"
$CCACHE_COMPILE -c test1.c
checkstat 'cache hit' 0
checkstat 'cache miss' 1
testname="BASIC2"
$CCACHE_COMPILE -c test1.c
checkstat 'cache hit' 1
checkstat 'cache miss' 1
testname="debug"
$CCACHE_COMPILE -c test1.c -g
checkstat 'cache hit' 1
checkstat 'cache miss' 2
testname="debug2"
$CCACHE_COMPILE -c test1.c -g
checkstat 'cache hit' 2
checkstat 'cache miss' 2
testname="output"
$CCACHE_COMPILE -c test1.c -o foo.o
checkstat 'cache hit' 3
checkstat 'cache miss' 2
testname="link"
$CCACHE_COMPILE test1.c -o test 2> /dev/null
checkstat 'called for link' 1
testname="multiple"
$CCACHE_COMPILE -c test1.c test2.c
checkstat 'multiple source files' 1
testname="find"
$CCACHE blahblah -c test1.c 2> /dev/null
checkstat "couldn't find the compiler" 1
testname="bad"
$CCACHE_COMPILE -c test1.c -I 2> /dev/null
checkstat 'bad compiler arguments' 1
testname="c/c++"
ln -f test1.c test1.ccc
$CCACHE_COMPILE -c test1.ccc 2> /dev/null
checkstat 'not a C/C++ file' 1
testname="unsupported"
$CCACHE_COMPILE -M foo -c test1.c > /dev/null 2>&1
checkstat 'unsupported compiler option' 1
testname="stdout"
$CCACHE echo foo -c test1.c > /dev/null
checkstat 'compiler produced stdout' 1
testname="non-regular"
mkdir testd
$CCACHE_COMPILE -o testd -c test1.c > /dev/null 2>&1
rm -rf testd
checkstat 'output to a non-regular file' 1
testname="no-input"
$CCACHE_COMPILE -c -O2 2> /dev/null
checkstat 'no input file' 1
testname="CCACHE_DISABLE"
CCACHE_DISABLE=1 $CCACHE_COMPILE -c test1.c 2> /dev/null
checkstat 'cache hit' 3
$CCACHE_COMPILE -c test1.c
checkstat 'cache hit' 4
testname="CCACHE_CPP2"
CCACHE_CPP2=1 $CCACHE_COMPILE -c test1.c -O -O
checkstat 'cache hit' 4
checkstat 'cache miss' 3
CCACHE_CPP2=1 $CCACHE_COMPILE -c test1.c -O -O
checkstat 'cache hit' 5
checkstat 'cache miss' 3
testname="CCACHE_NOSTATS"
CCACHE_NOSTATS=1 $CCACHE_COMPILE -c test1.c -O -O
checkstat 'cache hit' 5
checkstat 'cache miss' 3
testname="CCACHE_RECACHE"
CCACHE_RECACHE=1 $CCACHE_COMPILE -c test1.c -O -O
checkstat 'cache hit' 5
checkstat 'cache miss' 4
# strictly speaking should be 6 - RECACHE causes a double counting!
checkstat 'files in cache' 8
$CCACHE -c > /dev/null
checkstat 'files in cache' 6
testname="CCACHE_HASHDIR"
CCACHE_HASHDIR=1 $CCACHE_COMPILE -c test1.c -O -O
checkstat 'cache hit' 5
checkstat 'cache miss' 5
CCACHE_HASHDIR=1 $CCACHE_COMPILE -c test1.c -O -O
checkstat 'cache hit' 6
checkstat 'cache miss' 5
checkstat 'files in cache' 8
testname="comments"
echo '/* a silly comment */' > test1-comment.c
cat test1.c >> test1-comment.c
$CCACHE_COMPILE -c test1-comment.c
rm -f test1-comment*
checkstat 'cache hit' 6
checkstat 'cache miss' 6
testname="CCACHE_UNIFY"
CCACHE_UNIFY=1 $CCACHE_COMPILE -c test1.c
checkstat 'cache hit' 6
checkstat 'cache miss' 7
mv test1.c test1-saved.c
echo '/* another comment */' > test1.c
cat test1-saved.c >> test1.c
CCACHE_UNIFY=1 $CCACHE_COMPILE -c test1.c
mv test1-saved.c test1.c
checkstat 'cache hit' 7
checkstat 'cache miss' 7
testname="cache-size"
for f in *.c; do
$CCACHE_COMPILE -c $f
done
checkstat 'cache hit' 8
checkstat 'cache miss' 37
checkstat 'files in cache' 72
$CCACHE -F 48 -c > /dev/null
if [ `getstat 'files in cache'` -gt 48 ]; then
test_failed '-F test failed'
fi
testname="cpp call"
$CCACHE_COMPILE -c test1.c -E > test1.i
checkstat 'cache hit' 8
checkstat 'cache miss' 37
testname="direct .i compile"
$CCACHE_COMPILE -c test1.c
checkstat 'cache hit' 8
checkstat 'cache miss' 38
$CCACHE_COMPILE -c test1.i
checkstat 'cache hit' 9
checkstat 'cache miss' 38
$CCACHE_COMPILE -c test1.i
checkstat 'cache hit' 10
checkstat 'cache miss' 38
# removed these tests as some compilers (including newer versions of gcc)
# determine which language to use based on .ii/.i extension, and C++ may
# not be installed
# testname="direct .ii file"
# mv test1.i test1.ii
# $CCACHE_COMPILE -c test1.ii
# checkstat 'cache hit' 10
# checkstat 'cache miss' 39
# $CCACHE_COMPILE -c test1.ii
# checkstat 'cache hit' 11
# checkstat 'cache miss' 39
testname="stripc" # This test might not be portable
CCACHE_STRIPC=1 $CCACHE_COMPILE -c test1.c
checkstat 'cache hit' 10
checkstat 'cache miss' 39
CCACHE_STRIPC=1 $CCACHE_COMPILE -c test1.c
checkstat 'cache hit' 11
checkstat 'cache miss' 39
testname="zero-stats"
$CCACHE -z > /dev/null
checkstat 'cache hit' 0
checkstat 'cache miss' 0
testname="clear"
$CCACHE -C > /dev/null
checkstat 'files in cache' 0
rm -f test1.c
}
swigtests() {
echo "starting swig testsuite $testsuite"
rm -rf "$CCACHE_DIR"
checkstat 'cache hit' 0
checkstat 'cache miss' 0
j=1
rm -f *.i
genswigcode testswig1.i 1
testname="BASIC"
$CCACHE_COMPILE -java testswig1.i
checkstat 'cache hit' 0
checkstat 'cache miss' 1
checkstat 'files in cache' 6
testname="BASIC2"
$CCACHE_COMPILE -java testswig1.i
checkstat 'cache hit' 1
checkstat 'cache miss' 1
testname="output"
$CCACHE_COMPILE -java testswig1.i -o foo_wrap.c
checkstat 'cache hit' 1
checkstat 'cache miss' 2
testname="bad"
$CCACHE_COMPILE -java testswig1.i -I 2> /dev/null
checkstat 'bad compiler arguments' 1
testname="stdout"
$CCACHE_COMPILE -v -java testswig1.i > /dev/null
checkstat 'compiler produced stdout' 1
testname="non-regular"
mkdir testd
$CCACHE_COMPILE -o testd -java testswig1.i > /dev/null 2>&1
rm -rf testd
checkstat 'output to a non-regular file' 1
testname="no-input"
$CCACHE_COMPILE -java 2> /dev/null
checkstat 'no input file' 1
testname="CCACHE_DISABLE"
CCACHE_DISABLE=1 $CCACHE_COMPILE -java testswig1.i 2> /dev/null
checkstat 'cache hit' 1
$CCACHE_COMPILE -java testswig1.i
checkstat 'cache hit' 2
testname="CCACHE_CPP2"
CCACHE_CPP2=1 $CCACHE_COMPILE -java -O -O testswig1.i
checkstat 'cache hit' 2
checkstat 'cache miss' 3
CCACHE_CPP2=1 $CCACHE_COMPILE -java -O -O testswig1.i
checkstat 'cache hit' 3
checkstat 'cache miss' 3
testname="CCACHE_NOSTATS"
CCACHE_NOSTATS=1 $CCACHE_COMPILE -java -O -O testswig1.i
checkstat 'cache hit' 3
checkstat 'cache miss' 3
testname="CCACHE_RECACHE"
CCACHE_RECACHE=1 $CCACHE_COMPILE -java -O -O testswig1.i
checkstat 'cache hit' 3
checkstat 'cache miss' 4
# strictly speaking should be 3x6=18 instead of 4x6=24 - RECACHE causes a double counting!
checkstat 'files in cache' 24
$CCACHE -c > /dev/null
checkstat 'files in cache' 18
testname="CCACHE_HASHDIR"
CCACHE_HASHDIR=1 $CCACHE_COMPILE -java -O -O testswig1.i
checkstat 'cache hit' 3
checkstat 'cache miss' 5
CCACHE_HASHDIR=1 $CCACHE_COMPILE -java -O -O testswig1.i
checkstat 'cache hit' 4
checkstat 'cache miss' 5
checkstat 'files in cache' 24
testname="cpp call"
$CCACHE_COMPILE -java -E testswig1.i > testswig1-preproc.i
checkstat 'cache hit' 4
checkstat 'cache miss' 5
testname="direct .i compile"
$CCACHE_COMPILE -java testswig1.i
checkstat 'cache hit' 5
checkstat 'cache miss' 5
# No cache hit due to different input file name, -nopreprocess should not be given twice to SWIG
$CCACHE_COMPILE -java -nopreprocess testswig1-preproc.i
checkstat 'cache hit' 5
checkstat 'cache miss' 6
$CCACHE_COMPILE -java -nopreprocess testswig1-preproc.i
checkstat 'cache hit' 6
checkstat 'cache miss' 6
testname="stripc"
CCACHE_STRIPC=1 $CCACHE_COMPILE -java -O -O testswig1.i
checkstat 'cache hit' 7
checkstat 'cache miss' 6
CCACHE_STRIPC=1 $CCACHE_COMPILE -java -O -O -O testswig1.i
checkstat 'cache hit' 7
checkstat 'cache miss' 7
rm -f testswig1-preproc.i
rm -f testswig1.i
}
######
# main program
rm -rf $TESTDIR
mkdir $TESTDIR
if test -n "$CCACHE_PROG"; then
ln -s $CCACHE $TESTDIR/$CCACHE_PROG
CCACHE=./$CCACHE_PROG
fi
cd $TESTDIR || exit 1
unset CCACHE_DIR
unset CCACHE_TEMPDIR
unset CCACHE_LOGFILE
unset CCACHE_VERBOSE
unset CCACHE_PATH
unset CCACHE_CC
unset CCACHE_PREFIX
unset CCACHE_DISABLE
unset CCACHE_READONLY
unset CCACHE_CPP2
unset CCACHE_NOCOMPRESS
unset CCACHE_NOSTATS
unset CCACHE_NLEVELS
unset CCACHE_HARDLINK
unset CCACHE_RECACHE
unset CCACHE_UMASK
unset CCACHE_HASHDIR
unset CCACHE_UNIFY
unset CCACHE_EXTENSION
unset CCACHE_STRIPC
unset CCACHE_SWIG
CCACHE_DIR="ccache dir" # with space in directory name (like Windows default)
mkdir "$CCACHE_DIR"
export CCACHE_DIR
testsuite="base"
CCACHE_COMPILE="$CCACHE $COMPILER"
basetests
CCACHE_COMPILE="$CCACHE $SWIG"
swigtests
if test -z "$NOSOFTLINKSTEST"; then
testsuite="link"
compilername=`basename $COMPILER`
ln -s $CCACHE ./$compilername
CCACHE_COMPILE="./$compilername"
basetests
rm "./$compilername"
compilername=`basename $SWIG`
ln -s $CCACHE ./$compilername
CCACHE_COMPILE="./$compilername"
swigtests
rm "./$compilername"
else
echo "skipping testsuite link"
fi
testsuite="hardlink"
CCACHE_COMPILE="env CCACHE_NOCOMPRESS=1 CCACHE_HARDLINK=1 $CCACHE $COMPILER"
basetests
CCACHE_COMPILE="env CCACHE_NOCOMPRESS=1 CCACHE_HARDLINK=1 $CCACHE $SWIG"
swigtests
testsuite="cpp2"
CCACHE_COMPILE="env CCACHE_CPP2=1 $CCACHE $COMPILER"
basetests
CCACHE_COMPILE="env CCACHE_CPP2=1 $CCACHE $SWIG"
swigtests
testsuite="nlevels4"
CCACHE_COMPILE="env CCACHE_NLEVELS=4 $CCACHE $COMPILER"
basetests
testsuite="nlevels1"
CCACHE_COMPILE="env CCACHE_NLEVELS=1 $CCACHE $COMPILER"
basetests
cd ..
rm -rf $TESTDIR
echo test done - OK
exit 0

308
CCache/unify.c Normal file
View File

@ -0,0 +1,308 @@
/*
Copyright (C) Andrew Tridgell 2002
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
C/C++ unifier
the idea is that changes that don't affect the resulting C code
should not change the hash. This is achieved by folding white-space
and other non-semantic fluff in the input into a single unified format.
This unifier was design to match the output of the unifier in
compilercache, which is flex based. The major difference is that
this unifier is much faster (about 2x) and more forgiving of
syntactic errors. Continuing on syntactic errors is important to
cope with C/C++ extensions in the local compiler (for example,
inline assembly systems).
*/
#include "ccache.h"
static char *s_tokens[] = {
"...", ">>=", "<<=", "+=", "-=", "*=", "/=", "%=", "&=", "^=",
"|=", ">>", "<<", "++", "--", "->", "&&", "||", "<=", ">=",
"==", "!=", ";", "{", "<%", "}", "%>", ",", ":", "=",
"(", ")", "[", "<:", "]", ":>", ".", "&", "!", "~",
"-", "+", "*", "/", "%", "<", ">", "^", "|", "?",
0
};
#define C_ALPHA 1
#define C_SPACE 2
#define C_TOKEN 4
#define C_QUOTE 8
#define C_DIGIT 16
#define C_HEX 32
#define C_FLOAT 64
#define C_SIGN 128
static struct {
unsigned char type;
unsigned char num_toks;
char *toks[7];
} tokens[256];
/* build up the table used by the unifier */
static void build_table(void)
{
unsigned char c;
int i;
static int done;
if (done) return;
done = 1;
memset(tokens, 0, sizeof(tokens));
for (c=0;c<128;c++) {
if (isalpha(c) || c == '_') tokens[c].type |= C_ALPHA;
if (isdigit(c)) tokens[c].type |= C_DIGIT;
if (isspace(c)) tokens[c].type |= C_SPACE;
if (isxdigit(c)) tokens[c].type |= C_HEX;
}
tokens['\''].type |= C_QUOTE;
tokens['"'].type |= C_QUOTE;
tokens['l'].type |= C_FLOAT;
tokens['L'].type |= C_FLOAT;
tokens['f'].type |= C_FLOAT;
tokens['F'].type |= C_FLOAT;
tokens['U'].type |= C_FLOAT;
tokens['u'].type |= C_FLOAT;
tokens['-'].type |= C_SIGN;
tokens['+'].type |= C_SIGN;
for (i=0;s_tokens[i];i++) {
c = s_tokens[i][0];
tokens[c].type |= C_TOKEN;
tokens[c].toks[tokens[c].num_toks] = s_tokens[i];
tokens[c].num_toks++;
}
}
/* buffer up characters before hashing them */
static void pushchar(unsigned char c)
{
static unsigned char buf[64];
static int len;
if (c == 0) {
if (len > 0) {
hash_buffer((char *)buf, len);
len = 0;
}
hash_buffer(NULL, 0);
return;
}
buf[len++] = c;
if (len == 64) {
hash_buffer((char *)buf, len);
len = 0;
}
}
/* hash some C/C++ code after unifying */
static void unify(unsigned char *p, size_t size)
{
size_t ofs;
unsigned char q;
int i;
build_table();
for (ofs=0; ofs<size;) {
if (p[ofs] == '#') {
if ((size-ofs) > 2 && p[ofs+1] == ' ' && isdigit(p[ofs+2])) {
do {
ofs++;
} while (ofs < size && p[ofs] != '\n');
ofs++;
} else {
do {
pushchar(p[ofs]);
ofs++;
} while (ofs < size && p[ofs] != '\n');
pushchar('\n');
ofs++;
}
continue;
}
if (tokens[p[ofs]].type & C_ALPHA) {
do {
pushchar(p[ofs]);
ofs++;
} while (ofs < size &&
(tokens[p[ofs]].type & (C_ALPHA|C_DIGIT)));
pushchar('\n');
continue;
}
if (tokens[p[ofs]].type & C_DIGIT) {
do {
pushchar(p[ofs]);
ofs++;
} while (ofs < size &&
((tokens[p[ofs]].type & C_DIGIT) || p[ofs] == '.'));
if (ofs < size && (p[ofs] == 'x' || p[ofs] == 'X')) {
do {
pushchar(p[ofs]);
ofs++;
} while (ofs < size && (tokens[p[ofs]].type & C_HEX));
}
if (ofs < size && (p[ofs] == 'E' || p[ofs] == 'e')) {
pushchar(p[ofs]);
ofs++;
while (ofs < size &&
(tokens[p[ofs]].type & (C_DIGIT|C_SIGN))) {
pushchar(p[ofs]);
ofs++;
}
}
while (ofs < size && (tokens[p[ofs]].type & C_FLOAT)) {
pushchar(p[ofs]);
ofs++;
}
pushchar('\n');
continue;
}
if (tokens[p[ofs]].type & C_SPACE) {
do {
ofs++;
} while (ofs < size && (tokens[p[ofs]].type & C_SPACE));
continue;
}
if (tokens[p[ofs]].type & C_QUOTE) {
q = p[ofs];
pushchar(p[ofs]);
do {
ofs++;
while (ofs < size-1 && p[ofs] == '\\') {
pushchar(p[ofs]);
pushchar(p[ofs+1]);
ofs+=2;
}
pushchar(p[ofs]);
} while (ofs < size && p[ofs] != q);
pushchar('\n');
ofs++;
continue;
}
if (tokens[p[ofs]].type & C_TOKEN) {
q = p[ofs];
for (i=0;i<tokens[q].num_toks;i++) {
unsigned char *s = (unsigned char *)tokens[q].toks[i];
int len = strlen((char *)s);
if (size >= ofs+len && memcmp(&p[ofs], s, len) == 0) {
int j;
for (j=0;s[j];j++) {
pushchar(s[j]);
ofs++;
}
pushchar('\n');
break;
}
}
if (i < tokens[q].num_toks) {
continue;
}
}
pushchar(p[ofs]);
pushchar('\n');
ofs++;
}
pushchar(0);
}
/* hash a file that consists of preprocessor output, but remove any line
number information from the hash
*/
int unify_hash(const char *fname)
{
#ifdef _WIN32
HANDLE file;
HANDLE section;
DWORD filesize_low;
char *map;
int ret = -1;
file = CreateFileA(fname, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if (file != INVALID_HANDLE_VALUE) {
filesize_low = GetFileSize(file, NULL);
if (!(filesize_low == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)) {
section = CreateFileMappingA(file, NULL, PAGE_READONLY, 0, 0, NULL);
CloseHandle(file);
if (section != NULL) {
map = MapViewOfFile(section, FILE_MAP_READ, 0, 0, 0);
CloseHandle(section);
if (map != NULL)
ret = 0;
}
}
}
if (ret == -1) {
cc_log("Failed to open preprocessor output %s\n", fname);
stats_update(STATS_PREPROCESSOR);
return -1;
}
/* pass it through the unifier */
unify((unsigned char *)map, filesize_low);
UnmapViewOfFile(map);
return 0;
#else
int fd;
struct stat st;
char *map;
fd = open(fname, O_RDONLY|O_BINARY);
if (fd == -1 || fstat(fd, &st) != 0) {
cc_log("Failed to open preprocessor output %s\n", fname);
if (fd != -1) close(fd);
stats_update(STATS_PREPROCESSOR);
return -1;
}
/* we use mmap() to make it easy to handle arbitrarily long
lines in preprocessor output. I have seen lines of over
100k in length, so this is well worth it */
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (map == (char *)-1) {
cc_log("Failed to mmap %s\n", fname);
stats_update(STATS_PREPROCESSOR);
return -1;
}
/* pass it through the unifier */
unify((unsigned char *)map, st.st_size);
munmap(map, st.st_size);
return 0;
#endif
}

889
CCache/util.c Normal file
View File

@ -0,0 +1,889 @@
/*
Copyright (C) Andrew Tridgell 2002
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "ccache.h"
static FILE *logfile;
/* log a message to the CCACHE_LOGFILE location */
void cc_log(const char *format, ...)
{
va_list ap;
extern char *cache_logfile;
if (!cache_logfile) return;
if (!logfile) logfile = fopen(cache_logfile, "a");
if (!logfile) return;
va_start(ap, format);
vfprintf(logfile, format, ap);
va_end(ap);
fflush(logfile);
}
/* something went badly wrong! */
void fatal(const char *msg)
{
cc_log("FATAL: %s\n", msg);
exit(1);
}
int safe_rename(const char* oldpath, const char* newpath)
{
/* safe_rename is for creating entries in the cache.
Works like rename(), but it never overwrites an existing
cache entry. This avoids corruption on NFS. */
#ifndef _WIN32
int status = link(oldpath, newpath);
if( status == 0 || errno == EEXIST )
#else
int status = CreateHardLinkA(newpath, oldpath, NULL) ? 0 : -1;
if( status == 0 || GetLastError() == ERROR_ALREADY_EXISTS )
#endif
{
return unlink( oldpath );
}
else
{
return -1;
}
}
#ifndef ENABLE_ZLIB
/* copy all data from one file descriptor to another */
void copy_fd(int fd_in, int fd_out)
{
char buf[10240];
int n;
while ((n = read(fd_in, buf, sizeof(buf))) > 0) {
if (write(fd_out, buf, n) != n) {
fatal("Failed to copy fd");
}
}
}
#ifndef HAVE_MKSTEMP
/* cheap and nasty mkstemp replacement */
int mkstemp(char *template)
{
mktemp(template);
return open(template, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
}
#endif
/* move a file using rename */
int move_file(const char *src, const char *dest) {
return safe_rename(src, dest);
}
/* copy a file - used when hard links don't work
the copy is done via a temporary file and atomic rename
*/
static int copy_file(const char *src, const char *dest)
{
int fd1, fd2;
char buf[10240];
int n;
char *tmp_name;
mode_t mask;
x_asprintf(&tmp_name, "%s.XXXXXX", dest);
fd1 = open(src, O_RDONLY|O_BINARY);
if (fd1 == -1) {
free(tmp_name);
return -1;
}
fd2 = mkstemp(tmp_name);
if (fd2 == -1) {
close(fd1);
free(tmp_name);
return -1;
}
while ((n = read(fd1, buf, sizeof(buf))) > 0) {
if (write(fd2, buf, n) != n) {
close(fd2);
close(fd1);
unlink(tmp_name);
free(tmp_name);
return -1;
}
}
close(fd1);
/* get perms right on the tmp file */
#ifndef _WIN32
mask = umask(0);
fchmod(fd2, 0666 & ~mask);
umask(mask);
#else
(void)mask;
#endif
/* the close can fail on NFS if out of space */
if (close(fd2) == -1) {
unlink(tmp_name);
free(tmp_name);
return -1;
}
unlink(dest);
if (rename(tmp_name, dest) == -1) {
unlink(tmp_name);
free(tmp_name);
return -1;
}
free(tmp_name);
return 0;
}
/* copy a file to the cache */
static int copy_file_to_cache(const char *src, const char *dest) {
return copy_file(src, dest);
}
/* copy a file from the cache */
static int copy_file_from_cache(const char *src, const char *dest) {
return copy_file(src, dest);
}
#else /* ENABLE_ZLIB */
/* copy all data from one file descriptor to another
possibly decompressing it
*/
void copy_fd(int fd_in, int fd_out) {
char buf[10240];
int n;
gzFile gz_in;
gz_in = gzdopen(dup(fd_in), "rb");
if (!gz_in) {
fatal("Failed to copy fd");
}
while ((n = gzread(gz_in, buf, sizeof(buf))) > 0) {
if (write(fd_out, buf, n) != n) {
gzclose(gz_in);
fatal("Failed to copy fd");
}
}
gzclose(gz_in);
}
static int _copy_file(const char *src, const char *dest, int mode) {
int fd_in, fd_out;
gzFile gz_in, gz_out = NULL;
char buf[10240];
int n, ret;
char *tmp_name;
mode_t mask;
struct stat st;
x_asprintf(&tmp_name, "%s.XXXXXX", dest);
if (getenv("CCACHE_NOCOMPRESS")) {
mode = COPY_UNCOMPRESSED;
}
/* open source file */
fd_in = open(src, O_RDONLY);
if (fd_in == -1) {
return -1;
}
gz_in = gzdopen(fd_in, "rb");
if (!gz_in) {
close(fd_in);
return -1;
}
/* open destination file */
fd_out = mkstemp(tmp_name);
if (fd_out == -1) {
gzclose(gz_in);
free(tmp_name);
return -1;
}
if (mode == COPY_TO_CACHE) {
/* The gzip file format occupies at least 20 bytes. So
it will always occupy an entire filesystem block,
even for empty files.
Since most stderr files will be empty, we turn off
compression in this case to save space.
*/
if (fstat(fd_in, &st) != 0) {
gzclose(gz_in);
close(fd_out);
free(tmp_name);
return -1;
}
if (file_size(&st) == 0) {
mode = COPY_UNCOMPRESSED;
}
}
if (mode == COPY_TO_CACHE) {
int dup_fd_out = dup(fd_out);
gz_out = gzdopen(dup_fd_out, "wb");
if (!gz_out) {
gzclose(gz_in);
close(dup_fd_out);
close(fd_out);
free(tmp_name);
return -1;
}
}
while ((n = gzread(gz_in, buf, sizeof(buf))) > 0) {
if (mode == COPY_TO_CACHE) {
ret = gzwrite(gz_out, buf, n);
} else {
ret = write(fd_out, buf, n);
}
if (ret != n) {
gzclose(gz_in);
if (gz_out) {
gzclose(gz_out);
}
close(fd_out);
unlink(tmp_name);
free(tmp_name);
return -1;
}
}
gzclose(gz_in);
if (gz_out) {
gzclose(gz_out);
}
/* get perms right on the tmp file */
mask = umask(0);
fchmod(fd_out, 0666 & ~mask);
umask(mask);
/* the close can fail on NFS if out of space */
if (close(fd_out) == -1) {
unlink(tmp_name);
free(tmp_name);
return -1;
}
unlink(dest);
if (rename(tmp_name, dest) == -1) {
unlink(tmp_name);
free(tmp_name);
return -1;
}
free(tmp_name);
return 0;
}
/* move a file to the cache, compressing it */
int move_file(const char *src, const char *dest) {
int ret;
ret = _copy_file(src, dest, COPY_TO_CACHE);
if (ret != -1) unlink(src);
return ret;
}
/* copy a file to the cache, compressing it */
static int copy_file_to_cache(const char *src, const char *dest) {
return _copy_file(src, dest, COPY_TO_CACHE);
}
/* copy a file from the cache, decompressing it */
static int copy_file_from_cache(const char *src, const char *dest) {
return _copy_file(src, dest, COPY_FROM_CACHE);
}
#endif /* ENABLE_ZLIB */
/* test if a file is zlib compressed */
int test_if_compressed(const char *filename) {
FILE *f;
f = fopen(filename, "rb");
if (!f) {
return 0;
}
/* test if file starts with 1F8B, which is zlib's
* magic number */
if ((fgetc(f) != 0x1f) || (fgetc(f) != 0x8b)) {
fclose(f);
return 0;
}
fclose(f);
return 1;
}
/* copy file to the cache with error checking taking into account compression and hard linking if desired */
int commit_to_cache(const char *src, const char *dest, int hardlink)
{
int ret = -1;
struct stat st;
if (stat(src, &st) == 0) {
unlink(dest);
if (hardlink) {
#ifdef _WIN32
ret = CreateHardLinkA(dest, src, NULL) ? 0 : -1;
#else
ret = link(src, dest);
#endif
}
if (ret == -1) {
ret = copy_file_to_cache(src, dest);
if (ret == -1) {
cc_log("failed to commit %s -> %s (%s)\n", src, dest, strerror(errno));
stats_update(STATS_ERROR);
}
}
} else {
cc_log("failed to put %s in the cache (%s)\n", src, strerror(errno));
stats_update(STATS_ERROR);
}
return ret;
}
/* copy file out of the cache with error checking taking into account compression and hard linking if desired */
int retrieve_from_cache(const char *src, const char *dest, int hardlink)
{
int ret = 0;
x_utimes(src);
if (strcmp(dest, "/dev/null") == 0) {
ret = 0;
} else {
unlink(dest);
/* only make a hardlink if the cache file is uncompressed */
if (hardlink && test_if_compressed(src) == 0) {
#ifdef _WIN32
ret = CreateHardLinkA(dest, src, NULL) ? 0 : -1;
#else
ret = link(src, dest);
#endif
} else {
ret = copy_file_from_cache(src, dest);
}
}
/* the cached file might have been deleted by some external process */
if (ret == -1 && errno == ENOENT) {
cc_log("hashfile missing for %s\n", dest);
stats_update(STATS_MISSING);
return -1;
}
if (ret == -1) {
ret = copy_file_from_cache(src, dest);
if (ret == -1) {
cc_log("failed to retrieve %s -> %s (%s)\n", src, dest, strerror(errno));
stats_update(STATS_ERROR);
return -1;
}
}
return ret;
}
/* make sure a directory exists */
int create_dir(const char *dir)
{
struct stat st;
if (stat(dir, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
return 0;
}
errno = ENOTDIR;
return 1;
}
#ifdef _WIN32
if (mkdir(dir) != 0 && errno != EEXIST) {
return 1;
}
#else
if (mkdir(dir, 0777) != 0 && errno != EEXIST) {
return 1;
}
#endif
return 0;
}
char const CACHEDIR_TAG[] =
"Signature: 8a477f597d28d172789f06886806bc55\n"
"# This file is a cache directory tag created by ccache.\n"
"# For information about cache directory tags, see:\n"
"# http://www.brynosaurus.com/cachedir/\n";
int create_cachedirtag(const char *dir)
{
char *filename;
struct stat st;
FILE *f;
x_asprintf(&filename, "%s/CACHEDIR.TAG", dir);
if (stat(filename, &st) == 0) {
if (S_ISREG(st.st_mode)) {
goto success;
}
errno = EEXIST;
goto error;
}
f = fopen(filename, "w");
if (!f) goto error;
if (fwrite(CACHEDIR_TAG, sizeof(CACHEDIR_TAG)-1, 1, f) != 1) {
fclose(f);
goto error;
}
if (fclose(f)) goto error;
success:
free(filename);
return 0;
error:
free(filename);
return 1;
}
/*
this is like asprintf() but dies if the malloc fails
note that we use vsnprintf in a rather poor way to make this more portable
*/
void x_asprintf(char **ptr, const char *format, ...)
{
va_list ap;
*ptr = NULL;
va_start(ap, format);
if (vasprintf(ptr, format, ap) == -1) {
fatal("out of memory in x_asprintf");
}
va_end(ap);
if (!*ptr) fatal("out of memory in x_asprintf");
}
/*
this is like strdup() but dies if the malloc fails
*/
char *x_strdup(const char *s)
{
char *ret;
ret = strdup(s);
if (!ret) {
fatal("out of memory in strdup\n");
}
return ret;
}
/*
this is like malloc() but dies if the malloc fails
*/
void *x_malloc(size_t size)
{
void *ret;
ret = malloc(size);
if (!ret) {
fatal("out of memory in malloc\n");
}
return ret;
}
/*
this is like realloc() but dies if the malloc fails
*/
void *x_realloc(void *ptr, size_t size)
{
void *p2;
#if 1
/* Avoid invalid read in memcpy below */
p2 = realloc(ptr, size);
if (!p2) {
fatal("out of memory in x_realloc");
}
#else
if (!ptr) return x_malloc(size);
p2 = malloc(size);
if (!p2) {
fatal("out of memory in x_realloc");
}
if (ptr) {
/* Note invalid read as the memcpy reads beyond the memory allocated by ptr */
memcpy(p2, ptr, size);
free(ptr);
}
#endif
return p2;
}
/*
revsusive directory traversal - used for cleanup
fn() is called on all files/dirs in the tree
*/
void traverse(const char *dir, void (*fn)(const char *, struct stat *))
{
DIR *d;
struct dirent *de;
d = opendir(dir);
if (!d) return;
while ((de = readdir(d))) {
char *fname;
struct stat st;
if (strcmp(de->d_name,".") == 0) continue;
if (strcmp(de->d_name,"..") == 0) continue;
if (strlen(de->d_name) == 0) continue;
x_asprintf(&fname, "%s/%s", dir, de->d_name);
#ifdef _WIN32
if (stat(fname, &st))
#else
if (lstat(fname, &st))
#endif
{
if (errno != ENOENT) {
perror(fname);
}
free(fname);
continue;
}
if (S_ISDIR(st.st_mode)) {
traverse(fname, fn);
}
fn(fname, &st);
free(fname);
}
closedir(d);
}
/* return the base name of a file - caller frees */
char *str_basename(const char *s)
{
char *p = strrchr(s, '/');
if (p) {
s = (p+1);
}
#ifdef _WIN32
p = strrchr(s, '\\');
if (p) {
s = (p+1);
}
#endif
return x_strdup(s);
}
/* return the dir name of a file - caller frees */
char *dirname(char *s)
{
char *p;
s = x_strdup(s);
p = strrchr(s, '/');
#ifdef _WIN32
p = strrchr(s, '\\');
#endif
if (p) {
*p = 0;
}
return s;
}
/*
http://www.ecst.csuchico.edu/~beej/guide/ipc/flock.html
http://cvs.php.net/viewvc.cgi/php-src/win32/flock.c?revision=1.2&view=markup
Should return 0 for success, >0 otherwise
*/
int lock_fd(int fd)
{
#ifdef _WIN32
# if 1
return _locking(fd, _LK_NBLCK, 1);
# else
HANDLE fl = (HANDLE)_get_osfhandle(fd);
OVERLAPPED o;
memset(&o, 0, sizeof(o));
return (LockFileEx(fl, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &o))
? 0 : GetLastError();
# endif
#else
struct flock fl;
int ret;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 1;
fl.l_pid = 0;
/* not sure why we would be getting a signal here,
but one user claimed it is possible */
do {
ret = fcntl(fd, F_SETLKW, &fl);
} while (ret == -1 && errno == EINTR);
return ret;
#endif
}
/* return size on disk of a file */
size_t file_size(struct stat *st)
{
#ifdef _WIN32
return (st->st_size + 1023) & ~1023;
#else
size_t size = st->st_blocks * 512;
if ((size_t)st->st_size > size) {
/* probably a broken stat() call ... */
size = (st->st_size + 1023) & ~1023;
}
return size;
#endif
}
/* a safe open/create for read-write */
int safe_open(const char *fname)
{
int fd = open(fname, O_RDWR|O_BINARY);
if (fd == -1 && errno == ENOENT) {
fd = open(fname, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0666);
if (fd == -1 && errno == EEXIST) {
fd = open(fname, O_RDWR|O_BINARY);
}
}
return fd;
}
/* display a kilobyte unsigned value in M, k or G */
void display_size(unsigned v)
{
if (v > 1024*1024) {
printf("%8.1f Gbytes", v/((double)(1024*1024)));
} else if (v > 1024) {
printf("%8.1f Mbytes", v/((double)(1024)));
} else {
printf("%8u Kbytes", v);
}
}
/* return a value in multiples of 1024 give a string that can end
in K, M or G
*/
size_t value_units(const char *s)
{
char m;
double v = atof(s);
m = s[strlen(s)-1];
switch (m) {
case 'G':
case 'g':
default:
v *= 1024*1024;
break;
case 'M':
case 'm':
v *= 1024;
break;
case 'K':
case 'k':
v *= 1;
break;
}
return (size_t)v;
}
/*
a sane realpath() function, trying to cope with stupid path limits and
a broken API
*/
char *x_realpath(const char *path)
{
#ifdef _WIN32
char namebuf[MAX_PATH];
DWORD ret;
ret = GetFullPathNameA(path, sizeof(namebuf), namebuf, NULL);
if (ret == 0 || ret >= sizeof(namebuf)) {
return NULL;
}
return x_strdup(namebuf);
#else
int maxlen;
char *ret, *p;
#ifdef PATH_MAX
maxlen = PATH_MAX;
#elif defined(MAXPATHLEN)
maxlen = MAXPATHLEN;
#elif defined(_PC_PATH_MAX)
maxlen = pathconf(path, _PC_PATH_MAX);
#endif
if (maxlen < 4096) maxlen = 4096;
ret = x_malloc(maxlen);
#if HAVE_REALPATH
p = realpath(path, ret);
#else
/* yes, there are such systems. This replacement relies on
the fact that when we call x_realpath we only care about symlinks */
{
int len = readlink(path, ret, maxlen-1);
if (len == -1) {
free(ret);
return NULL;
}
ret[len] = 0;
p = ret;
}
#endif
if (p) {
p = x_strdup(p);
free(ret);
return p;
}
free(ret);
return NULL;
#endif
}
/* a getcwd that will returns an allocated buffer */
char *gnu_getcwd(void)
{
unsigned size = 128;
while (1) {
char *buffer = (char *)x_malloc(size);
if (getcwd(buffer, size) == buffer) {
return buffer;
}
free(buffer);
if (errno != ERANGE) {
return 0;
}
size *= 2;
}
}
/* create an empty file */
int create_empty_file(const char *fname)
{
int fd;
fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666);
if (fd == -1) {
return -1;
}
close(fd);
return 0;
}
/*
return current users home directory or die
*/
const char *get_home_directory(void)
{
#ifdef _WIN32
static char home_path[MAX_PATH] = {0};
HRESULT ret;
/* we already have the path */
if (home_path[0] != 0) {
return home_path;
}
/* get the path to "Application Data" folder */
ret = SHGetFolderPathA(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, home_path);
if (SUCCEEDED(ret)) {
return home_path;
}
fprintf(stderr, "ccache: Unable to determine home directory\n");
return NULL;
#else
const char *p = getenv("HOME");
if (p) {
return p;
}
#ifdef HAVE_GETPWUID
{
struct passwd *pwd = getpwuid(getuid());
if (pwd) {
return pwd->pw_dir;
}
}
#endif
fatal("Unable to determine home directory");
return NULL;
#endif
}
int x_utimes(const char *filename)
{
#ifdef HAVE_UTIMES
return utimes(filename, NULL);
#else
return utime(filename, NULL);
#endif
}
#ifdef _WIN32
/* perror for Win32 API calls, using GetLastError() instead of errno */
void perror_win32(LPTSTR pszFunction)
{
LPTSTR pszMessage;
DWORD dwLastError = GetLastError();
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pszMessage,
0, NULL );
fprintf(stderr, "%s: %s\n", pszFunction, pszMessage);
LocalFree(pszMessage);
}
#endif

158
CCache/web/index.html Normal file
View File

@ -0,0 +1,158 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>ccache</TITLE>
</HEAD>
<BODY BGCOLOR="#ffffff" TEXT="#000000" VLINK="#292555" LINK="#292555" ALINK="#cc0033">
<h2>ccache</h2>
ccache is a compiler cache. It acts as a caching pre-processor to
C/C++ compilers, using the -E compiler switch and a hash to detect
when a compilation can be satisfied from cache. This often results in
a 5 to 10 times speedup in common compilations.<p>
The idea came from Erik Thiele wrote the original <a
href="http://compilercache.sourceforge.net/">compilercache</a> program
as a bourne shell script. ccache is a re-implementation of Erik's idea
in C with more features and better performance.<p>
<h2>Latest release</h2>
The latest release is ccache 2.4.
<ul>
<li>Added CCACHE_READONLY option
<li>Added CCACHE_TEMPDIR option
<li>fixed handling of hard-linked compilers on AIX
<li>added O_BINARY support, to try and support win32 compiles
<li>show cache directory in stats output
<li>fixed handling of HOME environment variable
</ul>
See the <a href="ccache-man.html">manual page</a> for details
on the new options.<p>
You can get this release from the <a href="http://ccache.samba.org/ftp/ccache/">download directory</a>
<p>NOTE! This release changes the hash input slighly, so you will
probably find that you will not get any hits against your existing
cache when you upgrade.
<h2>Why bother?</h2>
Why bother with a compiler cache? If you ever run "make clean; make"
then you can probably benefit from ccache. It is very common for
developers to do a clean build of a project for a whole host of
reasons, and this throws away all the information from your previous
compiles.<p>
By using ccache you can get exactly the same effect as "make clean;
make" but much faster. It also helps a lot when doing RPM builds,
as RPM can make doing incremental builds tricky.<p>
I put the effort into writing ccache for 2 reasons. The first is the
Samba build farm
(<a href="http://build.samba.org/">http://build.samba.org/</a>)
which constantly does clean builds of Samba on about 30 machines after each
CVS commit. On some of those machines the build took over an hour. By
using ccache we get the same effect as clean builds but about 6 times
faster.<p>
The second reason is the autobuild system I used to run for
Quantum. That system builds our whole Linux based OS from scratch
after every CVS commit to catch compilation problems quickly. Using
ccache those builds are much faster.
<h2>Is it safe?</h2>
Yes. The most important aspect of a compiler cache is to <b>always</b>
produce exactly the same output that the real compiler would
produce. The includes providing exactly the same object files and
exactly the same compiler warnings that would be produced if you use
the real compiler. The only way you should be able to tell that you
are using ccache is the speed.<p>
I have coded ccache very carefully to try to provide these guarantees.
<h2>Features</h2>
<ul>
<li> keeps statistics on hits/misses
<li> automatic cache size management
<li> can cache compiles that generate warnings
<li> easy installation
<li> very low overhead
<li> uses hard links where possible to avoid copies
</ul>
<h2>Documentation</h2>
See the <a href="ccache-man.html">manual page</a>
<h2>Performance</h2>
Here are some results for compiling Samba on my Linux laptop. I have
also included the results of using Erik's compilercache program
(version 1.0.10) for comparison.<p>
<table border=1>
<tr><th> </th> <th>&nbsp;&nbsp;&nbsp;&nbsp;ccache</th> <th>&nbsp;compilercache</th> </tr>
<tr><td>normal </td> <td align=right>13m 4s </td><td align=right>13m 4s</td> </tr>
<tr><td>uncached </td> <td align=right>13m 15s </td><td align=right>15m 41s</td> </tr>
<tr><td>cached </td> <td align=right>2m 45s </td><td align=right>4m 26s</td> </tr>
</table>
<h2>How to use it</h2>
You can use ccache in two ways. The first is just to prefix your
compile commands with "ccache". For example, you could change the
"CC=gcc" line in your Makefile to be "CC=ccache gcc".<p>
Alternatively, you can create symbolic links from your compilers name
to ccache. This allows you to use ccache without any changes to your
build system.
<h2>Download</h2>
You can download the latest release from the <a
href="http://ccache.samba.org/ftp/ccache/">download directory</a>.<p>
For the bleeding edge, you can fetch ccache via CVS or
rsync. To fetch via cvs use the following command:
<pre>
cvs -d :pserver:cvs@pserver.samba.org:/cvsroot co ccache
</pre>
To fetch via rsync use this command:
<pre>
rsync -Pavz samba.org::ftp/unpacked/ccache .
</pre>
<h2>Related projects</h2>
Here are some related programs you may find interesting
<ul>
<li> <a href="http://distcc.samba.org/">distcc</a> - a distributed compilation system
<li> <a href="http://cachecc1.sourceforge.net/">cachecc1</a> - a gcc specific cache
<li> <a href="http://sourceforge.net/projects/gocache/">gocache</a> - a cross platform compiler cache
</ul>
<p>
<h2>Mailing list</h2>
<p>A <a href="http://lists.samba.org/mailman/listinfo/ccache/">mailing
list</a> is available for discussion of ccache.
<hr>
<tiny>
<a href="http://samba.org/~tridge/">Andrew Tridgell</a><br>
<a href="mailto:bugs@ccache.samba.org">bugs@ccache.samba.org</a>
</tiny>
</BODY>
</HTML>

26570
CHANGES Normal file

File diff suppressed because it is too large Load Diff

150
CHANGES.current Normal file
View File

@ -0,0 +1,150 @@
Below are the changes for the current release.
See the CHANGES file for changes in older releases.
See the RELEASENOTES file for a summary of changes in each release.
Issue # numbers mentioned below can be found on Github. For more details, add
the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.0.2 (8 Jun 2020)
==========================
2020-06-07 vigsterkr
[Ruby] #1717 Nil fix mangling strings
2020-06-07 vadz
#1748 Fix doxygen comments quoting issue
2020-06-07 munoah
#1800 Escape spaces in file paths for dependencies (-M -MM etc)
2020-06-06 andreas-schwab
[Ruby] #1801 Fix encoding on big endian systems when wrapping std::wstring.
2020-05-31 kwwette
[Octave] #1789 error handling improvements and return error code on exit for SWIG wrapped modules.
2020-05-30 msteinbeck
[D] #1593 Replace broken imports when using newer versions of D.
2020-05-29: ZackerySpytz
[Python] #1716 Performance improvements converting strings when using Python >= 3.3.
2020-05-28: ZackerySpytz
#1776 Quite dramatically decrease run times when generating very large interface files by changing
some internal memory pool sizes.
2020-05-28: mcfarljm
#1788 Fix handling of Doxygen \endlink command.
2020-05-24: vapier
[Javascript] #1796 Fix pkg-config invocation in configure.
2020-04-30: kwwette
[Octave] Fix exception raising for newer Octave versions
Since (at least) Octave 5.1.0, the Octave error() function now raises a C++ exception,
which if uncaught immediately exits a SWIG wrapper function, bypassing any cleanup code
that may appear after a "fail:" label. This patch adds a "try { ... } catch(...) { }"
block around the contents of SWIG wrapper functions to first execute the cleanup code
before rethrowing any exception raised. It is backward compatible with earlier versions
of Octave where error() does not raise an exception, which will still branch to the
"fail:" block to execute cleanup code if an error is encountered.
Note that the new "try { ... } catch(...) { }" block will localise any local variables
used in typemaps that were NOT declared through SWIG's %typemap(...) syntax, so it's
possible this could break existing SWIG wrappers which were implicitly sharing local
variables between typemaps. This can be fixed, however, by declaring local variables
which need to be shared between typemaps through SWIG's %typemap(...) syntax.
2020-02-18: ryannevell
[Lua] #1728 Add support for LUA lightuserdata to SWIG_Lua_ConvertPtr.
2020-02-18: dmach
[Ruby] #1725 Fix gcc -Wcatch-value warnings.
2020-02-14: treitmayr
#1724 Fix wrapping of abstract user-defined conversion operators.
2020-02-13: ddurham2
[Python] #1512 Fix memleak when using STL containers of shared_ptr objects.
2020-02-06: wsfulton
[Python] #1673 #1674 Fix setting 'this' when extending a proxy class with __slots__.
2020-01-31: vadz
[Ruby] #1651 Add std::auto_ptr<> typemaps.
2020-01-31: ZackerySpytz
[Python] #1700 More robust error checking for failures in calls to Python C API:
PyBytes_AsStringAndSize() and PyString_AsStringAndSize().
2020-01-31: vadz
[Python] #1710 Fix crash parsing empty docstrings.
2020-01-30: Alzathar
[R] #910 #914 Fix R memory leak on exception.
2020-01-30: richardbeare
[R] #1511 Fix bug wrapping functions. These were previously incorrectly wrapped as if
they were variables. This happened when 'get' or 'set' was in the name of the function
or method, but sometimes also in some other circumstances. If you were using R
attribute syntax to access these methods, you'll need to switch to calling them as R
methods.
*** POTENTIAL INCOMPATIBILITY ***
2020-01-24: etse-dignitas, wsfulton
[C#, D, Java] #1533 Fix upcasting for shared_ptr's of templated types.
2020-01-16: mcfarljm
#1643 #1654 When using -doxygen, fix segfault when nameless parameters or vararg parameters
are used.
2020-01-16: mcfarljm
#1632 #1659 Fix newline handling for doxygen "///" comments.
2020-01-14: mcfarljm
#1647 #1656 Fix crash handling empty doxygen comments.
2020-01-14: mcfarljm
#1608 Improve doxygen support.
- Add support for \param[] commands such as: \param[in].
- Optional arguments are marked as 'optional' in pydoc.
- Improve support for \code commands so that other languages are supported as code blocks.
Support added for java, c and py. For example Python: \code{.py} ... \endcode
- Fix doxygen handling of \em and \p tags for Python.
2020-01-13: wsfulton
[Python] #1595 Python -builtin constructors silently ignored keyword arguments.
Instead of silenty ignoring them, now a "TypeError: f() takes no keyword arguments"
exception is thrown if keyword arguments are used. Hence constructors and normal methods/
functions behave in the same way. Note, -keyword should be used with -builtin to obtain
keyword argument support.
2020-01-05: jschueller shadchin
[Python] #1670 #1696 Add missing field initializers introduced in python 3.8:
tp_vectorcall and tp_print.
2020-01-05: friedrichatgc
[Octave] #1688 Change swig_this() to use size_t instead of long for compatibility
with Windows 64 bit.
2020-01-05: treitmayr
[Ruby] #1692 #1689 Add support for Ruby 2.7
2019-12-30: treitmayr
[Ruby] #1653 #1668 Fix code generated when using -globalmodule option.
2019-12-29: ZackerySpytz
[OCaml] #1686 Fix compilation errors with OCaml 4.09.0.
2019-12-10: wsfulton
#1679 Fix parsing of C++11 identifiers with special meaning (final and override) when
they are used as part of the scope name of an identifier, such as a namespace name.
2019-11-26: wsfulton
[C#] #1628 'out' or 'ref' used in a cstype typemap was not always stripped out in parts
of director code generation.
2019-11-01: wsfulton
[Python] #1595 Fix bug in support for keyword arguments (kwargs feature or -keyword)
when using -builtin. The fix is in the argument error checking when wrapping zero
argument constructors only.

113
COPYRIGHT Normal file
View File

@ -0,0 +1,113 @@
SWIG Copyright and Authors
--------------------------
Copyright (c) 1995-2011 The SWIG Developers
Copyright (c) 2005-2006 Arizona Board of Regents (University of Arizona).
Copyright (c) 1998-2005 University of Chicago.
Copyright (c) 1995-1998 The University of Utah and the Regents of the University of California
Portions also copyrighted by:
Network Applied Communication Laboratory, Inc
Information-technology Promotion Agency, Japan
Active SWIG Developers:
William Fulton (wsf@fultondesigns.co.uk) (SWIG core, Java, C#, Windows, Cygwin)
Olly Betts (olly@survex.com) (PHP)
Joseph Wang (joequant@gmail.com) (R)
Xavier Delacour (xavier.delacour@gmail.com) (Octave)
David Nadlinger (code@klickverbot.at) (D)
Oliver Buchtala (oliver.buchtala@gmail.com) (Javascript)
Neha Narang (narangneha03@gmail.com) (Javascript)
Simon Marchetto (simon.marchetto@scilab-enterprises.com) (Scilab)
Zackery Spytz (zspytz@gmail.com) (OCaml, SWIG core)
Past SWIG developers and major contributors include:
Dave Beazley (dave-swig@dabeaz.com) (SWIG core, Python, Tcl, Perl)
Henning Thielemann (swig@henning-thielemann.de) (Modula3)
Matthias Köppe (mkoeppe@mail.math.uni-magdeburg.de) (Guile, MzScheme)
Luigi Ballabio (luigi.ballabio@fastwebnet.it) (STL wrapping)
Mikel Bancroft (mikel@franz.com) (Allegro CL)
Surendra Singhi (efuzzyone@netscape.net) (CLISP, CFFI)
Marcelo Matus (mmatus@acms.arizona.edu) (SWIG core, Python, UTL[python,perl,tcl,ruby])
Art Yerkes (ayerkes@speakeasy.net) (OCaml)
Lyle Johnson (lyle@users.sourceforge.net) (Ruby)
Charlie Savage (cfis@interserv.com) (Ruby)
Thien-Thi Nguyen (ttn@glug.org) (build/test/misc)
Richard Palmer (richard@magicality.org) (PHP)
Sam Liddicott - Ananova Ltd (saml@liddicott.com) (PHP)
Tim Hockin - Sun Microsystems (thockin@sun.com) (PHP)
Kevin Ruland (PHP)
Shibukawa Yoshiki (Japanese Translation)
Jason Stewart (jason@openinformatics.com) (Perl5)
Loic Dachary (Perl5)
David Fletcher (Perl5)
Gary Holt (Perl5)
Masaki Fukushima (Ruby)
Scott Michel (scottm@cs.ucla.edu) (Java directors)
Tiger Feng (songyanf@cs.uchicago.edu) (SWIG core)
Mark Rose (mrose@stm.lbl.gov) (Directors)
Jonah Beckford (beckford@usermail.com) (CHICKEN)
Ahmon Dancy (dancy@franz.com) (Allegro CL)
Dirk Gerrits (Allegro CL)
Neil Cawse (C#)
Harco de Hilster (Java)
Alexey Dyachenko (dyachenko@fromru.com) (Tcl)
Bob Techentin (Tcl)
Martin Froehlich <MartinFroehlich@ACM.org> (Guile)
Marcio Luis Teixeira <marciot@holly.colostate.edu> (Guile)
Duncan Temple Lang (R)
Miklos Vajna <vmiklos@frugalware.org> (PHP directors)
Mark Gossage (mark@gossage.cjb.net) (Lua)
Raman Gopalan (ramangopalan@gmail.com) (eLua)
Gonzalo Garramuno (ggarra@advancedsl.com.ar) (Ruby, Ruby's UTL)
John Lenz (Guile, MzScheme updates, Chicken module, runtime system)
Baozeng Ding <sploving1@163.com> (Scilab)
Ian Lance Taylor (Go)
Dmitry Kabak (userdima@gmail.com) (Doxygen)
Vadim Zeitlin (PCRE, Python, Doxygen)
Stefan Zager (szager@gmail.com) (Python)
Vincent Couvert (Scilab)
Sylvestre Ledru (Scilab)
Wolfgang Frisch (Scilab)
Past contributors include:
James Michael DuPont, Clark McGrew, Dustin Mitchell, Ian Cooke, Catalin Dumitrescu, Baran
Kovuk, Oleg Tolmatcev, Tal Shalif, Lluis Padro, Chris Seatory, Igor Bely, Robin Dunn,
Edward Zimmermann, David Ascher, Dominique Dumont, Pier Giorgio Esposito, Hasan Baran Kovuk,
Klaus Wiederänders, Richard Beare, Hans Oesterholt.
(See CHANGES and CHANGES.current and the bug tracker for a more complete list).
Past students:
Songyan Feng (Chicago).
Xinghua Shi (Chicago).
Jing Cao (Chicago).
Aquinas Hobor (Chicago).
Historically, the following people contributed to early versions of SWIG.
Peter Lomdahl, Brad Holian, Shujia Zhou, Niels Jensen, and Tim Germann
at Los Alamos National Laboratory were the first users. Patrick
Tullmann at the University of Utah suggested the idea of automatic
documentation generation. John Schmidt and Kurtis Bleeker at the
University of Utah tested out the early versions. Chris Johnson
supported SWIG's developed at the University of Utah. John Buckman,
Larry Virden, and Tom Schwaller provided valuable input on the first
releases and improving the portability of SWIG. David Fletcher and
Gary Holt have provided a great deal of input on improving SWIG's
Perl5 implementation. Kevin Butler contributed the first Windows NT
port.
Early bug reports and patches:
Adam Hupp, Arthur Smyles, Brad Clements, Brett Williams, Buck Hodges,
Burkhard Kloss, Chia-Liang Kao, Craig Files, Dennis Marsa, Dieter Baron,
Drake Diedrich, Fleur Diana Dragan, Gary Pennington, Geoffrey Hort, Gerald Williams,
Greg Anderson, Greg Kochanski, Greg Troxel, Henry Rowley, Irina Kotlova,
Israel Taller, James Bailey, Jim Fulton, Joel Reed, Jon Travis,
Junio Hamano, Justin Heyes-Jones, Karl Forner, Keith Davidson,
Krzysztof Kozminski, Larry Virden, Luke J Crook, Magnus Ljung, Marc Zonzon,
Mark Howson, Micahel Scharf, Michel Sanner, Mike Romberg, Mike Simons,
Mike Weiblen, Paul Brannan, Ram Bhamidipaty, Reinhard Fobbe, Rich Wales,
Richard Salz, Roy Lecates, Rudy Albachten, Scott Drummonds
Scott Michel, Shaun Lowry, Steve Galser, Tarn Weisner Burton,
Thomas Weidner, Tony Seward, Uwe Steinmann, Vadim Chugunov, Wyss Clemens,
Zhong Ren.

79
Doc/Devel/cmdopt.html Normal file
View File

@ -0,0 +1,79 @@
<html>
<head>
<title>SWIG Command Line Handling</title>
</head>
<body>
<center>
<h1>SWIG Command Line Handling</h1>
<p>
David M. Beazley <br>
dave-swig@dabeaz.com<br>
December, 2006<br>
</b>
</center>
<h2>Introduction</h2>
This document describes the functions related to the handling of
command line options passed to SWIG. These functions are defined in
the header file <tt>Source/Swig/swigopt.h</tt>. This API is
considered to be stable.
<h2>Initialization</h2>
Upon SWIG startup, the following function is called:
<p>
<b><tt>void Swig_init_args(int argc, char **argv_)</tt></b>
<blockquote>
Registers command line options with the SWIG core. This creates an internal array that is used by other
functions to mark whether or not a particular command line option was used. This is ultimately used to issue error messages about unused or unknown command line options. This function is currently invoked in the SWIG main() function that is found in <tt>Source/Modules/swigmain.cxx</tt>.
</blockquote>
<h2>Argument Marking</h2>
As command line options are processed by language modules, the following functions are used
to mark the arguments as used:
<p>
<b><tt>void Swig_mark_arg(int n)</tt></b>
<blockquote>
Mark argument number <tt>n</tt> as used.
</blockquote>
<p>
<b><tt>int Swig_check_marked(int n)</tt></b>
<blockquote>
Check to see if argument <tt>n</tt> has been marked. Returns 0 or 1.
</blockquote>
<h2>Argument Checking</h2>
The following function is used to check all of the command line options after parsing. It looks at the marked list
and issues an error message if any unconsumed arguments are found.
<p>
<b><tt>void Swig_check_options()</tt></b>
<blockquote>
Checks all command line options to see if they have all been processed. If not, an error message is generated and
execution terminates with a call to <tt>exit()</tt>. This function is currently invoked in <tt>Source/Modules/main.cxx</tt> just before SWIG starts any processing of input files.
</blockquote>
<h2>Utility Function</h2>
<p>
<b><tt>void Swig_arg_error())</tt></b>
<blockquote>
A generic function that issues an error message about being unable to parse command line options. SWIG is terminated by a call to <tt>exit()</tt>.
</body>
</html>

404
Doc/Devel/engineering.html Normal file
View File

@ -0,0 +1,404 @@
<html>
<head>
<title>SWIG Engineering Manual</title>
</head>
<body bgcolor="#ffffff">
<center>
<h1>SWIG Engineering Manual</h1>
<b>David Beazley <br>
</b>
</center>
<p>
(Note : This is a work in progress.)
<h2>Table of Contents</h2>
<ul>
<li><a name="i1" href="#1">1. Introduction</a>
<li><a name="i2" href="#2">2. Programming Languages and Libraries</a>
<li><a name="i3" href="#3">3. The Source Directory and Module Names</a>
<li><a name="i4" href="#4">4. Include Files</a>
<li><a name="i5" href="#5">5. File Structure</a>
<li><a name="i6" href="#6">6. Bottom-Up Design</a>
<li><a name="i7" href="#7">7. Functions</a>
<li><a name="i8" href="#8">8. Naming Conventions</a>
<li><a name="i9" href="#9">9. Visibility</a>
<li><a name="i10" href="#10">10. Miscellaneous Coding Guidelines</a>
<li><a name="i11" href="#11">11. Git Tagging Conventions</a>
</ul>
<a name="1" href="#i1">
<h2>1. Introduction</h2>
</a>
The purpose of this document is to describe various coding conventions
and organizational aspects for SWIG developers. The idea for this
document is largely borrowed from John Ousterhout's Tcl/Tk Engineering
Manual. It is not my intent to overly managerial about matters--rather I'm
hoping to make life a little less chaotic for everyone.
<p>
First a little background: SWIG was started in 1995 as a one-person
project and continued in this mode of operation until about 1998.
Most of this development was driven by ideas submitted by early SWIG
users as opposed to being motivated by a grand design. As a result,
the code ended up being a pretty horrible C++ coding disaster. A
mostly working disaster perhaps, but a disaster nonetheless.
<p>
With that said, the primary goal of future SWIG development is to
reengineer the original system, fix most of its inherent design flaws,
and to produce what I hope will become a highly extensible and modular
interface compiler framework. To this do this, there are a few
critical areas of work. First, I want to restructure SWIG as a
collection of loosely coupled modules written in either ANSI C or an
scripting language. Second, I want the system to be minimalistic in
its use of data structures and interconnections. The primary reason
for this is that the fewer data structures there are, the less users
will have to remember. This will also make the system more accessible
to non-experts. Finally, I want to reevaluate the whole idea of a
SWIG module is and expand the definition to include just about
anything from parsers, preprocessors, optimizers, interface editors,
and code generators.
<p>
The rest of this document outlines a few general rules of how code
should be developed within the SWIG project. These rules are
primarily drawn from my own experience developing software and
observing the practices of other successful projects.
<a name="2" href="#i2">
<h2>2. Programming Languages and Libraries </h2>
</a>
All SWIG modules must be written in either ANSI C or one of the
scripting languages for which SWIG can generate an interface (e.g.,
Perl, Python, or Tcl). C++ is currently being used to write
SWIG modules, but it is only being utilized to avoid working with
a lot of pointers to functions. <b>Advanced C++ features like namespaces, templates,
and overloading should not be used.</b>.
<p>
Module writers should make every attempt to use only those functions
described in the POSIX.1 standard. This includes most of the
functions contained the Kernighan and Ritchie C programming book. Use
of operating system dependent functionality such as socket libraries
should always be included inside a conditional compilation block so
that it can be omitted on problematic platforms. If you are unsure
about a library call, check the man page or contact Dave.
<a name="3" href="#i3">
<h2>3. The Source Directory and Module Names</h2>
</a>
All SWIG modules are contained within the "Source" directory. Within
this directory, each module is placed into its own subdirectory. The
name of this subdirectory should exactly match the name of the module.
For example, if you are creating a module called "Tcl", all of your
files should be placed in a directory "Tcl".
<p>
When choosing a module name, please pick a name that is not
currently in use. As a general convention, the first letter of a
module name is capitalized such as "Perl". Alternatives such as
"perl" or "PERL" should be avoided. In certain instances, the first
two letters may be capitalized as in "CParse." The exact usage of
this is somewhat inconsistent and isn't terribly important--just make
sure the first letter is capitalized. Also, module names should not
start with numbers, include underscores or any other special
non-alphanumeric characters.
<a name="5" href="#i5">
<h2>5. File Structure </h2>
</a>
Each file in a module should be given a filename that is all lowercase letters
such as "parser.c", not "Parser.c" or "PARSER.c". Please note that filenames
are case-insensitive on Windows so this convention will prevent you from inadvertently
creating two files that differ in case-only.
<p>
Each file should include a short abstract and license information
like this:
<blockquote>
<pre>
/* -----------------------------------------------------------------------------
* This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
* included with the SWIG source code as distributed by the SWIG developers
* and at http://www.swig.org/legal.html.
*
* xxx.c
*
* This file defines ...
* ----------------------------------------------------------------------------- */
#include "swig.h"
/* Declarations */
typedef struct {
int x, y;
} Foo;
...
/* Private Declarations (used only in this file) */
static int avariable;
...
/* Functions */
...
</pre>
</blockquote>
<p>
As a general rule, files start to get unmanageable once they exceed
about 2000 lines. Files larger than this should be broken up into
multiple files. Similarly, you should avoid the temptation to create
many small files as this increases compilation time and makes the
directory structure too complicated.
<a name="6" href="#i6">
<h2>6. Bottom-Up Design </h2>
</a>
Within each source file, the preferred organization is to use what is
known as "bottom-up" design. Under this scheme, lower-level functions
appear first and the highest level function appears last. The easy
way to remember is that the "main" function of your module should
always appear last in the source file. For example:
<blockquote>
<pre>
/* Simple bottom-up program */
#include &lt;stdio.h&gt;
int foo(int x, int y) {
/* Implement foo */
...
}
int bar() {
...
foo(i,j);
...
}
...
int main(int argc, char **argv) {
...
bar();
...
}
</pre>
</blockquote>
This choice of design is somewhat arbitrary however it has a number of
benefits particular to C. In particular, a bottom-up design generally
eliminates the need to include forward references--resulting in
cleaner code and fewer compilation errors.
<a name="7" href="#i7">
<h2>7. Functions</h2>
</a>
All functions should have a function header that gives the function name
and a short description like this:
<blockquote>
<pre>
/* -------------------------------------------------------------------------
* Swig_add_directory()
*
* Adds a directory to the SWIG search path.
* ------------------------------------------------------------------------- */
void
Swig_add_directory(DOH *dirname) {
...
}
</pre>
</blockquote>
In the function declaration, the return type and any specifiers
(extern or static) should appear on a separate line followed by the
function name and arguments as shown above. The left curly brace
should appear on the same line as the function name.
<p>
Function declarations should <b>NOT</b> use the pre-ANSI function
declaration syntax. The ANSI standard has been around long enough for
this to be a non-issue.
<a name="8" href="#i8">
<h2>8. Naming Conventions</h2>
</a>
The following conventions are used to name various objects throughout SWIG.
<h4>Functions</h4>
Functions should consist of the module name and the function name separated by an underscore like this:
<blockquote>
<pre>
Preprocessor_define()
Swig_add_directory()
</pre>
</blockquote>
In general, the module name should match the name of the module
subdirectory and the function name should be in all lowercase with
words separated by underscores.
<h4>Structures and Types</h4>
If your module defines new structures, the structure name should include the name of the
module and the name of the structure appended together like this:
<blockquote>
<pre>
typedef struct SwigScanner {
...
} SwigScanner;
typedef struct LParseType {
...
} LParseType;
</pre>
</blockquote>
In this case, both the name of the module and the type should be capitalized. Also, whenever
possible, you should use the "typedef struct Name { ... } Name" form when defining new
data structures.
<h4>Global Variables</h4>
Global variables should be avoided if at all possible. However, if you must use a global
variable, please prepend the module name and use the same naming scheme as for functions.
<h4>Constants</h4>
Constants should be created using #define and should be in all caps like this:
<blockquote>
<pre>
#define SWIG_TOKEN_LPAREN 1
</pre>
</blockquote>
Separate words in a constant should be separated by underscores as with functions.
<h4>Structure members</h4>
Structure members should be in all lower-case and follow the same word-separation convention
as for function names. However, the module name does not have to be included.
For example:
<blockquote>
<pre>
typedef struct SwigScanner {
DOH *text; /* Current token value */
DOH *scanobjs; /* Objects being scanned */
DOH *str; /* Current object being scanned */
char *idstart; /* Optional identifier start characters */
int next_token; /* Next token to be returned */
int start_line; /* Starting line of certain declarations */
int yylen; /* Length of text pushed into text */
DOH *file; /* Current file name */
} SwigScanner;
</pre>
</blockquote>
<h4>Static Functions and Variables </h4>
Static declarations are free to use any naming convention that is appropriate. However, most
existing parts of SWIG use lower-case names and follow the same convention as described for functions.
<a name="9" href="#i9">
<h2>9. Visibility</h2>
</a>
Modules should keep the following rules in mind when exposing their internals:
<ul>
<li>Only publicly accessible functions should be included in the module header file.
<li>All non-static declarations must be prepended with some form of the module name
to avoid potential linker namespace conflicts with other modules.
<li>Modules should not expose global variables or use global variables in their
public interface.
<li>Similarly, modules should discourage the direct manipulation of data contained
within data structures in favor of using function calls instead. For example,
instead of providing a user with a structure like this:
<blockquote>
<pre>
typedef struct Foo {
int line;
} Foo;
</pre>
</blockquote>
It is better to hide the implementation of Foo and provide an
function-call interface like this:
<blockquote>
<pre>
typedef struct Foo Foo;
extern int Foo_getline(Foo *f);
extern void Foo_setline(Foo *f, int line);
</pre>
</blockquote>
Although this results in worse performance, there are many practical
reasons for doing this. The most important reason is that it allows
you to change the internal representation of Foo without breaking all
of the other modules or having to recompile the entire universe after
making your changes.
</ul>
<a name="10" href="#i10">
<h2>10. Miscellaneous Coding Guidelines</h2>
</a>
These are largely covered in the main documentation in the Extending.html file.
<a name="11" href="#i11">
<h2>11. Git Tagging Conventions</h2>
</a>
Use <tt>git tag</tt> to declare some set of file revisions as related in some
symbolic way. This eases reference, retrieval and manipulation of these files
later. At the moment (2001/01/16 14:02:53), the conventions are very simple;
let's hope they stay that way!
<p>
There are two types of tags, internal (aka personal) and external.
Internal tags are used by SWIG developers primarily, whereas external
tags are used when communicating with people w/ anonymous git access.
<ul>
<li> Internal tags should start with the developer name and a hyphen.
<li> External tags should start with "rel-".
</ul>
That's all there is to it. Some example tags:
<ul>
<li> ttn-pre-xml-patch
<li> ttn-post-xml-patch
<li> ttn-going-on-vacation-so-dutifully-tagging-now
<li> rel-1.3.40
<li> rel-2.0.9
</ul>
<hr>
Copyright (C) 1999-2004 SWIG Development Team.
</body>
</html>

181
Doc/Devel/file.html Normal file
View File

@ -0,0 +1,181 @@
<html>
<head>
<title>SWIG File Handling</title>
</head>
<body>
<center>
<h1>SWIG File Handling</h1>
<p>
David M. Beazley <br>
dave-swig@dabeaz.com<br>
December, 2006<br>
</b>
</center>
<h2>Introduction</h2>
This document describes the functions related to file and filename handling in the SWIG core. These functions are
defined in the header file <tt>Source/Swig/swigfile.h</tt>. This API is considered to be stable.
<h2>File Search Path</h2>
These functions manipulate the search path for locating files.
<p>
<b><tt>List *Swig_add_directory(const String_or_char *dirname)</tt></b>
<blockquote>
Adds a new directory to the system search path. The directory is appended to
the end of the search path. Returns a list containing the current
system search path.
</blockquote>
<p>
<b><tt>void Swig_push_directory(const String_or_char *dirname)</tt></b>
<blockquote>
Pushes a temporary directory onto the search path. This directory is searched before
directories added with <tt>Swig_add_directory()</tt> except when including a system
file explicitly (either using #include &lt;file&gt; or calling <tt>Swig_include_sys()</tt>).
This function is normally used by the preprocessor to add temporary directories when
processing #include statements.
</blockquote>
<p>
<b><tt>void Swig_pop_directory()</tt></b>
<blockquote>
Pops off the last pushed directory with <tt>Swig_push_directory()</tt>
</blockquote>
<p>
<b><tt>int Swig_get_push_dir()</tt></b>
<blockquote>
Returns a flag that indicates whether directory pushing is enabled or not.
</blockquote>
<p>
<b><tt>void Swig_set_push_dir(int dopush)</tt></b>
<blockquote>
Enables or disables directory pushing. By default, it is turned on. However, the <tt>-I-</tt> command line
option to SWIG disables it.
</blockquote>
<p>
<b><tt>List *Swig_search_path()</tt></b>
<blockquote>
Returns the current search path.
</blockquote>
<h2>File access functions</h2>
<p>
<b><tt>FILE *Swig_open(const String_or_char *name)</tt></b>
<blockquote>
Opens a file, using the applicable search paths, and returns an open <tt>FILE *</tt> object if found. Returns NULL if the file is not found.
</blockquote>
<p>
<b><tt>String *Swig_read_file(FILE *f)</tt></b>
<blockquote>
Reads all of the data from an open file into a string which is returned.
</blockquote>
<p>
<b><tt>String *Swig_include(const String_or_char *name)</tt></b>
<blockquote>
Searches for an include file <tt>name</tt> and returns its contents as
a string if found. Returns NULL if not found. All of the applicable
search paths are searched when trying to locate the file.
</blockquote>
<p>
<b><tt>String *Swig_include_sys(const String_or_char *name)</tt></b>
<blockquote>
Searches for an include file <tt>name</tt> and returns its contents as
a string if found. Returns NULL if not found. All of the applicable
search paths are searched when trying to locate the file, but
preference is given to system paths first. This mimics the behavior
of <tt>#include &lt;file&gt;</tt> in the preprocessor.
</blockquote>
<p>
<b><tt>int Swig_insert_file(const String_or_char *name, File *outfile)</tt></b>
<blockquote>
Searches for a file <tt>name</tt> and dumps its contents to <tt>outfile</tt> if found.
Returns 0 on success, -1 if the file couldn't be found.
</blockquote>
<h2>Query functions</h2>
<p>
<b><tt>String *Swig_last_file()</tt></b>
<blockquote>
Returns the full pathname of the file last opened or included.
</blockquote>
<h2>Named files</h2>
<p>
<b><tt>void *Swig_register_filebyname(const String_or_char *filename, File *outfile)</tt></b>
<blockquote>
Registers a file object <tt>outfile</tt> with a specific name <tt>filename</tt>. This function is
used to implement the SWIG %insert directive and to manage different sections of the output
file such as "runtime","header","wrapper","init", etc. Different language modules may add their own
sections for generating Python code, Perl code, etc.
</blockquote>
<p>
<b><tt>File *Swig_filebyname(const String_or_char *filename)</tt></b>
<blockquote>
This looks up a file object previously registered using <tt>Swig_register_filebyname()</tt>. This
is used to implement the %insert directive.
</blockquote>
<h2>Filename utilities</h2>
<p>
<b><tt>char *Swig_file_suffix(const String_or_char *filename)</tt></b>
<blockquote>
Returns the suffix of a filename. For instance, if the filename is "foo.txt", it returns ".txt".
</blockquote>
<p>
<b><tt>char *Swig_file_basename(const String_or_char *filename)</tt></b>
<blockquote>
Returns the filename without the suffix attached to it. For instance, if the filename is "foo.txt", it returns
"foo". The result is stored in a static variable. If you need to save it, make your own copy.
</blockquote>
<p>
<b><tt>char *Swig_file_filename(const String_or_char *filename)</tt></b>
<blockquote>
Returns the filename without any leading directories. For instance, if the filename is "/bar/spam/foo.txt", it
returns "foo.txt". This function is aware of local naming conventions on the machine (e.g., forward versus back slashes on Unix and Windows). The result is stored in a static variable. If you need to save the value, make a copy.
</blockquote>
<p>
<b><tt>char *Swig_file_dirname(const String_or_char *filename)</tt></b>
<blockquote>
Returns the directory name (if any). For instance, if the filename is "/bar/spam/foo.txt", it
returns "/bar/spam/". This function is aware of local naming conventions on the machine (e.g., forward versus back slashes on Unix and Windows). The result is stored in a static variable. If you need to save the value, make a copy.
</blockquote>
<p>
<b><tt>SWIG_FILE_DELIMITER</tt></b>
<blockquote>
This macro contains the file delimiter string for the local machine. On Unix it is "/", on Windows it is "\\".
</blockquote>
</body>
</html>

31
Doc/Devel/index.html Normal file
View File

@ -0,0 +1,31 @@
<html>
<head>
<title>SWIG Documentation</title>
</head>
<body>
This directory contains SWIG documentation:
<ul>
<li><a href="engineering.html">Engineering Manual</a>
<li><a href="internals.html">Internals Manual</a>
<li><a href="migrate.txt">SWIG1.3 Migration Guide</a>
</ul>
The following documentation describe the internal APIs used by SWIG. These may be useful to module developers.
<ul>
<li><a href="file.html">File handling functions</a>
<li><a href="cmdopt.html">Command line arguments</a>
<li><a href="tree.html">Parse tree navigation and manipulation</a>
<li><a href="parm.html">Parameter and Parameter list handling functions</a>
<li><a href="scanner.html">Generic C/C++ Scanner interface</a>
<li><a href="wrapobj.html">Wrapper objects</a>.
<li><a href="runtime.txt">SWIG Runtime</a>.
</ul>
<hr>
Copyright (C) 1999-2007 SWIG Development Team.
</body>
</html>

1215
Doc/Devel/internals.html Normal file

File diff suppressed because it is too large Load Diff

140
Doc/Devel/migrate.txt Normal file
View File

@ -0,0 +1,140 @@
SWIG1.3 Migration Guide
(The not entirely complete guide to updating language modules to work with SWIG1.3).
Dave Beazley
August 15, 2000
1. Introduction
---------------
Virtually all of SWIG's internal data structures have now been
rewritten. Take everything you thought you knew about SWIG1.1 and
throw it out.
2. DataTypes
------------
The old 'DataType' data structure is gone. Therefore, direct
manipulation of 'is_pointer', 'implicit_ptr', and 'arraystr'
attributes no longer applies. Sorry.
Datatypes are now represented by the type 'SwigType' which has no
public attributes. Actually, if you look at it closely, 'SwigType' is
really just an alias for 'void' and if you look at it even closer than
that you will realize that it's nothing more than a string!
The string encoding of types is described in more detail in the file
Source/Swig/stype.c and is not so important here. What is important is
the functions used to produce various types of output:
SwigType_str(type,name = 0);
This produces an exact C representation of the datatype with all
qualifiers, arrays, references, and so forth. name is an optional
name that is given if you wanted to associate the type with a
parameter name or something.
SwigType_lstr(type,name = 0);
This function takes a type and produces a C string containing
a type suitable for assignment (appearing as an lvalue in an
expression). To do this, certain things such as 'const',
arrays, and references are stripped away or converted into
pointers.
SwigType_ltype(type);
Returns a SwigType object corresponding to the type created
by SwigType_lstr().
SwigType_lcaststr(type,name);
Produces a string casting a value 'name' from the real datatype
to the assignable type created by SwigType_lstr().
SwigType_rcaststr(type,name)
Produces a string that casts a value 'name' from the type
created by SwigType_lstr() to the real datatype.
SwigType_manglestr(type)
Produces the 'mangled' version of a datatype.
Getting the 'type' code. Most language modules still operate by
looking at special integer type codes. This interface is a little
ragged and will probably go away at some point. However, for now the
following function can be used to get the type code:
int SwigType_type(type)
The codes are the same as the before, except that there are a few
special codes:
T_STRING - The 'char *' type and variations.
T_POINTER - Any pointer type (not char * though)
T_REFERENCE - Any C++ reference
T_ARRAY - Any array
T_FUNCTION - A function (this is usually an error).
Because of the special codes, it is no longer necessary to have code like this:
if ((t->is_pointer == 1) and (t->type == T_CHAR)) {
... get a string ...
}
Instead, just use the type code above like this:
switch(SwigType_type(type)) {
case T_STRING:
... get a string ...
break;
case T_POINTER:
... get a pointer ...
break;
}
There are about 2-dozen type manipulation functions that could also be useful.
See Source/Swig/swig.h and Source/Swig/stype.c.
3. Parameter Lists
------------------
The ParmList data structure is gone. In reality, parameter lists are nothing more than
a linked list of parameters. The proper way to iterate over this list and get
parameter values is as follows:
ParmList *l;
Parm *p;
for (p = l; p; p = Getnext(p)) {
SwigType *pt = Gettype(p); /* Get parameter type */
String *pn = Getname(p); /* Get parameter name */
String *value = Getvalue(p); /* Get parameter value */
...
do whatever
...
}
4. Typemaps
-----------
Typemaps more or less work. However, the interface has changed slightly. Instead of
typemap_lookup("in","python",type,pname,"$source","$target",wrapper);
the function is
Swig_typemap_lookup("in",type,pname,"$source","$target",wrapper);
There are a variety of other changes to typemaps (see CHANGES).
5. Use of new types
-------------------
When possible, language modules should try to use the built in String,
List, and Hash objects instead of C arrays or 'char *'. This will probably require a
detailed pass through the code with an eye towards cleanup.
6. Miscellaneous
----------------
Language modules no longer need to concern themselves with formatting the
wrapper code they produce (provided you are using the special Wrapper object).
The function Wrapper_print() passes everything through a pretty-printer that
automatically performs indentation and tries to clean things up. This especially
works well when there are lots of typemaps.

102
Doc/Devel/parm.html Normal file
View File

@ -0,0 +1,102 @@
<html>
<head>
<title>SWIG Parameter Handling</title>
</head>
<body>
<center>
<h1>SWIG Parameter Handling</h1>
<p>
David M. Beazley <br>
dave-swig@dabeaz.com<br>
January 9, 2007<br>
</b>
</center>
<h2>Introduction</h2>
This document describes the functions related to management of function parameters and parameter lists in the SWIG core. These functions are declared in <tt>Source/Swig/swigparm.h</tt>. This API is considered to be stable.
<h2>Parameters</h2>
The following utility functions are used to create and copy individual parameters. In their most basic form, a parameter merely contains a type, a name, and an optional default value.
<p>
<b><tt>Parm *NewParm(SwigType *type, const String_or_char *name)</tt></b>
<blockquote>
Creates a new parameter object with type <tt>type</tt> and name <tt>name</tt>. The type is stored in the attribute "type" and the name is stored in the attribute "name".
</blockquote>
<p>
<b><tt>Parm *CopyParm(Parm *p)</tt></b>
<blockquote>
Copies a parameter object. All string attributes are copied in the
process of making the copy. However, no complex attributes (lists,
hashes, etc.) are copied.
</blockquote>
<h2>Parameter Lists</h2>
<p>
<b><tt>ParmList *CopyParmList(ParmList *p)</tt></b>
<blockquote>
Creates a copy of a parameter list. A parameter list is merely a linked list of parameters created by NewParm().
</blockquote>
<p>
<b><tt>ParmList *CopyParmListMax(ParmList *p, int count)</tt></b>
<blockquote>
Copies at most <tt>count</tt> parameters from the parameter list <tt>p</tt>.
</blockquote>
<p>
<b><tt>int ParmList_len(ParmList *p)</tt></b>
<blockquote>
Returns the total number of parameters in a parameter list.
</blockquote>
<p>
<b><tt>int ParmList_numrequired(ParmList *p)</tt></b>
<blockquote>
Returns the number of required parameters in a parameter list. This pertains to invoking a function/method in C/C++.
</blockquote>
<p>
<b><tt>int ParmList_has_defaultargs(ParmList *p)</tt></b>
<blockquote>
Returns 1 if the parameter list has any default arguments. Otherwise returns 0.
</blockquote>
<h2>Code Generation Functions</h2>
<p>
<b><tt>String *ParmList_str(ParmList *p)</tt></b>
<blockquote>
Creates a C prototype string of the parameters, but without any default values.
</blockquote>
<p>
<b><tt>String *ParmList_str_defaultargs(ParmList *p)</tt></b>
<blockquote>
Creates a C prototype string of the parameters and includes the default values (if any).
</blockquote>
<p>
<b><tt>String *ParmList_protostr(ParmList *p)</tt></b>
<blockquote>
Creates a C prototype string of the parameters.
</blockquote>
</body>
</html>

View File

@ -0,0 +1,341 @@
Project Plan
============
SWIG Code Comments
Google Summer of Code 2012
This document describes goals for the Google Summer of Code 2012,
SWIG code documentation project.
Author: Marko Klopcic, Dmitry Kabak
Introduction
============
The goal of this project is _not_ to translate _any_ possible Doxygen
formatted comment to JavaDoc or PyDoc, but to make it possible to
translate a subset of comment types in C/C++ code to
JavaDoc and PyDoc. Covering all the Doxygen functionality would be to
complex for the limited time. However, the code must be flexible so
that implementing missing features would not require redesign of the
comment handling code in SWIG.
There will also be a possibility to add untranslated comments to Java
and Python code (## comments, see Doxygen manual), if the user will
prefer to use Doxygen on the generated code.
Note:
'-OK-' tick below means that the item is implemented, committed and
working.
Abbreviations:
JD - JavaDoc
PD - PyDoc
Functionality
=============
Types of comments
-----------------
Note:
See 'http://www.stack.nl/~dimitri/doxygen/docblocks.html' for
the detailed description of Doxygen syntax and terms used in this
section.
1. -OK- Only JavaDoc (/** */) and Qt (/*! */) styles of comment blocks
will be supported by SWIG translator.
2. -OK- The following doc after members will be supported:
int var; ///< Detailed description after the member
//!<
int var; //!< Brief description after the member
int var; ///< Brief description after the member
3. -OK- Only comments before or after declaration/definition will be
supported. Comments with structural commands will be ignored
(warning will be written). (What about writing them to
'package.info.java' for JD?)
Tags
----
This section contains all doxygen tags taken from
http://www.stack.nl/~dimitri/doxygen/commands.html. If a tag is
marked as 'ignored', then the tag is ignored, but the text is copied
to the destination documentation. 'Not implemented' means that the
tag with it's contents is stripped out of the output.
Doxygen tags:
All tags: -OK-
\a - translated to <i></i> in JD, surrounded with _ in PD
\addindex - ignored
\addtogroup - ignored
\anchor - ignored, not supported by JD and PD
\arg - equivalent to \li
\attention - ignored
\authors, \author - translated to @author in JD, 'Author:' in PD
\b - <b></b> in JD, surrounded with __ in PD
\brief - ignored
\bug - ignored
\c - translated to <code></code> in JD, ignored in PD
\callgraph - ignored, not supported by JD and PD
\callergraph - ignored, not supported by JD and PD
\category - ignored, used only in Objective C
\cite - translated to <i></i> in JD, single quotes in PD
\class - ignored (structural command)
\code - translated to {@code ...} in JD, ignored in PD
\cond - translated to 'Conditional comment: <condition>'. Later
SWIG may support definitions of conditions in config file.
\copybrief - ignored. Later SWIG may support this command by
performing copy
\copydetails - ignored. Later SWIG may support this command by
performing copy
\copydoc - ignored. Later SWIG may support this command by
performing copy
\copyright - replaced with text 'Copyright' in PD and PD
\date - ignored
\def - ignored (structural command)
\defgroup - not supported
\deprecated - translated to @deprecated in JD, 'Deprecated:' in PD
\details - ignored
\dir - not supported
\dontinclude - not supported
\dot - not supported. Later SWIG may call dot and produce the graph image
to include in JD and PD
\dotfile - see note for \dot
\e - equivalent \a
\else - see note for \cond
\elseif - see note for \cond
\em - equivalent to \a
\endcode - see note for \code
\endcond - translated to 'End of conditional comment: <condition>'. Later
SWIG may support definitions of conditions in config file.
\enddot - see note for \dot
\endhtmlonly - ignored
\endif - see note for \cond
\endinternal - ignored
\endlatexonly - ignored
\endlink - see note for \link
\endmanonly - ignored
\endmsc - see note for \msc
\endrtfonly - ignored
\endverbatim - see note for \verbatim
\endxmlonly - ignored
\enum - ignored (structural command)
\example - translated to 'Example:' in JD and PD
\exception - equivalent to throws, but translates to @exception in JD
\extends - not supported
\f$ - ignored. Later swig may call LATeX to produce bitmaps with formulas
to include in JD and PD
\f[ - see note for \f$
\f] - see note for \f$
\f{ - see note for \f$
\f} - see note for \f$
\file - ignored (structural command)
\fn - ignored (structural command)
\headerfile - not supported
\hideinitializer - not supported
\htmlinclude - not supported
\htmlonly - ignored
\if - see note for \cond
\ifnot - see note for \cond
\image - translated to <img/> in JD only when target=HTML, translated to
'Image: filename(Title)'
\implements - not supported
\include - not supported
\includelineno - not supported
\ingroup - not supported. Later swig may print group names as plain text
in comments like 'Code group: something' in both JD and PD
\internal - ignored
\invariant - ignored
\interface - ignored (structural command)
\latexonly - ignored
\li - trabslated to <li></li> in JD, ignored in PD
\line - not supported
\link - translated to {@link ...} in JD, ignored in PD
\mainpage - ignored
\manonly - ignored
\memberof - not supported
\msc - not supported. Later SWIG may call dot and produce the graph image
to include in JD and PD
\mscfile - see note for \msc
\n - prints the new line
\name - ignored
\namespace - included in package-info.java if nspace feature is enabled,
otherwise ignored, ignored in PD
\nosubgrouping - ignored
\note - translated to 'Note:' in both JD and PD
\overload - prints 'This is an overloaded member function, provided for
convenience. It differs from the above function only in what
argument(s) it accepts.' to the output in both JD and PD
\p - equivalent to \c
\package - is kept same in JD (it is already a JD tag), ignored in PD
\page - ignored
\par - translated to <p alt='title'></p> in JD, 'Title: ...' in PD
\paragraph - ignored
\param - translated to @param in JD, special formatting in PD
\post - ignored
\pre - ignored
\private - ignored
\privatesection - ignored
\property - ignored
\protected - ignored
\protectedsection - ignored
\protocol - ignored (Objective-C tag)
\public - ignored
\publicsection - ignored
\ref - ignored, not supported by JD and PD
\related - ignored
\relates - ignored
\relatedalso - ignored
\relatesalso - ignored
\remark - translated to 'Remarks:' in both JD and PD
\remarks - equivalent to remark
\result - translated to @return in JD, 'Return:' in PD
\return - equivalent to result
\returns - equivalent to result
\retval - ignored
\rtfonly - ignored
\sa - translated to @see in JD, 'See also:' in PD
\section - not supported
\see - equivalent to \sa
\short - equivalent to \brief
\showinitializer - not supported
\since - translated to @since in JD, 'Since:' in PD
\skip - not supported
\skipline - not supported
\snippet - not supported
\struct - ignored (structural command)
\subpage - not supported
\subsection - not supported
\subsubsection - not supported
\tableofcontents - not supported
\test - ignored
\throw - translated to @throws in JD, 'Throws:' in PD
\throws - equivalent to \throw
\todo - translated to 'TODO:' in both JD and PD
\tparam - similar to \arg
\typedef - ignored (structural command)
\union - ignored (structural command)
\until - not supported
\var - ignored (structural command)
\verbatim - translated to {@literal ...} in JD, ignored in PD
\verbinclude - ignored
\version - translated to @version in JD, 'Version:' in PD
\warning - translated to 'Warning:' in both JD and PD
\weakgroup - not supported
\xmlonly - ignored
\xrefitem - ignored
\$ - this and all the others below: these commands insert single char,
it is escaped as HTML char in JD, kept as-is in PD
\@
\\
\&
\~
\<
\>
\#
\%
\"
\.
\::
Optional functionality
======================
That section describes some complex cases where the current code
does not behave really well. Like a short to-do list of special cases.
-OK- When translating functions with default parameters in swig to
java, it creates overloaded functions with all the parameters
except the default ones. We need to copy the doxygen comment to
such functions and correct the list of @param tags.
-OK- In doxygen there is a special tags (and even a special option)
to create links to some code members from the current comment.
Sometimes it needs a type of parameters specified because of the
overloaded functions. And the same linking tags are supported in JD,
but it has a completely different typesystem, so we need to translate
the types of function parameters in comments also. For example:
{@link MyClass#doSomething(const std::string &)}
does not make sense in Java, so the type should be converted.
{@link MyClass#doSomething(String)}
Tests
=====
The following test cases will be implemented:
-OK- Class comments.
-OK- Struct comments.
-OK- Enum comments.
-OK- Function comments.
-OK- Var comments.
-OK- Class attributes, comment before and after declaration.
-OK- Class methods, comment of parameters in function
comment.
-OK- Class methods, comment of parameters
after parameter declaration.
-OK- Struct attributes, comment before and after declaration.
-OK- Struct methods, comment of parameters in function
comment.
-OK- Struct methods, comment of parameters
after parameter declaration.
-OK- Enum items JD and Qt style, comment before items
-OK- Enum items JD and Qt style, comment after items
-OK- Class comment, with all supported tags.
-OK- Class comment, with all doxygen tags, including
ignored ones.
The list of all tests, in form of shell commands to make it simple
to test project by copying the text below into terminal program.
make doxygen_parsing.cpptest -s
make doxygen_translate.cpptest -s
make doxygen_translate_all_tags.cpptest -s
make doxygen_basic_translate.cpptest -s
make doxygen_basic_notranslate.cpptest -s
make doxygen_translate_links.cpptest -s
make doxygen_tricky_constructs.cpptest -s
Refactoring
===========
All the code in directory _Doxygen_ should be refactored:
-OK- all methods should be class members
-OK- most static methods should be normal members
-OK- replace C arrays of strings and sequential searches with STL data
structures and algorithms.
-OK- use singletons instead of class instantiaion for each comment found.
Documentation
=============
SWIG documentation will contain:
-OK- command line options
-OK- list of implemented features (types and placements of comments)
-OK- list of unimplemented features (types and placements of comments)
-OK- list of tags and their translations (all Doxygen tags).
-OK- some amount of debugging and development information

169
Doc/Devel/runtime.txt Normal file
View File

@ -0,0 +1,169 @@
This file describes the necessary functions and interfaces a language module
needs to implement to take advantage of the run time type system. I assume you
have read the run-time section of the Typemaps chapter in the SWIG
documentation.
Last updated: February 23, 2005
The file we are concerned with here should be named langrun.swg. A good example
of a simple file is the Lib/mzscheme/mzrun.swg file. First, a few requirements
and notes:
1) Every function in this file should be declared static.
2) It should be inserted into the runtime section of the _wrap file from your
config file. The Lib/swigrun.swg file should be included before this file.
That is, you need to have
%runtime "swigrun.swg"
%runtime "langrun.swg"
3) You must also include the swiginit.swg file in the init section of the
wrapper. That is, you should have
%insert(init) "swiginit.swg"
4) From module.cxx, you need to call the SwigType_emit_type_table function, as
well as register types with SwigType_remember or SwigType_remember_clientdata
5) By convention, all functions in this file are of the form
SWIG_Language_Whatever, and #defines are used to rename SWIG API functions to
these function names
6) You need to call void SWIG_InitializeModule(void *clientdata) from your init
function.
7) You need to implement the runtimeCode() and defaultExternalRuntimeFilename()
functions inside module.cxx. runtimeCode should return all the language
specific runtime code as a string, and defaultExternalRuntimeFilename should
return a string for the default name of the external runtime header. This is
usually "swigpyrun.h", where "py" is replaced by the language name. These
two functions are used by the -external-runtime argument.
-------------------------------------------------------------------------------
Required Functions
-------------------------------------------------------------------------------
swig_module_info *SWIG_GetModule(void *clientdata);
void SWIG_SetModule(void *clientdata, swig_module_info *mod);
The SetModule function should store the mod argument into some globally
accessible variable in the target language. The action of these two functions
is to provide a way for multiple modules to share information. The SetModule
function should create a new global var named something like
"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME
SWIG_RUNTIME_VERSION is currently defined as "2", and SWIG_TYPE_TABLE_NAME is
defined by the -DSWIG_TYPE_TABLE=mytable option when compiling the wrapper.
Alternatively, if the language supports modules, a module named
"swig_runtime_data" SWIG_RUNTIME_VERSION can be created, and a global variable
named "type_table" SWIG_TYPE_TABLE_NAME can be created inside it. The most
common approach is to store the mod pointer in some global variable in the
target language, but if the language provides an alternative place to store data
then that is good too.
The way the code is set up, SetModule should only be called when GetModule
returns NULL, and if SetModule is called a second time, the behavior is
undefined. Just make sure it doesn't crash in the random chance occurrence that
SetModule is called twice.
There are two options here.
1) The preferred approach is for GetModule and SetModule to not require a
clientdata pointer. If you can at all avoid it, please do so. Here, you would
write swig_module_info *SWIG_Language_GetModule();
void SWIG_Language_SetModule(swig_module_info *mod);
and then add
#define SWIG_GetModule(clientdata) SWIG_Language_GetModule()
#define SWIG_SetModule(cd, ptr) SWIG_Language_SetModule(ptr)
You would then call
SWIG_InitializeModule(0)
2) If GetModule and SetModule need to take a custom pointer (most notably an
environment pointer, see tcl or mzscheme), then you should write
swig_module_info *SWIG_Language_GetModule(void *clientdata)
void SWIG_Language_SetModule(void *clientdata, swig_module_info *mod);
and also define
#define SWIG_GetModule(cd) SWIG_Language_GetModule(cd)
#define SWIG_SetModule(cd, ptr) SWIG_Language_SetModule(cd, ptr)
#define SWIG_MODULE_CLIENTDATA_TYPE Whatever
SWIG_MODULE_CLIENTDATA_TYPE should be defined to whatever the type of
clientdata is.
You would then call SWIG_InitializeModule(clientdata), and clientdata would get
passed to GetModule and SetModule. clientdata will not be stored and will only
be referenced during the InitializeModule call. After InitializeModule returns,
clientdata does not need to be valid any more.
This method is not preferred, because it makes external access to the type
system more complicated. See the Modules chapter of the documentation, and read
the "External access to the run-time" section. Then take a look at
Lib/runtime.swg. Anybody that calls SWIG_TypeQuery needs to pass along the
clientdata pointer, and that is the reason for defining
SWIG_MODULE_CLIENTDATA_TYPE.
-------------------------------------------------------------------------------
Standard Functions
-------------------------------------------------------------------------------
These functions are not required and their API is not formalized, but almost all
language modules implement them for consistency across languages. Throughout
this discussion, I will use LangType to represent the underlying language type
(Scheme_Object * in mzscheme, PyObject * in python, etc)
LangObj SWIG_NewPointerObj(void *ptr, swig_type_info *type, int flags);
Create and return a new pointer object that has both ptr and type. For almost
all language modules, flags is used for ownership. If flags==1, then the
created pointer should be registered to be garbage collected.
int SWIG_ConvertPtr(LangType obj, void **result, swig_type_info *type, int flags);
Convert a language wrapped pointer into a void *. The pointer is returned in
result, and the function should return 0 on success, non-zero on error.
A sample ConvertPtr is given here:
swig_cast_info *cast;
if (<obj is a wrapped pointer type>) {
cast = SWIG_TypeCheck(<obj type name>, type);
cast = SWIG_TypeCheckStruct(<obj type structure>, type);
if (cast) {
*result = SWIG_TypeCast(cast, <obj pointer>);
return 0;
}
}
return 1;
Either TypeCheck or TypeCheckStruct can be called, depending on how the pointer
is wrapped in langtype. If obj stores the void pointer and the type name, then
the TypeCheck function should be used, while if obj stores the void pointer and
a pointer to the swig_type_info structure, then the TypeCheckStruct function
should be called. The TypeCheckStruct is slightly faster, since it does a
pointer comparison instead of a strcmp.
The flag argument to ConvertPtr is used in some languages for disowning a
pointer. If the wrapped C function is taking ownership of the pointer (that
means, the wrapped C function is responsible for deleting the object), then that
pointer should be removed from the garbage collector. We do that in the
ConvertPtr function. The pointer is still valid in the target language, but
when the target language type is garbage collected, it will not call the
associated destructor. Languages have a special typemap called DISOWN that can be
applied which passes this argument. All the languages have the flags argument
for consistency, and the flags argument can be ignored or used for some other
purpose.
void *SWIG_MustGetPtr(LangType obj, swig_type_info *type, int flags,
int argnum, const char *func_name) {
void *result;
if (SWIG_ConvertPtr(s, &result, type, flags)) {
generate runtime type error ("Error in func_name, expected a" +
type->str ? type->str : "void *" +
"at argument number" + argnum);
}
return result;
}
This function is optional, and the number and type of parameters can be
different, but is useful for typemap purposes:
%typemap(in) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] {
$1 = ($1_ltype)SWIG_MustGetPtr($input, $descriptor, 0, $argnum, FUNC_NAME);
}

283
Doc/Devel/scanner.html Normal file
View File

@ -0,0 +1,283 @@
<html>
<head>
<title>SWIG C Scanner</title>
</head>
<body>
<center>
<h1>SWIG C/C++ Scanning</h1>
<p>
David M. Beazley <br>
dave-swig@dabeaz.com<br>
January 11, 2007<br>
</b>
</center>
<h2>Introduction</h2>
This document describes functions that can be used to tokenize C/C++
input text. These functions are relatively low-level and are meant to
be used in the implementation of scanners that can be plugged into yacc or used for
other purposes. For instance, the preprocessor uses these functions to evaluate and test
constant expressions.
<p>
All of these functions are declared in <tt>Source/Swig/swigscan.h</tt>. This API is considered to be stable.
<h2>Creation and Deletion of Scanners</h2>
The following functions are used to create and destroy a scanner object. More than one scanner object can be created and used
as necessary.
<p>
<b><tt>Scanner *NewScanner()</tt></b>
<blockquote>
Creates a new scanner object. The scanner contains initially contains no text. To feed text to the scanner use <tt>Scanner_push()</tt>.
</blockquote>
<p>
<b><tt>Scanner *DelScanner()</tt></b>
<blockquote>
Deletes a scanner object.
</blockquote>
<h2>Scanner Functions</h2>
<p>
<b><tt>void Scanner_clear(Scanner *s)</tt></b>
<blockquote>
Clears all text from the scanner. This can be used to reset a scanner to its initial state, ready to receive new input text.
</blockquote>
<p>
<b><tt>void Scanner_push(Scanner *s, String *text)</tt></b>
<blockquote>
Pushes an input string into the scanner. Subsequent tokens will be
returned from the new string. If the scanner is already processing a
string, the pushed string takes precedence--in effect, interrupting
the scanning of the previous string. This behavior is used to
implement certain SWIG features such as the <tt>%inline</tt>
directive. Once the pushed string has been completely scanned, the
scanner will return to scanning the previous string (if any). The
scanning of text relies upon the DOH file interface to strings
(<tt>Getc()</tt>, <tt>Ungetc()</tt>, etc.). Prior to calling this
function, the input string should be set so that its file pointer is
in the location where you want scanning to begin. You may have to
use <tt>Seek()</tt> to set the file pointer back to the beginning of a
string prior to using this function.
</blockquote>
<p>
<b><tt>void Scanner_pushtoken(Scanner *s, int tokvalue, String_or_char *val)</tt></b>
<blockquote>
Pushes a token into the scanner. This exact token will be returned by the next call to <tt>Scanner_token()</tt>.
<tt>tokvalue</tt> is the integer token value to return and <tt>val</tt> is the token text to return. This
function is only used to handle very special parsing cases. For instance, if you need the scanner to
return a fictitious token into order to enter a special parsing case.
</blockquote>
<p>
<b><tt>int Scanner_token(Scanner *s)</tt></b>
<blockquote>
Returns the next token. An integer token code is returned (see table below) on success. If no more input text is
available 0 is returned. If a scanning error occurred, -1 is returned. In this case, error information can be
obtained using <tt>Scanner_errinfo()</tt>.
</blockquote>
<p>
<b><tt>String *Scanner_text(Scanner *s)</tt></b>
<blockquote>
Returns the scanned text corresponding to the last token returned by <tt>Scanner_token()</tt>. The returned string
is only valid until the next call to <tt>Scanner_token()</tt>. If you need to save it, make a copy.
</blockquote>
<p>
<b><tt>void Scanner_skip_line(Scanner *s)</tt></b>
<blockquote>
Skips to the end of the current line. The text skipped can be obtained using <tt>Scanner_text()</tt> afterwards.
</blockquote>
<p>
<b><tt>void Scanner_skip_balanced(Scanner *s, int startchar, int endchar)</tt></b>
<blockquote>
Skips to the end of a block of text denoted by starting and ending characters. For example, <tt>{</tt> and <tt>}</tt>. The
function is smart about how it skips text. String literals and comments are ignored. The function also is aware of nesting. The
skipped text can be obtained using <tt>Scanner_text()</tt> afterwards. Returns 0 on success, -1 if no matching <tt>endchar</tt> could be found.
</blockquote>
<p>
<b><tt>void Scanner_set_location(Scanner *s, int startchar, int endchar)</tt></b>
<blockquote>
Changes the current filename and line number of the scanner.
</blockquote>
<p>
<b><tt>String *Scanner_file(Scanner *s)</tt></b>
<blockquote>
Gets the current filename associated with text in the scanner.
</blockquote>
<p>
<b><tt>int Scanner_line(Scanner *s)</tt></b>
<blockquote>
Gets the current line number associated with text in the scanner.
</blockquote>
<p>
<b><tt>int Scanner_start_line(Scanner *s)</tt></b>
<blockquote>
Gets the starting line number of the last token returned by the scanner.
</blockquote>
<p>
<b><tt>void Scanner_idstart(Scanner *s, char *idchar)</tt></b>
<blockquote>
Sets additional characters (other than the C default) that may be used to start C identifiers. <tt>idchar</tt> is a string
containing the characters (e.g., "%@"). The purpose of this function is to up special keywords such as "%module" or "@directive" as
simple identifiers.
</blockquote>
<p>
<b><tt>String *Scanner_errmsg(Scanner *s)</tt></b>
<blockquote>
Returns the error message associated with the last scanner error (if any). This will only return a meaningful result
if <tt>Scanner_token()</tt> returned -1.
</blockquote>
<p>
<b><tt>int Scanner_errline(Scanner *s)</tt></b>
<blockquote>
Returns the line number associated with the last scanner error (if any). This will only return a meaningful result
if <tt>Scanner_token()</tt> returned -1. The line number usually corresponds to the starting line number of a particular
token (e.g., for unterminated strings, comments, etc.).
</blockquote>
<p>
<b><tt>int Scanner_isoperator(int tokval)</tt></b>
<blockquote>
A convenience function that returns 0 or 1 depending on whether <tt>tokval</tt> is a valid C/C++ operator (i.e., a candidate for
operator overloading).
</blockquote>
<p>
<b><tt>void Scanner_freeze_line(int val)</tt></b>
<blockquote>
Freezes the current line number depending upon whether or not <tt>val</tt> is 1 or 0. When the line number is frozen, newline characters will not result in
updates to the line number. This is sometimes useful in tracking line numbers through complicated macro expansions.
</blockquote>
<h2>Token Codes</h2>
The following table shows token codes returned by the scanner. These are integer codes returned by
the <tt>Scanner_token()</tt> function.
<blockquote>
<pre>
Token code C Token
------------------------- -------------
SWIG_TOKEN_LPAREN (
SWIG_TOKEN_RPAREN )
SWIG_TOKEN_SEMI ;
SWIG_TOKEN_COMMA ,
SWIG_TOKEN_STAR *
SWIG_TOKEN_TIMES *
SWIG_TOKEN_LBRACE {
SWIG_TOKEN_RBRACE }
SWIG_TOKEN_EQUAL =
SWIG_TOKEN_EQUALTO ==
SWIG_TOKEN_NOTEQUAL !=
SWIG_TOKEN_PLUS +
SWIG_TOKEN_MINUS -
SWIG_TOKEN_AND &amp;
SWIG_TOKEN_LAND &amp;&amp;
SWIG_TOKEN_OR |
SWIG_TOKEN_LOR ||
SWIG_TOKEN_XOR ^
SWIG_TOKEN_LESSTHAN &lt;
SWIG_TOKEN_GREATERTHAN &gt;
SWIG_TOKEN_LTEQUAL &lt;=
SWIG_TOKEN_GTEQUAL &gt;=
SWIG_TOKEN_NOT ~
SWIG_TOKEN_LNOT !
SWIG_TOKEN_LBRACKET [
SWIG_TOKEN_RBRACKET ]
SWIG_TOKEN_SLASH /
SWIG_TOKEN_DIVIDE /
SWIG_TOKEN_BACKSLASH \
SWIG_TOKEN_POUND #
SWIG_TOKEN_PERCENT %
SWIG_TOKEN_MODULO %
SWIG_TOKEN_COLON :
SWIG_TOKEN_DCOLON ::
SWIG_TOKEN_DCOLONSTAR ::*
SWIG_TOKEN_LSHIFT &lt;&lt;
SWIG_TOKEN_RSHIFT &gt;&gt;
SWIG_TOKEN_QUESTION ?
SWIG_TOKEN_PLUSPLUS ++
SWIG_TOKEN_MINUSMINUS --
SWIG_TOKEN_PLUSEQUAL +=
SWIG_TOKEN_MINUSEQUAL -=
SWIG_TOKEN_TIMESEQUAL *=
SWIG_TOKEN_DIVEQUAL /=
SWIG_TOKEN_ANDEQUAL &amp;=
SWIG_TOKEN_OREQUAL |=
SWIG_TOKEN_XOREQUAL ^=
SWIG_TOKEN_LSEQUAL &lt;&lt;=
SWIG_TOKEN_RSEQUAL &gt;&gt;=
SWIG_TOKEN_MODEQUAL %=
SWIG_TOKEN_ARROW -&gt;
SWIG_TOKEN_ARROWSTAR -&gt;*
SWIG_TOKEN_PERIOD .
SWIG_TOKEN_AT @
SWIG_TOKEN_DOLLAR $
SWIG_TOKEN_ENDLINE Literal newline
SWIG_TOKEN_ID identifier
SWIG_TOKEN_FLOAT Floating point with F suffix (e.g., 3.1415F)
SWIG_TOKEN_DOUBLE Floating point (e.g., 3.1415 )
SWIG_TOKEN_INT Integer (e.g., 314)
SWIG_TOKEN_UINT Unsigned integer (e.g., 314U)
SWIG_TOKEN_LONG Long integer (e.g., 314L)
SWIG_TOKEN_ULONG Unsigned long integer (e.g., 314UL)
SWIG_TOKEN_LONGLONG Long long integer (e.g., 314LL )
SWIG_TOKEN_ULONGLONG Unsigned long long integer (e.g., 314ULL)
SWIG_TOKEN_CHAR Character literal in single quotes ('c')
SWIG_TOKEN_STRING String literal in double quotes ("str")
SWIG_TOKEN_RSTRING Reverse quote string (`str`)
SWIG_TOKEN_CODEBLOCK SWIG code literal block %{ ... %}
SWIG_TOKEN_COMMENT C or C++ comment (// or /* ... */)
SWIG_TOKEN_ILLEGAL Illegal character
</pre>
</blockquote>
<b>Notes</b>
<ul>
<li>When more than one token code exist for the same token text, those codes are identical (e.g., <tt>SWIG_TOKEN_STAR</tt> and <tt>SWIG_TOKEN_TIMES</tt>).
<p>
<li>
String literals are returned in their exact representation in which escape codes (if any) have been interpreted.
<p>
<li>
All C identifiers and keywords are simply returned as <tt>SWIG_TOKEN_ID</tt>. To check for specific keywords, you will need to
add extra checking on the returned text.
<p>
<li>C and C++ comments include the comment starting and ending text (e.g., "//", "/*").
<p>
<li>The maximum token integer value is found in the constant <tt>SWIG_MAXTOKENS</tt>. This can be used if you wanted to create
an array or table for the purposes of remapping tokens to a different set of codes. For instance, if you are
using these functions to write a yacc-compatible lexer.
</ul>
</body>
</html>

284
Doc/Devel/tree.html Normal file
View File

@ -0,0 +1,284 @@
<html>
<head>
<title>SWIG Parse Tree Handling</title>
</head>
<body>
<center>
<h1>SWIG Parse Tree Handling</h1>
</center>
<h2>Introduction</h2>
This document describes the functions related to the handling of
parse trees in SWIG. The structure of SWIG parse trees has been influenced heavily by ideas
from XML-DOM trees. In fact, the functions in the API and attribute names are nearly identical.
The header file <tt>Source/swig/swigtree.h</tt> contains the functions and macros described in
this document. This API is
considered to be stable.
<h2>Parse tree navigation</h2>
The following macros are used to navigate the parse tree.
<p>
<b><tt>nodeType(n)</tt></b>
<blockquote>
Returns the type of a node as a String object. The type is stored in the "nodeType" attribute of <tt>n</tt>.
</blockquote>
<p>
<b><tt>parentNode(n)</tt></b>
<blockquote>
Returns the parent of a node. This is found in the "parentNode" attribute of <tt>n</tt>.
</blockquote>
<p>
<b><tt>previousSibling(n)</tt></b>
<blockquote>
Returns the previous sibling of a node (if any). This is found in the "previousSibling" attribute of <tt>n</tt>.
</blockquote>
<p>
<b><tt>nextSibling(n)</tt></b>
<blockquote>
Returns the next sibling of a node (if any). This is found in the "nextSibling" attribute of <tt>n</tt>.
</blockquote>
<p>
<b><tt>firstChild(n)</tt></b>
<blockquote>
Returns the first child of a node (if any). This is found in the "firstChild" attribute of <tt>n</tt>.
</blockquote>
<p>
<b><tt>lastChild(n)</tt></b>
<blockquote>
Returns the last child of a node (if any). This is found in the "lastChild" attribute of <tt>n</tt>.
</blockquote>
<h2>Parse Tree Construction</h2>
The following macros are used to construct parse trees.
<p>
<b><tt>set_nodeType(n, val)</tt></b>
<blockquote>
Sets the nodeType attribute of n. val is a string containing the type.
</blockquote>
<p>
<b><tt>set_parentNode(n, parent)</tt></b>
<blockquote>
Sets the parent of node n.
</blockquote>
<p>
<b><tt>set_previousSibling(n, prev)</tt></b>
<blockquote>
Sets the previous sibling of node n.
</blockquote>
<p>
<b><tt>set_nextSibling(n, next)</tt></b>
<blockquote>
Sets the next sibling of node n.
</blockquote>
<p>
<b><tt>set_firstChild(n, chd)</tt></b>
<blockquote>
Sets the first child of node n.
</blockquote>
<p>
<b><tt>set_lastChild(n, chd)</tt></b>
<blockquote>
Sets the last child of node n.
</blockquote>
<h2>Tree Management Functions</h2>
The following functions are used to help with the management and construction of parse trees.
<p>
<b><tt>void appendChild(Node *node, Node *child)</tt></b>
<blockquote>
Adds a new child to <tt>node</tt>. This function takes care of adjusting the "firstChild" and "lastChild" attributes of <tt>node</tt> to appropriate values. After calling this function, the "lastChild" attribute will point to <tt>child</tt>.
</blockquote>
<p>
<b><tt>void prependChild(Node *node, Node *child)</tt></b>
<blockquote>
Prepends a new child to <tt>node</tt>. The new child is added so that it becomes the first child of <tt>node</tt>.
</blockquote>
<p>
<b><tt>void removeNode(Node *node)</tt></b>
<blockquote>
Removes a node from the parse tree. The removal process detaches a node from its parent by removing it from the parent's child list. Upon return, <tt>node</tt> will have no parent and no siblings. This function does NOT delete <tt>node</tt> or modify children of <tt>node</tt>. If desired, <tt>node</tt> could be reattached to a different part of the parse tree.
</blockquote>
<p>
<b><tt>Node *copyNode(Node *node)</tt></b>
<blockquote>
Copies a node, but only copies those attributes that are simple strings. Thus, the new node will not contain any references to other nodes, lists, hashes, or other complex data structures. This function may be useful if you want to copy the data contents of a node in the process of creating a new parse tree node.
</blockquote>
<h2>Attribute Checking</h2>
The following utility is provided since this is an extremely common operation.
<p>
<b><tt>int checkAttribute(Node *n, const String_or_char *name, const String_or_char *value)</tt></b>
<blockquote>
This function checks to see whether node <tt>n</tt> has a given
attribute name and that the attribute has a given value. Returns 0 or
1.
</blockquote>
<h2>Node Transformation</h2>
In the course of processing, SWIG often applies a transform to a node.
This transformation process made modify many of the attributes--even
changing the type of a node. The following functions are used to help
manage this transformation process. In addition to provide sanity
checks, they save the old contents of the node so that they can be
restored later.
<p>
<b><tt>void Swig_save(const char *namespace, Node *n, ...)</tt></b>
<blockquote>
This function takes a node and a list of attribute names and saves their contents in a specified namespace. For example,
the call
<pre>
Swig_save("temp",n,"type","parms","name",NIL)
</pre>
takes the attributes "type","parms", and "name" and saves their
contents under the attribute names "temp:type","temp:parms","temp:name". In addition, this function sets
an attribute "view" to hold the name of the current namespace. In this example, the "view" attribute would be set
to "temp". The attribute names specified are all optional. If one or more of the attributes don't exist,
this function merely records that those attributes did not exist in the original node.
</blockquote>
<p>
<b><tt>void Swig_require(const char *namespace, Node *n, ...)</tt></b>
<blockquote>
This function is similar to <tt>Swig_save()</tt> except that adds additional attribute checking. There are different interpretations
of the attribute names. A name of "attr" merely requests that the function check for the presence of an attribute. If the attribute is missing, SWIG will exit with a failed assertion. An attribute name of "?attr" specifies that the attribute "attr" is optional and
that its old value must be saved (if any). An attribute name of "*attr" specifies that the attribute is required and that
its value must be saved. The saving of attributes is performed in the same manner as with <tt>Swig_save()</tt>. Here is an example:
<pre>
Swig_require("temp",n,"type","*name","?parms",NIL);
</pre>
</blockquote>
<p>
<b><tt>void Swig_restore(Node *n)</tt></b>
<blockquote>
This function restores a node to the state it was in prior to the last <tt>Swig_save()</tt> or <tt>Swig_require()</tt> call. This is used to undo node transformations.
</blockquote>
<h2>Debugging Functions</h2>
<p>
The following functions can be used to help debug any SWIG DOH object.
</p>
<b><tt>void Swig_print(DOH *object, int count = -1)</tt></b>
<blockquote>
Prints to stdout a string representation of any DOH type.
The number of nested Hash types to expand is set by count (default is 1 if count&lt;0). See Swig_set_max_hash_expand() to change default.
<pre>
</pre>
</blockquote>
<b><tt>void Swig_print_with_location(DOH *object, int count = -1)</tt></b>
<blockquote>
Prints to stdout a string representation of any DOH type, within [] brackets
for Hash and List types, prefixed by line and file information.
The number of nested Hash types to expand is set by count (default is 1 if count&lt;0). See Swig_set_max_hash_expand() to change default.
<pre>
</pre>
</blockquote>
<p>
The following functions can be used to help debug SWIG parse trees.
</p>
<p>
<b><tt>void Swig_print_tags(Node *node, String_or_char *prefix)</tt></b>
<blockquote>
Prints the tag-structure of the parse tree to standard output. <tt>node</tt> is the top-level parse tree node. <tt>prefix</tt> is
a string prefix that's added to the start of each line. Normally, you would specify the empty string or NIL for <tt>prefix</tt>.
This function is called by the <tt>-debug-tags</tt> option to SWIG.
<pre>
% swig -debug-tags -python example.i
. top (:1)
. top . include (/Users/beazley/Projects/share/swig/1.3.31/swig.swg:0)
. top . include . include (/Users/beazley/Projects/share/swig/1.3.31/swigwarnings.swg:0)
. top . include . include . include (/Users/beazley/Projects/share/swig/1.3.31/swigwarn.swg:0)
...
...
. top . include (example.i:0)
. top . include . module (example.i:2)
. top . include . insert (example.i:7)
. top . include . cdecl (example.i:5)
. top . include . cdecl (example.i:6)
</pre>
Since many language modules include hundreds of typemaps and other information, the output of this can be significantly more complicated than you might expect.
</blockquote>
<p>
<b><tt>void Swig_print_node(Node *node)</tt></b>
<blockquote>
Prints the contents of a parse tree node, including all children, to standard output. The output includes all attributes
and other details.
</blockquote>
<p>
<b><tt>void Swig_print_tree(Node *node)</tt></b>
<blockquote>
Prints the same output as <tt>Swig_print_node()</tt> except that it also processes all of the siblings of <tt>node</tt>. This can
be used to dump the entire parse tree to standard output. The command line options <tt>-debug-module</tt>
and <tt>-debug-top</tt> use this function to display the parse tree for a SWIG input file.
</blockquote>
</body>
</html>

223
Doc/Devel/wrapobj.html Normal file
View File

@ -0,0 +1,223 @@
<html>
<head>
<title>Wrapper Objects</title>
</head>
<body>
<center>
<h1>Wrapper Objects</h1>
<p>
David M. Beazley <br>
dave-swig@dabeaz.com<br>
January 15, 2007<br>
</b>
</center>
<h2>Introduction</h2>
This document describes the functions related to management of
wrapper objects. A wrapper object is a low-level
data structure used to contain the C/C++ code that is emitted during the
wrapping process. It contains not only the emitted code, but information
about local variables. These objects are a critical component of almost all
SWIG target language modules.
<p>
The functions described here are declared
in <tt>Source/Swig/swigwrap.h</tt>. This API is considered to be
stable.
<h2>Creating and Destroying Wrappers</h2>
The following functions create and destroy wrapper objects.
<p>
<b><tt>Wrapper *NewWrapper()</tt></b>
<blockquote>
Creates a new wrapper object.
</blockquote>
<p>
<b><tt>void DelWrapper(Wrapper *w)</tt></b>
<blockquote>
Destroys a wrapper object.
</blockquote>
<h2>Wrapper Objects</h2>
The <tt>Wrapper</tt> object returned by <tt>NewWrapper()</tt> has
three public attributes.
<blockquote><pre>
typedef struct Wrapper {
String *def;
String *locals;
String *code;
} Wrapper;
</pre></blockquote>
The <tt>def</tt> attribute is a string that holds the function
definition line. This line declares the function name, return type,
and parameters. Language modules create this declaration by simply printing
the appropriate text into this attribute.
<p>
The <tt>locals</tt> attribute is a string that holds the code
related to any local variables declaration. Normally, language modules
do not emit code to this string directly. They use <tt>Wrapper_add_local()</tt> or <tt>Wrapper_new_local()</tt> to do this.
<p>
The <tt>code</tt> attribute is a string that holds code related to the body of the function. Almost all code emitted by SWIG language modules is printed into this attribute.
<h2>Creating Local Variables</h2>
Perhaps the most useful aspect of <tt>Wrapper</tt> objects is the
management of local variables. When creating a wrapper, it is often
necessary to emit local variables related to the API of the target
language. In addition to this, typemaps and other aspects of SWIG
rely upon their own local variables. The following functions are used
to create local variables, but also provide support for renaming
variables in order to avoid name clashes.
<p>
<b><tt>int Wrapper_add_local(Wrapper *w, const String_or_char *name, const String_or_char *decl)</tt></b>
<blockquote>
Adds a new local variable to the wrapper object. <tt>name</tt> is the
name of the local variable. <tt>decl</tt> is a string containing the
actual variable declaration code. For example, if you wanted to
declare a variable "<tt>int x = 42;</tt>", you would set <tt>name</tt>
to <tt>"x"</tt> and
<tt>decl</tt> to <tt>"int x = 42;"</tt>. On success, the text in
<tt>decl</tt> is added to the <tt>locals</tt> attribute of <tt>w</tt>
and 0 is returned. -1 is returned if a variable with the given name
has already been declared.
</blockquote>
<p>
<b><tt>int Wrapper_add_localv(Wrapper *w, const String_or_char *name, ...)</tt></b>
<blockquote>
The same as <tt>Wrapper_add_local()</tt> except that instead of
passing a single string for the declaration, a NULL-terminated list of
strings can be passed. These strings are joined together when
producing the output. This convention turns out to be fairly useful
since language modules often create their output into pieces.
</blockquote>
<p>
<b><tt>char * Wrapper_new_local(Wrapper *w, const String_or_char *name, const String_or_char *decl)</tt></b>
<blockquote>
The same as <tt>Wrapper_add_local()</tt> except that if a local variable
with the given name already exists, this function picks a new name and adds
the declaration using the new name. The actual name used for the variable
is returned. This function is used when generating code originating from
typemaps. For instance, if a typemap declares a local variable, that variable
might have to be renamed if the same typemap is used more than once in the same function.
</blockquote>
<p>
<b><tt>char * Wrapper_new_localv(Wrapper *w, const String_or_char *name,...)</tt></b>
<blockquote>
The same as <tt>Wrapper_new_localv()</tt>, but accepts a NULL-terminated list
of strings as code output.
</blockquote>
<p>
<b><tt>int Wrapper_check_local(Wrapper *w, const String_or_char *name)</tt></b>
<blockquote>
Checks to see if a local variable with name <tt>name</tt> has been declared. Returns 1 if the local is defined, 0 otherwise.
</blockquote>
<h2>Output</h2>
<p>
<b><tt>void Wrapper_print(Wrapper *w, File *f)</tt></b>
<blockquote>
This function is used to format a wrapper function for output. The
formatted wrapper function is emitted to <tt>f</tt> which may be any
file-like object including a <tt>FILE *</tt> object or a <tt>String
*</tt> object. When emitting the wrapper, the code printed to the
wrapper object is automatically formatted. By default, the formatting
is done according to a "pretty printing" style in which lines are split onto
multiple lines and indented according to reasonable C formatting rules. This produces code that is moderately readable should you want to look at the wrapper
code output. An alternative output mode is "compact printing" in which
lines are collected and compacted. This may result in multiple C statements
appearing on the same line. This mode is sometimes used when the size of
a wrapper file is too large for certain compilers. For example, some compilers
might impose a limit of 65536 lines per source file.
</blockquote>
<p>
<b><tt>void Wrapper_compact_print_mode_set(int flag)</tt></b>
<blockquote>
Sets the output mode of the <tt>Wrapper_print()</tt>
function. If <tt>flag</tt> is set to 1, then wrapper code is formatted
to be compact.
</blockquote>
<p>
<b><tt>void Wrapper_pretty_print(String *str, File *f)</tt></b>
<blockquote>
Utility function that reformats a string containing C/C++ code and outputs
it to the file-like object <tt>f</tt>. The formatting process indents the code
and structures it according to reasonable C formatting rules.
</blockquote>
<p>
<b><tt>void Wrapper_compact_print(String *str, File *f)</tt></b>
<blockquote>
Utility function that reformats a string containing C/C++ code and outputs
it to the file-like object <tt>f</tt>. The formatting process tries to
make the code as compact as possible, without going completely overboard. For
example, multiple C statements may be combined onto a single line and braces may be aligned to not use up extra lines.
</blockquote>
<h2>An Example</h2>
Here is a simple example of how these functions are used. Suppose
you wanted to emit the following C function:
<blockquote>
<pre>
void foo(int n) {
int i;
for (i = 0; i &lt; n; i++) {
printf("%d\n", i);
}
}
</pre>
</blockquote>
Here is code that generates the above function:
<blockquote>
<pre>
Wrapper *w = NewWrapper();
Printf(w-&gt;def,"void foo(int n) {");
Wrapper_add_local(w,"n",""); /* parameter n */
Wrapper_add_local(w,"i", "int i;"); /* local i */
Printv(w-&gt;code,"for (i = 0; i &lt; n; i++) {",
"printf(\"%d\n",i);",
"}\n", NIL);
Printf(w-&gt;code,"}\n");
/* Emit wrapper code */
Wrapper_print(w,outf);
DelWrapper(w);
</pre>
</blockquote>
Within different language modules, this process is obviously much more
involved. However, this example shows the basic idea of how C/C++
code is prepared for output.
</body>
</html>

2150
Doc/Manual/Allegrocl.html Normal file

File diff suppressed because it is too large Load Diff

782
Doc/Manual/Android.html Normal file
View File

@ -0,0 +1,782 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Android</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#FFFFFF">
<H1><a name="Android">21 SWIG and Android</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Android_overview">Overview</a>
<li><a href="#Android_examples">Android examples</a>
<ul>
<li><a href="#Android_examples_intro">Examples introduction</a>
<li><a href="#Android_example_simple">Simple C example</a>
<li><a href="#Android_example_class">C++ class example</a>
<li><a href="#Android_examples_other">Other examples</a>
</ul>
<li><a href="#Android_stl">C++ STL</a>
</ul>
</div>
<!-- INDEX -->
<p>
This chapter describes SWIG's support of Android.
</p>
<H2><a name="Android_overview">21.1 Overview</a></H2>
<p>
The Android chapter is fairly short as support for Android is the same as for Java, where the Java Native Interface (JNI) is
used to call from Android Java into C or C++ compiled code.
Everything in the <a href="Java.html#Java">Java chapter</a> applies to generating code for access from Android Java code.
This chapter contains a few Android specific notes and examples.
</p>
<H2><a name="Android_examples">21.2 Android examples</a></H2>
<H3><a name="Android_examples_intro">21.2.1 Examples introduction</a></H3>
<p>
The examples require the <a href="https://developer.android.com/sdk/">Android SDK</a> and <a href="https://developer.android.com/ndk/">Android NDK</a> which can be installed as per instructions in the links.
The Eclipse version is not required for these examples as just the command line tools are used (shown for Linux as the host, but Windows will be very similar, if not identical in most places).
Add the SDK tools and NDK tools to your path and create a directory somewhere for your Android projects (adjust PATH as necessary to where you installed the tools):
</p>
<div class="shell">
<pre>
$ export PATH=$HOME/android/android-sdk-linux_x86/tools:$HOME/android/android-sdk-linux_x86/platform-tools:$HOME/android/android-ndk-r6b:$PATH
$ mkdir AndroidApps
$ cd AndroidApps
</pre>
</div>
<p>
The examples use a target id of 1. This might need changing depending on your setup.
After installation of the Android SDK, the available target ids can be viewed by running the command below.
Please adjust the id to suit your target device.
</p>
<div class="shell">
<pre>
$ android list targets
</pre>
</div>
<p>
The following examples are shipped with SWIG under the Examples/android directory and include a Makefile to build and install each example.
</p>
<H3><a name="Android_example_simple">21.2.2 Simple C example</a></H3>
<p>
This simple C example shows how to call a C function as well as read and modify a global variable.
First we'll create and build a pure Java Android app. Afterwards the JNI code will be generated by SWIG and built into the app.
First create and build an app called <tt>SwigSimple</tt> in a subdirectory called <tt>simple</tt> using the commands below.
Adjust the <tt>--target</tt> id as mentioned earlier in the <a href="Android.html#Android_examples_intro">Examples introduction</a>.
<a href="http://developer.android.com/guide/developing/projects/projects-cmdline.html">Managing Projects from the Command Line</a> on the Android developer's site is a useful reference for these steps.
</p>
<div class="shell">
<pre>
$ android create project --target 1 --name SwigSimple --path ./simple --activity SwigSimple --package org.swig.simple
$ cd simple
$ ant debug
</pre>
</div>
<p>
Modify <tt>src/org/swig/simple/SwigSimple.java</tt> from the default to:
</p>
<div class="code">
<pre>
package org.swig.simple;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.ScrollView;
import android.text.method.ScrollingMovementMethod;
public class SwigSimple extends Activity
{
TextView outputText = null;
ScrollView scroller = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
outputText = (TextView)findViewById(R.id.OutputText);
outputText.setText("Press 'Run' to start...\n");
outputText.setMovementMethod(new ScrollingMovementMethod());
scroller = (ScrollView)findViewById(R.id.Scroller);
}
public void onRunButtonClick(View view)
{
outputText.append("Started...\n");
nativeCall();
outputText.append("Finished!\n");
// Ensure scroll to end of text
scroller.post(new Runnable() {
public void run() {
scroller.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
/** Calls into C/C++ code */
public void nativeCall()
{
// TODO
}
}
</pre>
</div>
<p>
The above simply adds a <i>Run</i> button and scrollable text view as the GUI aspects of the program.
The associated resources need to be created, modify <tt>res/layout/main.xml</tt> as follows:
</p>
<div class="code">
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
&gt;
&lt;Button
android:id="@+id/RunButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Run..."
android:onClick="onRunButtonClick"
/&gt;
&lt;ScrollView
android:id="@+id/Scroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
&gt;
&lt;TextView
android:id="@+id/OutputText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/&gt;
&lt;/ScrollView&gt;
&lt;/LinearLayout&gt;
</pre>
</div>
<p>
Rebuild the project with your changes:
</p>
<div class="shell">
<pre>
$ ant debug
</pre>
</div>
<p>
Although there are no native function calls in the code, yet, you may want to check that this simple pure
Java app runs before adding in the native calls.
First, set up your Android device for hardware debugging, see <a href="http://developer.android.com/guide/developing/device.html">Using hardware devices</a> on the Android developer's site.
When complete your device should be listed in those attached, something like:
</p>
<div class="shell">
<pre>
$ adb devices
List of devices attached
A32-6DBE0001-9FF80000-015D62C3-02018028 device
</pre>
</div>
<p>
This means you are now ready to install the application...
</p>
<div class="shell">
<pre>
$ adb install bin/SwigSimple-debug.apk
95 KB/s (4834 bytes in 0.049s)
pkg: /data/local/tmp/SwigSimple-debug.apk
Success
</pre>
</div>
<p>
The newly installed 'SwigSimple' app will be amongst all your other applications on the home screen. Run the app and it will show a <i>Run</i> button text box below it.
Press the <i>Run</i> button to see the simple text output.
</p>
<p>
The application can be uninstalled like any other application and in fact must be uninstalled before installing an updated version. Uninstalling is quite easy too from your host computer:
</p>
<div class="shell">
<pre>
$ adb uninstall org.swig.simple
Success
</pre>
</div>
<p>
Now that you have a pure Java Android app working, let's add some JNI code generated from SWIG.
</p>
<p>
First create a <tt>jni</tt> subdirectory and then create some C source code in <tt>jni/example.c</tt>:
</p>
<div class="code">
<pre>
/* File : example.c */
/* A global variable */
double Foo = 3.0;
/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x &gt; 0) {
g = x;
x = y % x;
y = g;
}
return g;
}
</pre>
</div>
<p>
Create a SWIG interface file for this C code, <tt>jni/example.i</tt>:
</p>
<div class="code">
<pre>
/* File : example.i */
%module example
%inline %{
extern int gcd(int x, int y);
extern double Foo;
%}
</pre>
</div>
<p>
Invoke SWIG as follows:
</p>
<div class="shell">
<pre>
$ swig -java -package org.swig.simple -outdir src/org/swig/simple -o jni/example_wrap.c jni/example.i
</pre>
</div>
<p>
SWIG generates the following files:
</p>
<ul>
<li><tt>src/org/swig/simple/exampleJNI.java</tt></li>
<li><tt>src/org/swig/simple/example.java</tt></li>
<li><tt>jni/example_wrap.c</tt></li>
</ul>
<p>
Next we need to create a standard Android NDK build system file <tt>jni/Android.mk</tt>:
</p>
<div class="code">
<pre>
# File: Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := example
LOCAL_SRC_FILES := example_wrap.c example.c
include $(BUILD_SHARED_LIBRARY)
</pre>
</div>
<p>
See the <a href="https://developer.android.com/ndk/">Android NDK documentation</a> for more on the NDK build system and getting started with the NDK.
A simple invocation of ndk-build will compile the .c files and generate a shared object/system library. Output will be similar to:
</p>
<div class="shell">
<pre>
$ ndk-build
Compile thumb : example &lt;= example_wrap.c
Compile thumb : example &lt;= example.c
SharedLibrary : libexample.so
Install : libexample.so =&gt; libs/armeabi/libexample.so
</pre>
</div>
<p>
Now that the C JNI layer has been built, we can write Java code to call into the this layer.
Modify the <tt>nativeCall</tt> method in <tt>src/org/swig/simple/SwigSimple.java</tt> to call the JNI code as follows and add the static constructor to load the system library containing the compiled JNI C code:
</p>
<div class="code">
<pre>
/** Calls into C/C++ code */
public void nativeCall()
{
// Call our gcd() function
int x = 42;
int y = 105;
int g = example.gcd(x, y);
outputText.append("The greatest common divisor of " + x + " and " + y + " is " + g + "\n");
// Manipulate the Foo global variable
// Output its current value
double foo = example.getFoo();
outputText.append("Foo = " + foo + "\n");
// Change its value
example.setFoo(3.1415926);
// See if the change took effect
outputText.append("Foo = " + example.getFoo() + "\n");
// Restore value
example.setFoo(foo);
}
/** static constructor */
static {
System.loadLibrary("example");
}
</pre>
</div>
<p>
Compile the Java code as usual, uninstall the old version of the app if still installed and re-install the new app:
</p>
<div class="shell">
<pre>
$ ant debug
$ adb uninstall org.swig.simple
$ adb install bin/SwigSimple-debug.apk
</pre>
</div>
<p>
Run the app again and this time you will see the output pictured below, showing the result of calls into the C code:
</p>
<center><img src="android-simple.png" alt="Android screenshot of SwigSimple example"></center>
<H3><a name="Android_example_class">21.2.3 C++ class example</a></H3>
<p>
The steps for calling C++ code are almost identical to those in the previous C code example.
All the steps required to compile and use a simple hierarchy of classes for shapes are shown in this example.
</p>
<p>
First create an Android project called <tt>SwigClass</tt> in a subdirectory called <tt>class</tt>.
The steps below create and build the JNI C++ app.
Adjust the <tt>--target</tt> id as mentioned earlier in the <a href="Android.html#Android_examples_intro">Examples introduction</a>.
</p>
<div class="shell">
<pre>
$ android create project --target 1 --name SwigClass --path ./class --activity SwigClass --package org.swig.classexample
$ cd class
</pre>
</div>
<p>
Now create a <tt>jni</tt> subdirectory and then create a C++ header file <tt>jni/example.h</tt> which defines our
hierarchy of shape classes:
</p>
<div class="code">
<pre>
/* File : example.h */
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
}
double x, y;
void move(double dx, double dy);
virtual double area() = 0;
virtual double perimeter() = 0;
static int nshapes;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { }
virtual double area();
virtual double perimeter();
};
class Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { }
virtual double area();
virtual double perimeter();
};
</pre>
</div>
<p>
and create the implementation in the <tt>jni/example.cpp</tt> file:
</p>
<div class="code">
<pre>
/* File : example.cpp */
#include "example.h"
#define M_PI 3.14159265358979323846
/* Move the shape to a new location */
void Shape::move(double dx, double dy) {
x += dx;
y += dy;
}
int Shape::nshapes = 0;
double Circle::area() {
return M_PI*radius*radius;
}
double Circle::perimeter() {
return 2*M_PI*radius;
}
double Square::area() {
return width*width;
}
double Square::perimeter() {
return 4*width;
}
</pre>
</div>
<p>
Create a SWIG interface file for this C++ code in <tt>jni/example.i</tt>:
</p>
<div class="code">
<pre>
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"
</pre>
</div>
<p>
Invoke SWIG as follows, note that the -c++ option is required for C++ code:
</p>
<div class="shell">
<pre>
$ swig -c++ -java -package org.swig.classexample -outdir src/org/swig/classexample -o jni/example_wrap.cpp jni/example.i
</pre>
</div>
<p>
SWIG generates the following files:
</p>
<ul>
<li><tt>src/org/swig/classexample/Square.java</tt></li>
<li><tt>src/org/swig/classexample/exampleJNI.java</tt></li>
<li><tt>src/org/swig/classexample/example.java</tt></li>
<li><tt>src/org/swig/classexample/Circle.java</tt></li>
<li><tt>src/org/swig/classexample/Shape.java</tt></li>
<li><tt>jni/example_wrap.cpp</tt></li>
</ul>
<p>
Next we need to create an Android NDK build system file for compiling the C++ code <tt>jni/Android.mk</tt>.
The <tt>-frtti</tt> compiler flag isn't strictly needed for this example, but is needed for any code that uses C++ RTTI:
</p>
<div class="code">
<pre>
# File: Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := example
LOCAL_SRC_FILES := example_wrap.cpp example.cpp
LOCAL_CFLAGS := -frtti
include $(BUILD_SHARED_LIBRARY)
</pre>
</div>
<p>
A simple invocation of ndk-build will compile the .cpp files and generate a shared object/system library. Output will be similar to:
</p>
<div class="shell">
<pre>
$ ndk-build
Compile++ thumb : example &lt;= example_wrap.cpp
Compile++ thumb : example &lt;= example.cpp
StaticLibrary : libstdc++.a
SharedLibrary : libexample.so
Install : libexample.so =&gt; libs/armeabi/libexample.so
</pre>
</div>
<p>
Now that the C JNI layer has been built, we can write Java code to call into this layer.
Modify <tt>src/org/swig/classexample/SwigClass.java</tt> from the default to:
</p>
<div class="code">
<pre>
package org.swig.classexample;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.ScrollView;
import android.text.method.ScrollingMovementMethod;
public class SwigClass extends Activity
{
TextView outputText = null;
ScrollView scroller = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
outputText = (TextView)findViewById(R.id.OutputText);
outputText.setText("Press 'Run' to start...\n");
outputText.setMovementMethod(new ScrollingMovementMethod());
scroller = (ScrollView)findViewById(R.id.Scroller);
}
public void onRunButtonClick(View view)
{
outputText.append("Started...\n");
nativeCall();
outputText.append("Finished!\n");
// Ensure scroll to end of text
scroller.post(new Runnable() {
public void run() {
scroller.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
/** Calls into C/C++ code */
public void nativeCall()
{
// ----- Object creation -----
outputText.append( "Creating some objects:\n" );
Circle c = new Circle(10);
outputText.append( " Created circle " + c + "\n");
Square s = new Square(10);
outputText.append( " Created square " + s + "\n");
// ----- Access a static member -----
outputText.append( "\nA total of " + Shape.getNshapes() + " shapes were created\n" );
// ----- Member data access -----
// Notice how we can do this using functions specific to
// the 'Circle' class.
c.setX(20);
c.setY(30);
// Now use the same functions in the base class
Shape shape = s;
shape.setX(-10);
shape.setY(5);
outputText.append( "\nHere is their current position:\n" );
outputText.append( " Circle = (" + c.getX() + " " + c.getY() + ")\n" );
outputText.append( " Square = (" + s.getX() + " " + s.getY() + ")\n" );
// ----- Call some methods -----
outputText.append( "\nHere are some properties of the shapes:\n" );
Shape[] shapes = {c, s};
for (int i=0; i&lt;shapes.length; i++)
{
outputText.append( " " + shapes[i].toString() + "\n" );
outputText.append( " area = " + shapes[i].area() + "\n" );
outputText.append( " perimeter = " + shapes[i].perimeter() + "\n" );
}
// Notice how the area() and perimeter() functions really
// invoke the appropriate virtual method on each object.
// ----- Delete everything -----
outputText.append( "\nGuess I'll clean up now\n" );
// Note: this invokes the virtual destructor
// You could leave this to the garbage collector
c.delete();
s.delete();
outputText.append( Shape.getNshapes() + " shapes remain\n" );
outputText.append( "Goodbye\n" );
}
/** static constructor */
static {
System.loadLibrary("example");
}
}
</pre>
</div>
<p>
Note the static constructor and the interesting JNI code is in the <tt>nativeCall</tt> method.
The remaining code deals with the GUI aspects which are identical to the previous C simple example. Modify <tt>res/layout/main.xml</tt> to contain the xml for the 'Run' button and scrollable text view:
</p>
<div class="code">
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
&gt;
&lt;Button
android:id="@+id/RunButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Run..."
android:onClick="onRunButtonClick"
/&gt;
&lt;ScrollView
android:id="@+id/Scroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
&gt;
&lt;TextView
android:id="@+id/OutputText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/&gt;
&lt;/ScrollView&gt;
&lt;/LinearLayout&gt;
</pre>
</div>
<p>
Compile the Java code as usual, uninstall the old version of the app if installed and re-install the new app:
</p>
<div class="shell">
<pre>
$ ant debug
$ adb uninstall org.swig.classexample
$ adb install bin/SwigClass-debug.apk
</pre>
</div>
<p>
Run the app to see the result of calling the C++ code from Java:
</p>
<center><img src="android-class.png" alt="Android screenshot of SwigClass example"></center>
<H3><a name="Android_examples_other">21.2.4 Other examples</a></H3>
<p>
The Examples/android directory contains further examples which can be run and installed in a similar manner to the previous two examples.
</p>
<p>
Note that the 'extend' example is demonstrates the directors feature.
Normally C++ exception handling and the STL is not available by default in the version of g++ shipped with Android, but this example turns these features on as described in the next section.
</p>
<H2><a name="Android_stl">21.3 C++ STL</a></H2>
<p>
Should the C++ Standard Template Library (STL) be required, an <tt>Application.mk</tt> file needs to be created
in the same directory as the <tt>Android.mk</tt> directory containing information about the STL to use.
See the NDK documentation in the $NDKROOT/docs folder especially CPLUSPLUS-SUPPORT.html.
Below is an example of the <tt>Application.mk</tt> file to make the STLport static library available for use:
</p>
<div class="code">
<pre>
# File: Application.mk
APP_STL := gnustl_static
</pre>
</div>
</body>
</html>

497
Doc/Manual/Arguments.html Normal file
View File

@ -0,0 +1,497 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Argument Handling</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Arguments">12 Argument Handling</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Arguments_nn2">The typemaps.i library</a>
<ul>
<li><a href="#Arguments_nn3">Introduction</a>
<li><a href="#Arguments_nn4">Input parameters</a>
<li><a href="#Arguments_nn5">Output parameters</a>
<li><a href="#Arguments_nn6">Input/Output parameters</a>
<li><a href="#Arguments_nn7">Using different names</a>
</ul>
<li><a href="#Arguments_nn8">Applying constraints to input values</a>
<ul>
<li><a href="#Arguments_nn9">Simple constraint example</a>
<li><a href="#Arguments_nn10">Constraint methods</a>
<li><a href="#Arguments_nn11">Applying constraints to new datatypes</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
In Chapter 5, SWIG's treatment of basic datatypes and pointers was
described. In particular, primitive types such as <tt>int</tt> and
<tt>double</tt> are mapped to corresponding types in the target
language. For everything else, pointers are used to refer to
structures, classes, arrays, and other user-defined datatypes.
However, in certain applications it is desirable to change SWIG's
handling of a specific datatype. For example, you might want to
return multiple values through the arguments of a function. This chapter
describes some of the techniques for doing this.
</p>
<H2><a name="Arguments_nn2">12.1 The typemaps.i library</a></H2>
<p>
This section describes the <tt>typemaps.i</tt> library file--commonly used to
change certain properties of argument conversion.
</p>
<H3><a name="Arguments_nn3">12.1.1 Introduction</a></H3>
<p>
Suppose you had a C function like this:
</p>
<div class="code"><pre>
void add(double a, double b, double *result) {
*result = a + b;
}
</pre></div>
<p>
From reading the source code, it is clear that the function is storing
a value in the <tt>double *result</tt> parameter. However, since SWIG
does not examine function bodies, it has no way to know that this is
the underlying behavior.
</p>
<p>
One way to deal with this is to use the
<tt>typemaps.i</tt> library file and write interface code like this:
</p>
<div class="code"><pre>
// Simple example using typemaps
%module example
%include "typemaps.i"
%apply double *OUTPUT { double *result };
%inline %{
extern void add(double a, double b, double *result);
%}
</pre></div>
<p>
The <tt>%apply</tt> directive tells SWIG that you are going to apply
a special type handling rule to a type. The "<tt>double *OUTPUT</tt>" specification is the
name of a rule that defines how to return an output value from an argument of type
<tt>double *</tt>. This rule gets applied to all of the datatypes
listed in curly braces-- in this case "<tt>double *result</tt>".</p>
<p>
When the resulting module is created, you can now use the function
like this (shown for Python):
</p>
<div class="targetlang"><pre>
&gt;&gt;&gt; a = add(3, 4)
&gt;&gt;&gt; print a
7
&gt;&gt;&gt;
</pre></div>
<p>
In this case, you can see how the output value normally returned in
the third argument has magically been transformed into a function
return value. Clearly this makes the function much easier to use
since it is no longer necessary to manufacture a special <tt>double
*</tt> object and pass it to the function somehow.
</p>
<p>
Once a typemap has been applied to a type, it stays in effect for all future occurrences
of the type and name. For example, you could write the following:
</p>
<div class="code"><pre>
%module example
%include "typemaps.i"
%apply double *OUTPUT { double *result };
%inline %{
extern void add(double a, double b, double *result);
extern void sub(double a, double b, double *result);
extern void mul(double a, double b, double *result);
extern void div(double a, double b, double *result);
%}
...
</pre></div>
<p>
In this case, the <tt>double *OUTPUT</tt> rule is applied to all of the functions that follow.
</p>
<p>
Typemap transformations can even be extended to multiple return values.
For example, consider this code:
</p>
<div class="code">
<pre>
%include "typemaps.i"
%apply int *OUTPUT { int *width, int *height };
// Returns a pair (width, height)
void getwinsize(int winid, int *width, int *height);
</pre>
</div>
<p>
In this case, the function returns multiple values, allowing it to be used like this:
</p>
<div class="targetlang"><pre>
&gt;&gt;&gt; w, h = genwinsize(wid)
&gt;&gt;&gt; print w
400
&gt;&gt;&gt; print h
300
&gt;&gt;&gt;
</pre>
</div>
<p>
It should also be noted that although the <tt>%apply</tt> directive is
used to associate typemap rules to datatypes, you can also use the
rule names directly in arguments. For example, you could write this:
</p>
<div class="code"><pre>
// Simple example using typemaps
%module example
%include "typemaps.i"
%{
extern void add(double a, double b, double *OUTPUT);
%}
extern void add(double a, double b, double *OUTPUT);
</pre></div>
<p>
Typemaps stay in effect until they are explicitly deleted or redefined to something
else. To clear a typemap, the <tt>%clear</tt> directive should be used. For example:
</p>
<div class="code">
<pre>
%clear double *result; // Remove all typemaps for double *result
</pre>
</div>
<H3><a name="Arguments_nn4">12.1.2 Input parameters</a></H3>
<p>
The following typemaps instruct SWIG that a pointer really only holds a single
input value:
</p>
<div class="code"><pre>
int *INPUT
short *INPUT
long *INPUT
unsigned int *INPUT
unsigned short *INPUT
unsigned long *INPUT
double *INPUT
float *INPUT
</pre></div>
<p>
When used, it allows values to be passed instead of pointers. For example, consider this
function:
</p>
<div class="code"><pre>
double add(double *a, double *b) {
return *a+*b;
}
</pre></div>
<p>
Now, consider this SWIG interface:
</p>
<div class="code"><pre>
%module example
%include "typemaps.i"
...
%{
extern double add(double *, double *);
%}
extern double add(double *INPUT, double *INPUT);
</pre></div>
<p>
When the function is used in the scripting language interpreter, it will work like this:
</p>
<div class="targetlang"><pre>
result = add(3, 4)
</pre></div>
<H3><a name="Arguments_nn5">12.1.3 Output parameters</a></H3>
<p>
The following typemap rules tell SWIG that pointer is the output value of a
function. When used, you do not need to supply the argument when
calling the function. Instead, one or more output values are returned.
</p>
<div class="code"><pre>
int *OUTPUT
short *OUTPUT
long *OUTPUT
unsigned int *OUTPUT
unsigned short *OUTPUT
unsigned long *OUTPUT
double *OUTPUT
float *OUTPUT
</pre></div>
<p>
These methods can be used as shown in an earlier example. For example, if you have this C function :</p>
<div class="code"><pre>
void add(double a, double b, double *c) {
*c = a+b;
}
</pre></div>
<p>
A SWIG interface file might look like this :</p>
<div class="code"><pre>
%module example
%include "typemaps.i"
...
%inline %{
extern void add(double a, double b, double *OUTPUT);
%}
</pre></div>
<p>
In this case, only a single output value is returned, but this is not
a restriction. An arbitrary number of output values can be returned by applying
the output rules to more than one argument (as shown previously).
</p>
<p>
If the function also returns a value, it is returned along with the argument. For example,
if you had this:
</p>
<div class="code"><pre>
extern int foo(double a, double b, double *OUTPUT);
</pre></div>
<p>
The function will return two values like this:
</p>
<div class="targetlang">
<pre>
iresult, dresult = foo(3.5, 2)
</pre>
</div>
<H3><a name="Arguments_nn6">12.1.4 Input/Output parameters</a></H3>
<p>
When a pointer serves as both an input and output value you can use
the following typemaps :</p>
<div class="code"><pre>
int *INOUT
short *INOUT
long *INOUT
unsigned int *INOUT
unsigned short *INOUT
unsigned long *INOUT
double *INOUT
float *INOUT
</pre></div>
<p>
A C function that uses this might be something like this:</p>
<div class="code"><pre>
void negate(double *x) {
*x = -(*x);
}
</pre></div>
<p>
To make x function as both and input and output value, declare the
function like this in an interface file :</p>
<div class="code"><pre>
%module example
%include "typemaps.i"
...
%{
extern void negate(double *);
%}
extern void negate(double *INOUT);
</pre></div>
<p>
Now within a script, you can simply call the function normally :</p>
<div class="targetlang"><pre>
a = negate(3); # a = -3 after calling this
</pre></div>
<p>
One subtle point of the <tt>INOUT</tt> rule is that many scripting languages
enforce mutability constraints on primitive objects (meaning that simple objects
like integers and strings aren't supposed to change). Because of this, you can't
just modify the object's value in place as the underlying C function does in this example.
Therefore, the <tt>INOUT</tt> rule returns the modified value as a new object
rather than directly overwriting the value of the original input object.
</p>
<p>
<b>Compatibility note :</b> The <tt>INOUT</tt> rule used to be known as <tt>BOTH</tt> in earlier versions of
SWIG. Backwards compatibility is preserved, but deprecated.
</p>
<H3><a name="Arguments_nn7">12.1.5 Using different names</a></H3>
<p>
As previously shown, the <tt>%apply</tt> directive can be used to apply the <tt>INPUT</tt>, <tt>OUTPUT</tt>, and
<tt>INOUT</tt> typemaps to different argument names. For example:
</p>
<div class="code"><pre>
// Make double *result an output value
%apply double *OUTPUT { double *result };
// Make Int32 *in an input value
%apply int *INPUT { Int32 *in };
// Make long *x inout
%apply long *INOUT {long *x};
</pre></div>
<p>
To clear a rule, the <tt>%clear</tt> directive is used:
</p>
<div class="code"><pre>
%clear double *result;
%clear Int32 *in, long *x;
</pre></div>
<p>
Typemap declarations are lexically scoped so a typemap takes effect from the point of definition to the end of the
file or a matching <tt>%clear</tt> declaration.
</p>
<H2><a name="Arguments_nn8">12.2 Applying constraints to input values</a></H2>
<p>
In addition to changing the handling of various input values, it is
also possible to use typemaps to apply constraints. For example, maybe you want to
insure that a value is positive, or that a pointer is non-NULL. This
can be accomplished including the <tt>constraints.i</tt> library file.
</p>
<H3><a name="Arguments_nn9">12.2.1 Simple constraint example</a></H3>
<p>
The constraints library is best illustrated by the following interface
file :</p>
<div class="code"><pre>
// Interface file with constraints
%module example
%include "constraints.i"
double exp(double x);
double log(double POSITIVE); // Allow only positive values
double sqrt(double NONNEGATIVE); // Non-negative values only
double inv(double NONZERO); // Non-zero values
void free(void *NONNULL); // Non-NULL pointers only
</pre></div>
<p>
The behavior of this file is exactly as you would expect. If any of
the arguments violate the constraint condition, a scripting language
exception will be raised. As a result, it is possible to catch bad
values, prevent mysterious program crashes and so on.</p>
<H3><a name="Arguments_nn10">12.2.2 Constraint methods</a></H3>
<p>
The following constraints are currently available</p>
<div class="code"><pre>
POSITIVE Any number &gt; 0 (not zero)
NEGATIVE Any number &lt; 0 (not zero)
NONNEGATIVE Any number &gt;= 0
NONPOSITIVE Any number &lt;= 0
NONZERO Nonzero number
NONNULL Non-NULL pointer (pointers only).
</pre></div>
<H3><a name="Arguments_nn11">12.2.3 Applying constraints to new datatypes</a></H3>
<p>
The constraints library only supports the primitive C datatypes, but it
is easy to apply it to new datatypes using <tt>%apply</tt>. For
example :</p>
<div class="code"><pre>
// Apply a constraint to a Real variable
%apply Number POSITIVE { Real in };
// Apply a constraint to a pointer type
%apply Pointer NONNULL { Vector * };
</pre></div>
<p>
The special types of "Number" and "Pointer" can be applied to any
numeric and pointer variable type respectively. To later remove a
constraint, the <tt>%clear</tt> directive can be used :</p>
<div class="code"><pre>
%clear Real in;
%clear Vector *;
</pre></div>
</body>
</html>

474
Doc/Manual/CCache.html Normal file
View File

@ -0,0 +1,474 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>ccache-swig(1) manpage</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="CCache">20 Using SWIG with ccache - ccache-swig(1) manpage</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#CCache_nn2">NAME</a>
<li><a href="#CCache_nn3">SYNOPSIS</a>
<li><a href="#CCache_nn4">DESCRIPTION</a>
<li><a href="#CCache_nn5">OPTIONS SUMMARY</a>
<li><a href="#CCache_nn6">OPTIONS</a>
<li><a href="#CCache_nn7">INSTALLATION</a>
<li><a href="#CCache_nn8">EXTRA OPTIONS</a>
<li><a href="#CCache_nn9">ENVIRONMENT VARIABLES</a>
<li><a href="#CCache_nn10">CACHE SIZE MANAGEMENT</a>
<li><a href="#CCache_nn11">CACHE COMPRESSION</a>
<li><a href="#CCache_nn12">HOW IT WORKS</a>
<li><a href="#CCache_nn13">USING CCACHE WITH DISTCC</a>
<li><a href="#CCache_nn14">SHARING A CACHE</a>
<li><a href="#CCache_nn15">HISTORY</a>
<li><a href="#CCache_nn16">DIFFERENCES FROM COMPILERCACHE</a>
<li><a href="#CCache_nn17">CREDITS</a>
<li><a href="#CCache_nn18">AUTHOR</a>
</ul>
</div>
<!-- INDEX -->
<p>
<H2><a name="CCache_nn2">20.1 NAME</a></H2>
<p>
ccache-swig - a fast compiler cache
<p>
<H2><a name="CCache_nn3">20.2 SYNOPSIS</a></H2>
<p>
ccache-swig [OPTION]
<p>
ccache-swig &lt;compiler&gt; [COMPILER OPTIONS]
<p>
&lt;compiler&gt; [COMPILER OPTIONS]
<p>
<H2><a name="CCache_nn4">20.3 DESCRIPTION</a></H2>
<p>
ccache-swig is a compiler cache. It speeds up re-compilation of C/C++/SWIG code
by caching previous compiles and detecting when the same compile is
being done again. ccache-swig is ccache plus support for SWIG. ccache
and ccache-swig are used interchangeably in this document.
<p>
<H2><a name="CCache_nn5">20.4 OPTIONS SUMMARY</a></H2>
<p>
Here is a summary of the options to ccache-swig.
<p>
<pre>
-s show statistics summary
-z zero statistics
-c run a cache cleanup
-C clear the cache completely
-F &lt;n&gt; set maximum files in cache
-M &lt;n&gt; set maximum size of cache (use G, M or K)
-h this help page
-V print version number
</pre>
<p>
<H2><a name="CCache_nn6">20.5 OPTIONS</a></H2>
<p>
These options only apply when you invoke ccache as "ccache-swig". When
invoked as a compiler none of these options apply. In that case your
normal compiler options apply and you should refer to your compilers
documentation.
<p>
<dl>
<p><dt><strong><strong>-h</strong></strong><dd> Print a options summary page
<p>
<p><dt><strong><strong>-s</strong></strong><dd> Print the current statistics summary for the cache. The
statistics are stored spread across the subdirectories of the
cache. Using "ccache-swig -s" adds up the statistics across all
subdirectories and prints the totals.
<p>
<p><dt><strong><strong>-z</strong></strong><dd> Zero the cache statistics.
<p>
<p><dt><strong><strong>-V</strong></strong><dd> Print the ccache version number
<p>
<p><dt><strong><strong>-c</strong></strong><dd> Clean the cache and re-calculate the cache file count and
size totals. Normally the -c option should not be necessary as ccache
keeps the cache below the specified limits at runtime and keeps
statistics up to date on each compile. This option is mostly useful
if you manually modify the cache contents or believe that the cache
size statistics may be inaccurate.
<p>
<p><dt><strong><strong>-C</strong></strong><dd> Clear the entire cache, removing all cached files.
<p>
<p><dt><strong><strong>-F &lt;maxfiles&gt;</strong></strong><dd> This sets the maximum number of files allowed in
the cache. The value is stored inside the cache directory and applies
to all future compiles. Due to the way the value is stored the actual
value used is always rounded down to the nearest multiple of 16.
<p>
<p><dt><strong><strong>-M &lt;maxsize&gt;</strong></strong><dd> This sets the maximum cache size. You can specify
a value in gigabytes, megabytes or kilobytes by appending a G, M or K
to the value. The default is gigabytes. The actual value stored is
rounded down to the nearest multiple of 16 kilobytes.
<p>
</dl>
<p>
<H2><a name="CCache_nn7">20.6 INSTALLATION</a></H2>
<p>
There are two ways to use ccache. You can either prefix your compile
commands with "ccache-swig" or you can create a symbolic link between
ccache-swig and the names of your compilers. The first method is most
convenient if you just want to try out ccache or wish to use it for
some specific projects. The second method is most useful for when you
wish to use ccache for all your compiles.
<p>
To install for usage by the first method just copy ccache-swig to somewhere
in your path.
<p>
To install for the second method do something like this:
<pre>
cp ccache-swig /usr/local/bin/
ln -s /usr/local/bin/ccache-swig /usr/local/bin/gcc
ln -s /usr/local/bin/ccache-swig /usr/local/bin/g++
ln -s /usr/local/bin/ccache-swig /usr/local/bin/cc
ln -s /usr/local/bin/ccache-swig /usr/local/bin/swig
</pre>
This will work as long as /usr/local/bin comes before the path to gcc
(which is usually in /usr/bin). After installing you may wish to run
"which gcc" to make sure that the correct link is being used.
<p>
Note! Do not use a hard link, use a symbolic link. A hardlink will
cause "interesting" problems.
<p>
<H2><a name="CCache_nn8">20.7 EXTRA OPTIONS</a></H2>
<p>
When run as a compiler front end ccache usually just takes the same
command line options as the compiler you are using. The only exception
to this is the option '--ccache-skip'. That option can be used to tell
ccache that the next option is definitely not a input filename, and
should be passed along to the compiler as-is.
<p>
The reason this can be important is that ccache does need to parse the
command line and determine what is an input filename and what is a
compiler option, as it needs the input filename to determine the name
of the resulting object file (among other things). The heuristic
ccache uses in this parse is that any string on the command line that
exists as a file is treated as an input file name (usually a C
file). By using --ccache-skip you can force an option to not be
treated as an input file name and instead be passed along to the
compiler as a command line option.
<p>
<H2><a name="CCache_nn9">20.8 ENVIRONMENT VARIABLES</a></H2>
<p>
ccache uses a number of environment variables to control operation. In
most cases you won't need any of these as the defaults will be fine.
<p>
<dl>
<p>
<p><dt><strong><strong>CCACHE_DIR</strong></strong><dd> the CCACHE_DIR environment variable specifies
where ccache will keep its cached compiler output. The default is
"$HOME/.ccache".
<p>
<p><dt><strong><strong>CCACHE_TEMPDIR</strong></strong><dd> the CCACHE_TEMPDIR environment variable specifies
where ccache will put temporary files. The default is the same as
CCACHE_DIR. Note that the CCACHE_TEMPDIR path must be on the same
filesystem as the CCACHE_DIR path, so that renames of files between
the two directories can work.
<p>
<p><dt><strong><strong>CCACHE_LOGFILE</strong></strong><dd> If you set the CCACHE_LOGFILE environment
variable then ccache will write some log information on cache hits
and misses in that file. This is useful for tracking down problems.
<p>
<p><dt><strong><strong>CCACHE_VERBOSE</strong></strong><dd> If you set the CCACHE_VERBOSE environment
variable then ccache will display on stdout all the compiler invocations
that it makes. This can useful for debugging unexpected problems.
<p>
<p><dt><strong><strong>CCACHE_PATH</strong></strong><dd> You can optionally set CCACHE_PATH to a colon
separated path where ccache will look for the real compilers. If you
don't do this then ccache will look for the first executable matching
the compiler name in the normal PATH that isn't a symbolic link to
ccache itself.
<p>
<p><dt><strong><strong>CCACHE_CC</strong></strong><dd> You can optionally set CCACHE_CC to force the name
of the compiler to use. If you don't do this then ccache works it out
from the command line.
<p>
<p><dt><strong><strong>CCACHE_PREFIX</strong></strong><dd> This option adds a prefix to the command line
that ccache runs when invoking the compiler. Also see the section
below on using ccache with distcc.
<p>
<p><dt><strong><strong>CCACHE_DISABLE</strong></strong><dd> If you set the environment variable
CCACHE_DISABLE then ccache will just call the real compiler,
bypassing the cache completely.
<p>
<p><dt><strong><strong>CCACHE_READONLY</strong></strong><dd> the CCACHE_READONLY environment variable
tells ccache to attempt to use existing cached object files, but not
to try to add anything new to the cache. If you are using this because
your CCACHE_DIR is read-only, then you may find that you also need to
set CCACHE_TEMPDIR as otherwise ccache will fail to create the
temporary files.
<p>
<p><dt><strong><strong>CCACHE_CPP2</strong></strong><dd> If you set the environment variable CCACHE_CPP2
then ccache will not use the optimisation of avoiding the 2nd call to
the pre-processor by compiling the pre-processed output that was used
for finding the hash in the case of a cache miss. This is primarily a
debugging option, although it is possible that some unusual compilers
will have problems with the intermediate filename extensions used in
this optimisation, in which case this option could allow ccache to be
used.
<p>
<p><dt><strong><strong>CCACHE_NOCOMPRESS</strong></strong><dd> If you set the environment variable
CCACHE_NOCOMPRESS then there is no compression used on files that go
into the cache. However, this setting has no effect on how files are
retrieved from the cache, compressed results will still be usable.
<p>
<p><dt><strong><strong>CCACHE_NOSTATS</strong></strong><dd> If you set the environment variable
CCACHE_NOSTATS then ccache will not update the statistics files on
each compile.
<p>
<p><dt><strong><strong>CCACHE_NLEVELS</strong></strong><dd> The environment variable CCACHE_NLEVELS allows
you to choose the number of levels of hash in the cache directory. The
default is 2. The minimum is 1 and the maximum is 8.
<p>
<p><dt><strong><strong>CCACHE_HARDLINK</strong></strong><dd> If you set the environment variable
CCACHE_HARDLINK then ccache will attempt to use hard links from the
cache directory when creating the compiler output rather than using a
file copy. Using hard links is faster, but can confuse programs like
'make' that rely on modification times. Hard links are never made for
compressed cache files.
<p>
<p><dt><strong><strong>CCACHE_RECACHE</strong></strong><dd> This forces ccache to not use any cached
results, even if it finds them. New results are still cached, but
existing cache entries are ignored.
<p>
<p><dt><strong><strong>CCACHE_UMASK</strong></strong><dd> This sets the umask for ccache and all child
processes (such as the compiler). This is mostly useful when you wish
to share your cache with other users. Note that this also affects the
file permissions set on the object files created from your
compilations.
<p>
<p><dt><strong><strong>CCACHE_HASHDIR</strong></strong><dd> This tells ccache to hash the current working
directory when calculating the hash that is used to distinguish two
compiles. This prevents a problem with the storage of the current
working directory in the debug info of a object file, which can lead
ccache to give a cached object file that has the working directory in
the debug info set incorrectly. This option is off by default as the
incorrect setting of this debug info rarely causes problems. If you
strike problems with gdb not using the correct directory then enable
this option.
<p>
<p><dt><strong><strong>CCACHE_UNIFY</strong></strong><dd> If you set the environment variable CCACHE_UNIFY
then ccache will use the C/C++ unifier when hashing the pre-processor
output if -g is not used in the compile. The unifier is slower than a
normal hash, so setting this environment variable loses a little bit
of speed, but it means that ccache can take advantage of not
recompiling when the changes to the source code consist of
reformatting only. Note that using CCACHE_UNIFY changes the hash, so
cached compiles with CCACHE_UNIFY set cannot be used when
CCACHE_UNIFY is not set and vice versa. The reason the unifier is off
by default is that it can give incorrect line number information in
compiler warning messages.
<p>
<p><dt><strong><strong>CCACHE_EXTENSION</strong></strong><dd> Normally ccache tries to automatically
determine the extension to use for intermediate C pre-processor files
based on the type of file being compiled. Unfortunately this sometimes
doesn't work, for example when using the aCC compiler on HP-UX. On
systems like this you can use the CCACHE_EXTENSION option to override
the default. On HP-UX set this environment variable to "i" if you use
the aCC compiler.
<p>
<p><dt><strong><strong>CCACHE_STRIPC</strong></strong><dd> If you set the environment variable
CCACHE_STRIPC then ccache will strip the -c option when invoking
the preprocessor. This option is primarily for the Sun Workshop
C++ compiler as without this option an unwarranted warning is displayed:
CC: Warning: "-E" redefines product from "object" to "source (stdout)"
when -E and -c is used together.
<p>
<p><dt><strong><strong>CCACHE_SWIG</strong></strong><dd> When using SWIG as the compiler and it does not
have 'swig' in the executable name, then the CCACHE_SWIG environment
variable needs to be set in order for ccache to work correctly with
SWIG. The use of CCACHE_CPP2 is also recommended for SWIG due to some
preprocessor quirks, however, use of CCACHE_CPP2 can often be skipped
-- check your generated code with and without this option set. Known
problems are using preprocessor directives within %inline blocks and
the use of '#pragma SWIG'.
<p>
</dl>
<p>
<H2><a name="CCache_nn10">20.9 CACHE SIZE MANAGEMENT</a></H2>
<p>
By default ccache has a one gigabyte limit on the cache size and no
maximum number of files. You can set a different limit using the
"ccache -M" and "ccache -F" options, which set the size and number of
files limits.
<p>
When these limits are reached ccache will reduce the cache to 20%
below the numbers you specified in order to avoid doing the cache
clean operation too often.
<p>
<H2><a name="CCache_nn11">20.10 CACHE COMPRESSION</a></H2>
<p>
By default on most platforms ccache will compress all files it puts
into the cache
using the zlib compression. While this involves a negligible
performance slowdown, it significantly increases the number of files
that fit in the cache. You can turn off compression setting the
CCACHE_NOCOMPRESS environment variable.
<p>
<H2><a name="CCache_nn12">20.11 HOW IT WORKS</a></H2>
<p>
The basic idea is to detect when you are compiling exactly the same
code a 2nd time and use the previously compiled output. You detect
that it is the same code by forming a hash of:
<p>
<ul>
<li> the pre-processor output from running the compiler with -E
<li> the command line options
<li> the real compilers size and modification time
<li> any stderr output generated by the compiler
</ul>
<p>
These are hashed using md4 (a strong hash) and a cache file is formed
based on that hash result. When the same compilation is done a second
time ccache is able to supply the correct compiler output (including
all warnings etc) from the cache.
<p>
ccache has been carefully written to always produce exactly the same
compiler output that you would get without the cache. If you ever
discover a case where ccache changes the output of your compiler then
please let me know.
<p>
<H2><a name="CCache_nn13">20.12 USING CCACHE WITH DISTCC</a></H2>
<p>
distcc is a very useful program for distributing compilation across a
range of compiler servers. It is often useful to combine distcc with
ccache, so that compiles that are done are sped up by distcc, but that
ccache avoids the compile completely where possible.
<p>
To use distcc with ccache I recommend using the CCACHE_PREFIX
option. You just need to set the environment variable CCACHE_PREFIX to
'distcc' and ccache will prefix the command line used with the
compiler with the command 'distcc'.
<p>
<H2><a name="CCache_nn14">20.13 SHARING A CACHE</a></H2>
<p>
A group of developers can increase the cache hit rate by sharing a
cache directory. The hard links however cause unwanted side effects,
as all links to a cached file share the file's modification timestamp.
This results in false dependencies to be triggered by timestamp-based
build systems whenever another user links to an existing
file. Typically, users will see that their libraries and binaries are
relinked without reason. To share a cache without side effects, the
following conditions need to be met:
<p>
<ul>
<li> Use the same <strong>CCACHE_DIR</strong> environment variable setting
<li> Unset the <strong>CCACHE_HARDLINK</strong> environment variable
<li> Make sure everyone sets the CCACHE_UMASK environment variable
to 002, this ensures that cached files are accessible to everyone in
the group.
<li> Make sure that all users have write permission in the entire
cache directory (and that you trust all users of the shared cache).
<li> Make sure that the setgid bit is set on all directories in the
cache. This tells the filesystem to inherit group ownership for new
directories. The command "chmod g+s `find $CCACHE_DIR -type d`" might
be useful for this.
<li> Set <strong>CCACHE_NOCOMPRESS</strong> for all users, if there are users with
versions of ccache that do not support compression.
</ul>
<p>
<H2><a name="CCache_nn15">20.14 HISTORY</a></H2>
<p>
ccache was inspired by the compilercache shell script written
by Erik Thiele and I would like to thank him for an excellent piece of
work. See
<a href="http://www.erikyyy.de/compilercache/">http://www.erikyyy.de/compilercache/</a>
for the Erik's scripts.
ccache-swig is a port of the original ccache with support added for use
with SWIG.
<p>
I wrote ccache because I wanted to get a bit more speed out of a
compiler cache and I wanted to remove some of the limitations of the
shell-script version.
<p>
<H2><a name="CCache_nn16">20.15 DIFFERENCES FROM COMPILERCACHE</a></H2>
<p>
The biggest differences between Erik's compilercache script and ccache
are:
<ul>
<li> ccache is written in C, which makes it a bit faster (calling out to
external programs is mostly what slowed down the scripts).
<li> ccache can automatically find the real compiler
<li> ccache keeps statistics on hits/misses
<li> ccache can do automatic cache management
<li> ccache can cache compiler output that includes warnings. In many
cases this gives ccache a much higher cache hit rate.
<li> ccache can handle a much wider ranger of compiler options
<li> ccache avoids a double call to cpp on a cache miss
</ul>
<p>
<H2><a name="CCache_nn17">20.16 CREDITS</a></H2>
<p>
Thanks to the following people for their contributions to ccache
<ul>
<li> Erik Thiele for the original compilercache script
<li> Luciano Rocha for the idea of compiling the pre-processor output
to avoid a 2nd cpp pass
<li> Paul Russell for many suggestions and the debian packaging
</ul>
<p>
<H2><a name="CCache_nn18">20.17 AUTHOR</a></H2>
<p>
ccache was written by Andrew Tridgell
<a href="https://www.samba.org/~tridge/">https://www.samba.org/~tridge/</a>.
ccache was adapted to create ccache-swig for use with SWIG by William Fulton.
<p>
If you wish to report a problem or make a suggestion then please email
the SWIG developers on the swig-devel mailing list, see
<a href="http://www.swig.org/mail.html">http://www.swig.org/mail.html</a>
<p>
ccache is released under the GNU General Public License version 2 or
later. Please see the file COPYING for license details.
<p>
</body>
</html>

1299
Doc/Manual/CPlusPlus11.html Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and C++14</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="CPlusPlus14">8 SWIG and C++14</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#CPlusPlus14_introduction">Introduction</a>
<li><a href="#CPlusPlus14_core_language_changes">Core language changes</a>
<ul>
<li><a href="#CPlusPlus14_binary_literals">Binary integer literals</a>
</ul>
<li><a href="#CPlusPlus14_standard_library_changes">Standard library changes</a>
</ul>
</div>
<!-- INDEX -->
<H2><a name="CPlusPlus14_introduction">8.1 Introduction</a></H2>
<p>This chapter gives you a brief overview about the SWIG
implementation of the C++14 standard.
There isn't much in C++14 that affects SWIG, however, work has only just begun on adding
C++14 support.
</p>
<p>
<b>Compatibility note:</b> SWIG-4.0.0 is the first version to support any C++14 features.
</p>
<H2><a name="CPlusPlus14_core_language_changes">8.2 Core language changes</a></H2>
<H3><a name="CPlusPlus14_binary_literals">8.2.1 Binary integer literals</a></H3>
<p>
C++14 added binary integer literals and SWIG supports these.
Example:
</p>
<div class="code">
<pre>
int b = 0b101011;
</pre>
</div>
<H2><a name="CPlusPlus14_standard_library_changes">8.3 Standard library changes</a></H2>
</body>
</html>

109
Doc/Manual/CPlusPlus17.html Normal file
View File

@ -0,0 +1,109 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and C++17</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="CPlusPlus17">9 SWIG and C++17</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#CPlusPlus17_introduction">Introduction</a>
<li><a href="#CPlusPlus17_core_language_changes">Core language changes</a>
<ul>
<li><a href="#CPlusPlus17_nested_namespaces">Nested namespace definitions</a>
<li><a href="#CPlusPlus17_u8_char_literals">UTF-8 character literals</a>
<li><a href="#CPlusPlus17_hexadecimal_floating_literals">Hexadecimal floating literals</a>
</ul>
<li><a href="#CPlusPlus17_standard_library_changes">Standard library changes</a>
</ul>
</div>
<!-- INDEX -->
<H2><a name="CPlusPlus17_introduction">9.1 Introduction</a></H2>
<p>This chapter gives you a brief overview about the SWIG
implementation of the C++17 standard.
There isn't much in C++17 that affects SWIG, however, work has only just begun on adding
C++17 support.
</p>
<p>
<b>Compatibility note:</b> SWIG-4.0.0 is the first version to support any C++17 features.
</p>
<H2><a name="CPlusPlus17_core_language_changes">9.2 Core language changes</a></H2>
<H3><a name="CPlusPlus17_nested_namespaces">9.2.1 Nested namespace definitions</a></H3>
<p>
C++17 offers a more concise syntax for defining namespaces.
SWIG has support for nested namespace definitions such as:
</p>
<div class="code">
<pre>
namespace A::B::C {
...
}
</pre>
</div>
<p>
This is the equivalent to the C++98 namespace definitions:
</p>
<div class="code">
<pre>
namespace A {
namespace B {
namespace C {
...
}
}
}
</pre>
</div>
<H3><a name="CPlusPlus17_u8_char_literals">9.2.2 UTF-8 character literals</a></H3>
<p>
C++17 added UTF-8 (u8) character literals.
These are of type char.
Example:
</p>
<div class="code">
<pre>
char a = u8'a';
</pre>
</div>
<H3><a name="CPlusPlus17_hexadecimal_floating_literals">9.2.3 Hexadecimal floating literals</a></H3>
<p>
C++17 added hexadecimal floating literals.
For example:
</p>
<div class="code">
<pre>
double f = 0xF.68p2;
</pre>
</div>
<H2><a name="CPlusPlus17_standard_library_changes">9.3 Standard library changes</a></H2>
</body>
</html>

2788
Doc/Manual/CSharp.html Normal file

File diff suppressed because it is too large Load Diff

597
Doc/Manual/Chicken.html Normal file
View File

@ -0,0 +1,597 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Chicken</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Chicken">23 SWIG and Chicken</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Chicken_nn2">Preliminaries</a>
<ul>
<li><a href="#Chicken_nn3">Running SWIG in C mode</a>
<li><a href="#Chicken_nn4">Running SWIG in C++ mode</a>
</ul>
<li><a href="#Chicken_nn5">Code Generation</a>
<ul>
<li><a href="#Chicken_nn6">Naming Conventions</a>
<li><a href="#Chicken_nn7">Modules</a>
<li><a href="#Chicken_nn8">Constants and Variables</a>
<li><a href="#Chicken_nn9">Functions</a>
<li><a href="#Chicken_nn10">Exceptions</a>
</ul>
<li><a href="#Chicken_nn11">TinyCLOS</a>
<li><a href="#Chicken_nn12">Linkage</a>
<ul>
<li><a href="#Chicken_nn13">Static binary or shared library linked at compile time</a>
<li><a href="#Chicken_nn14">Building chicken extension libraries</a>
<li><a href="#Chicken_nn15">Linking multiple SWIG modules with TinyCLOS</a>
</ul>
<li><a href="#Chicken_nn16">Typemaps</a>
<li><a href="#Chicken_nn17">Pointers</a>
<ul>
<li><a href="#Chicken_collection">Garbage collection</a>
</ul>
<li><a href="#Chicken_nn18">Unsupported features and known problems</a>
<ul>
<li><a href="#Chicken_nn19">TinyCLOS problems with Chicken version &lt;= 1.92</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
This chapter describes SWIG's support of CHICKEN. CHICKEN is a
Scheme-to-C compiler supporting most of the language features as
defined in the <i>Revised^5 Report on Scheme</i>. Its main
attributes are that it
</p>
<ol>
<li>generates portable C code</li>
<li>includes a customizable interpreter</li>
<li>links to C libraries with a simple Foreign Function Interface</li>
<li>supports full tail-recursion and first-class continuations</li>
</ol>
<p>
When confronted with a large C library, CHICKEN users can use
SWIG to generate CHICKEN wrappers for the C library. However,
the real advantages of using SWIG with CHICKEN are its
<strong>support for C++</strong> -- object-oriented code is
difficult to wrap by hand in CHICKEN -- and its <strong>typed
pointer representation</strong>, essential for C and C++
libraries involving structures or classes.
</p>
<H2><a name="Chicken_nn2">23.1 Preliminaries</a></H2>
<p>
CHICKEN support was introduced to SWIG in version 1.3.18. SWIG
relies on some recent additions to CHICKEN, which are only
present in releases of CHICKEN with version number
<strong>greater than or equal to 1.89</strong>.
To use a chicken version between 1.40 and 1.89, see the <a href="#Chicken_collection">Garbage collection</a>
section below.
</p>
<p>
You may want to look at any of the examples in Examples/chicken/
directory for the basic steps to run SWIG CHICKEN.
</p>
<H3><a name="Chicken_nn3">23.1.1 Running SWIG in C mode</a></H3>
<p>
To run SWIG CHICKEN in C mode, use
the -chicken option.
</p>
<div class="shell">
<pre>% swig -chicken example.i</pre>
</div>
<p>
To allow the wrapper to take advantage of future CHICKEN code
generation improvements, part of the wrapper is direct CHICKEN
function calls (<tt>example_wrap.c</tt>) and part is CHICKEN
Scheme (<tt>example.scm</tt>). The basic Scheme code must
be compiled to C using your system's CHICKEN compiler or
both files can be compiled directly using the much simpler <tt>csc</tt>.
</p>
<div class="shell">
<pre>
% chicken example.scm -output-file oexample.c
</pre>
</div>
<p>
So for the C mode of SWIG CHICKEN, <tt>example_wrap.c</tt> and
<tt>oexample.c</tt> are the files that must be compiled to
object files and linked into your project.
</p>
<H3><a name="Chicken_nn4">23.1.2 Running SWIG in C++ mode</a></H3>
<p>
To run SWIG CHICKEN in C++ mode, use
the -chicken -c++ option.
</p>
<div class="shell">
<pre>% swig -chicken -c++ example.i</pre>
</div>
<p>
This will generate <tt>example_wrap.cxx</tt> and
<tt>example.scm</tt>. The basic Scheme code must be
compiled to C using your system's CHICKEN compiler or
both files can be compiled directly using the much simpler <tt>csc</tt>.
</p>
<div class="shell">
<pre>% chicken example.scm -output-file oexample.c</pre>
</div>
<p>
So for the C++ mode of SWIG CHICKEN, <tt>example_wrap.cxx</tt>
and <tt>oexample.c</tt> are the files that must be compiled to
object files and linked into your project.
</p>
<H2><a name="Chicken_nn5">23.2 Code Generation</a></H2>
<H3><a name="Chicken_nn6">23.2.1 Naming Conventions</a></H3>
<p>
Given a C variable, function or constant declaration named
<tt>Foo_Bar</tt>, the declaration will be available
in CHICKEN as an identifier ending with
<tt>Foo-Bar</tt>. That is, an underscore is converted
to a dash.
</p>
<p>
You may control what the CHICKEN identifier will be by using the
<tt>%rename</tt> SWIG directive in the SWIG interface file.
</p>
<H3><a name="Chicken_nn7">23.2.2 Modules</a></H3>
<p>
The name of the module must be declared one of two ways:
<ul>
<li>Placing <tt>%module example</tt> in the SWIG interface
file.</li>
<li>Using <tt>-module example</tt> on the SWIG command
line.</li>
</ul>
<p>
The generated example.scm file then exports <code>(declare (unit modulename))</code>.
If you do not want SWIG to export the <code>(declare (unit modulename))</code>, pass
the -nounit option to SWIG.
<p>
CHICKEN will be able to access the module using the <code>(declare
(uses <i>modulename</i>))</code> CHICKEN Scheme form.
</p>
<H3><a name="Chicken_nn8">23.2.3 Constants and Variables</a></H3>
<p>
Constants may be created using any of the four constructs in
the interface file:
</p>
<ol>
<li><code>#define MYCONSTANT1 ...</code></li>
<li><code>%constant int MYCONSTANT2 = ...</code></li>
<li><code>const int MYCONSTANT3 = ...</code></li>
<li><code>enum { MYCONSTANT4 = ... };</code></li>
</ol>
<p>
In all cases, the constants may be accessed from within CHICKEN
using the form <tt>(MYCONSTANT1)</tt>; that is, the constants
may be accessed using the read-only parameter form.
</p>
<p>
Variables are accessed using the full parameter form.
For example, to set the C variable "int my_variable;", use the
Scheme form <tt>(my-variable 2345)</tt>. To get the C variable,
use <tt>(my-variable)</tt>.
</p>
<p>
The <tt>%feature("constasvar")</tt> can be applied to any constant
or immutable variable. Instead of exporting the constant as
a function that must be called, the constant will appear as a
scheme variable. This causes the generated .scm file to just contain the code
<tt>(set! MYCONSTANT1 (MYCONSTANT1))</tt>. See
<a href="Customization.html#Customization_features">Features and the %feature directive</a>
for info on how to apply the %feature.
</p>
<H3><a name="Chicken_nn9">23.2.4 Functions</a></H3>
<p>
C functions declared in the SWIG interface file will have
corresponding CHICKEN Scheme procedures. For example, the C
function "int sqrt(double x);" will be available using the
Scheme form <tt>(sqrt 2345.0)</tt>. A <code>void</code> return
value will give C_SCHEME_UNDEFINED as a result.
</p>
<p>
A function may return more than one value by using the
<code>OUTPUT</code> specifier (see Lib/chicken/typemaps.i).
They will be returned as multiple values using <code>(values)</code> if there is more than one
result (that is, a non-void return value and at least one argout
parameter, or a void return value and at least two argout
parameters). The return values can then be accessed with <code>(call-with-values)</code>.
</p>
<H3><a name="Chicken_nn10">23.2.5 Exceptions</a></H3>
<p>The SWIG chicken module has support for exceptions thrown from
C or C++ code to be caught in scheme.
See <a href="Customization.html#Customization_exception">Exception handling with %exception</a>
for more information about declaring exceptions in the interface file.
</p>
<p>Chicken supports both the <code>SWIG_exception(int code, const char *msg)</code> interface
as well as a <code>SWIG_ThrowException(C_word val)</code> function for throwing exceptions from
inside the %exception blocks. <code>SWIG_exception</code> will throw a list consisting of the code
(as an integer) and the message. Both of these will throw an exception using <code>(abort)</code>,
which can be handled by <code>(handle-exceptions)</code>. See
the Chicken manual on Exceptions
and <a href="http://srfi.schemers.org/srfi-12/srfi-12.html">SFRI-12</a>. Since the exception values are thrown
directly, if <code>(condition-case)</code> is used to catch an exception the exception will come through in the <code>val ()</code> case.
</p>
<p>The following simple module</p>
<div class="code"><pre>
%module exception_test
%inline %{
void test_throw(int i) throws (int) {
if (i == 1) throw 15;
}
%}
</pre></div>
<p>could be run with</p>
<div class="targetlang"><pre>
(handle-exceptions exvar
(if (= exvar 15)
(print "Correct!")
(print "Threw something else " exvar))
(test-throw 1))
</pre></div>
<H2><a name="Chicken_nn11">23.3 TinyCLOS</a></H2>
<p>
The author of TinyCLOS, Gregor Kiczales, describes TinyCLOS as:
"Tiny CLOS is a Scheme implementation of a 'kernelized' CLOS, with a
metaobject protocol. The implementation is even simpler than
the simple CLOS found in 'The Art of the Metaobject Protocol',
weighing in at around 850 lines of code, including (some)
comments and documentation."
</p>
<p>
Almost all good Scheme books describe how to use metaobjects and
generic procedures to implement an object-oriented Scheme
system. Please consult a Scheme book if you are unfamiliar
with the concept.
</p>
<p>
CHICKEN has a modified version of TinyCLOS, which SWIG CHICKEN
uses if the -proxy argument is given. If -proxy is passed, then
the generated example.scm file will contain TinyCLOS class definitions.
A class named Foo is declared as &lt;Foo&gt;, and each member variable
is allocated a slot. Member functions are exported as generic functions.
<p>
Primitive symbols and functions (the interface that would be presented if
-proxy was not passed) are hidden and no longer accessible. If the -unhideprimitive
command line argument is passed to SWIG, then the primitive symbols will be
available, but each will be prefixed by the string "primitive:"
<p>
The exported symbol names can be controlled with the -closprefix and -useclassprefix arguments.
If -useclassprefix is passed to SWIG, every member function will be generated with the class name
as a prefix. If the -closprefix mymod: argument is passed to SWIG, then the exported functions will
be prefixed by the string "mymod:". If -useclassprefix is passed, -closprefix is ignored.
</p>
<H2><a name="Chicken_nn12">23.4 Linkage</a></H2>
<p>
Please refer to <em>CHICKEN - A practical and portable Scheme
system - User's manual</em> for detailed help on how to link
object files to create a CHICKEN Scheme program. Briefly, to
link object files, be sure to add <tt>`chicken-config
-extra-libs -libs`</tt> or <tt>`chicken-config -shared
-extra-libs -libs`</tt>to your linker options. Use the
<tt>-shared</tt> option if you want to create a dynamically
loadable module. You might also want to use the much simpler
<tt>csc</tt> or <tt>csc.bat</tt>.
</p>
<p>Each scheme file that is generated
by SWIG contains <code>(declare (uses <i>modname</i>))</code>. This means that to load the
module from scheme code, the code must include <code>(declare (uses <i>modname</i>))</code>.
</p>
<H3><a name="Chicken_nn13">23.4.1 Static binary or shared library linked at compile time</a></H3>
<p>We can easily use csc to build a static binary.</p>
<div class="shell">
<pre>
$ swig -chicken example.i
$ csc -v example.scm example_impl.c example_wrap.c test_script.scm -o example
$ ./example
</pre>
</div>
<p>Similar to the above, any number of <tt>module.scm</tt> files could be compiled
into a shared library, and then that shared library linked when compiling the
main application.</p>
<div class="shell">
<pre>
$ swig -chicken example.i
$ csc -sv example.scm example_wrap.c example_impl.c -o example.so
</pre>
</div>
<p>The <tt>example.so</tt> file can then linked with <tt>test_script.scm</tt> when it
is compiled, in which case <tt>test_script.scm</tt> must have <code>(declare (uses example))</code>.
Multiple SWIG modules could have been linked into <tt>example.so</tt> and each
one accessed with a <code>(declare (uses ... ))</code>.
</p>
<div class="shell">
<pre>
$ csc -v test_script.scm -lexample
</pre>
</div>
<p>An alternative is that the test_script.scm can have the code <code>(load-library 'example "example.so")</code>,
in which case the test script does not need to be linked with example.so. The test_script.scm file can then
be run with <tt>csi</tt>.
</p>
<H3><a name="Chicken_nn14">23.4.2 Building chicken extension libraries</a></H3>
<p>Building a shared library like in the above section only works if the library
is linked at compile time with a script containing <code>(declare (uses ...))</code> or is
loaded explicitly with <code>(load-library 'example "example.so")</code>. It is
not the format that CHICKEN expects for extension libraries and eggs. The problem is the
<code>(declare (unit <i>modname</i>))</code> inside the <tt>modname.scm</tt> file. There are
two possible solutions to this.</p>
<p>First, SWIG accepts a <tt>-nounit</tt> argument, in which case the <code>(declare (unit <i>modname</i>))</code>
is not generated. Then, the <tt>modname.scm</tt> and <tt>modname_wrap.c</tt> files <b>must</b> be compiled into
their own shared library.</p>
<div class="shell">
<pre>
$ csc -sv modname.scm modname_wrap.c modname_impl.c -o modname.so
</pre>
</div>
<p>This library can then be loaded by scheme code with the <code>(require 'modname)</code> function.
See the
Loading-extension-libraries in the eval unit inside the CHICKEN manual for more information.</p>
<p>Another alternative is to run SWIG normally and create a scheme file that contains <code>(declare (uses <i>modname</i>))</code>
and then compile that file into the shared library as well. For example, inside the <tt>mod_load.scm</tt> file,</p>
<div class="targetlang">
<pre>
(declare (uses mod1))
(declare (uses mod2))
</pre>
</div>
<p>Which would then be compiled with</p>
<div class="shell">
<pre>
$ swig -chicken mod1.i
$ swig -chicken mod2.i
$ csc -sv mod_load.scm mod1.scm mod2.scm mod1_wrap.c mod2_wrap.c mod1_impl.c mod2_impl.c -o mod.so
</pre>
</div>
<p>Then the extension library can be loaded with <code>(require 'mod)</code>. As we can see here,
<tt>mod_load.scm</tt> contains the code that gets executed when the module is loaded. All this code
does is load both mod1 and mod2. As we can see, this technique is more useful when you want to
combine a few SWIG modules into one chicken extension library, especially if modules are related by
<code>%import</code></p>
<p>In either method, the files that are compiled into the shared library could also be
packaged into an egg. The <tt>mod1_wrap.c</tt> and <tt>mod2_wrap.c</tt> files that are created by SWIG
are stand alone and do not need SWIG to be installed to be compiled. Thus the egg could be
distributed and used by anyone, even if SWIG is not installed.</p>
<p>See the <tt>Examples/chicken/egg</tt> directory in the SWIG source for an example that builds
two eggs, one using the first method and one using the second method.</p>
<H3><a name="Chicken_nn15">23.4.3 Linking multiple SWIG modules with TinyCLOS</a></H3>
<p>Linking together multiple modules that share type information using the <code>%import</code>
directive while also using <tt>-proxy</tt> is more complicated. For example, if <tt>mod2.i</tt> imports <tt>mod1.i</tt>, then the
<tt>mod2.scm</tt> file contains references to symbols declared in <tt>mod1.scm</tt>,
and thus a <code>(declare (uses <i>mod1</i>))</code> or <code>(require '<i>mod1</i>)</code> must be exported
to the top of <tt>mod2.scm</tt>. By default, when SWIG encounters an <code>%import "modname.i"</code> directive,
it exports <code>(declare (uses <i>modname</i>))</code> into the scm file. This works fine unless mod1 was compiled with
the <tt>-nounit</tt> argument or was compiled into an extension library with other modules under a different name.</p>
<p>One option is to override the automatic generation of <code>(declare (uses mod1))</code>
by passing the <tt>-noclosuses</tt> option to SWIG when compiling <tt>mod2.i</tt>.
SWIG then provides the <code>%insert(closprefix) %{ %}</code> directive. Any scheme code inside that directive is inserted into the
generated .scm file, and if <tt>mod1</tt> was compiled with <tt>-nounit</tt>, the directive should contain <code>(require 'mod1)</code>.
This option allows for mixed loading as well, where some modules are imported with <code>(declare (uses <i>modname</i>))</code>
(which means they were compiled without -nounit) and some are imported with <code>(require 'modname)</code>.</p>
<p>The other option is to use the second idea in the above section. Compile all the modules normally, without any
<code>%insert(closprefix)</code>, <tt>-nounit</tt>, or <tt>-noclosuses</tt>. Then the modules will import each other correctly
with <code>(declare (uses ...))</code>.
To create an extension library or an egg, just create a <tt>module_load.scm</tt> file that <code>(declare (uses ...))</code>
all the modules.</p>
<H2><a name="Chicken_nn16">23.5 Typemaps</a></H2>
<p>
The Chicken module handles all types via typemaps. This information is
read from <code>Lib/chicken/typemaps.i</code> and
<code>Lib/chicken/chicken.swg</code>.
</p>
<H2><a name="Chicken_nn17">23.6 Pointers</a></H2>
<p>
For pointer types, SWIG uses CHICKEN tagged pointers.
A tagged pointer is an ordinary CHICKEN pointer with an
extra slot for a void *. With SWIG
CHICKEN, this void * is a pointer to a type-info
structure. So each pointer used as input or output from
the SWIG-generated CHICKEN wrappers will have type
information attached to it. This will let the wrappers
correctly determine which method should be called
according to the object type hierarchy exposed in the SWIG
interface files.
</p>
<p>
To construct a Scheme object from a C pointer, the wrapper code
calls the function
<code>SWIG_NewPointerObj(void *ptr, swig_type_info *type, int owner)</code>,
The function that calls <code>SWIG_NewPointerObj</code> must have a variable declared
<code>C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER);</code>
It is ok to call <code>SWIG_NewPointerObj</code> more than once,
just make sure known_space has enough space for all the created pointers.
</p>
<p>
To get the pointer represented by a CHICKEN tagged pointer, the
wrapper code calls the function
<code>SWIG_ConvertPtr(C_word s, void **result, swig_type_info *type, int flags)</code>,
passing a pointer to a struct representing the expected pointer
type. flags is either zero or SWIG_POINTER_DISOWN (see below).
</p>
<H3><a name="Chicken_collection">23.6.1 Garbage collection</a></H3>
<p>If the owner flag passed to <code>SWIG_NewPointerObj</code> is 1, <code>NewPointerObj</code> will add a
finalizer to the type which will call the destructor or delete method of
that type. The destructor and delete functions are no longer exported for
use in scheme code, instead SWIG and chicken manage pointers.
In situations where SWIG knows that a function is returning a type that should
be garbage collected, SWIG will automatically set the owner flag to 1. For other functions,
the <code>%newobject</code> directive must be specified for functions whose return values
should be garbage collected. See
<a href="Customization.html#Customization_ownership">Object ownership and %newobject</a> for more information.
</p>
<p>In situations where a C or C++ function will assume ownership of a pointer, and thus
chicken should no longer garbage collect it, SWIG provides the <code>DISOWN</code> input typemap.
After applying this typemap (see the <a href="Typemaps.html#Typemaps">Typemaps chapter</a> for more information on how to apply typemaps),
any pointer that gets passed in will no longer be garbage collected.
An object is disowned by passing the <code>SWIG_POINTER_DISOWN</code> flag to <code>SWIG_ConvertPtr</code>.
<b>Warning:</b> Since the lifetime of the object is now controlled by the underlying code, the object might
get deleted while the scheme code still holds a pointer to it. Further use of this pointer
can lead to a crash.
</p>
<p>Adding a finalizer function from C code was added to chicken in the 1.89 release, so garbage collection
does not work for chicken versions below 1.89. If you would like the SWIG generated code to work with
chicken 1.40 to 1.89, pass the <code>-nocollection</code> argument to SWIG. This will not export code
inside the _wrap.c file to register finalizers, and will then export destructor functions which
must be called manually.
</p>
<H2><a name="Chicken_nn18">23.7 Unsupported features and known problems</a></H2>
<ul>
<li>No director support.</li>
<li>No support for c++ standard types like std::vector.</li>
<li>The TinyCLOS wrappers for overloaded functions will not work correctly when using
<a href="SWIGPlus.html#SWIGPlus_default_args">%feature(compactdefaultargs)</a>.</li>
</ul>
<H3><a name="Chicken_nn19">23.7.1 TinyCLOS problems with Chicken version &lt;= 1.92</a></H3>
<p>In Chicken versions equal to or below 1.92, TinyCLOS has a limitation such that generic methods do not properly work on methods
with different number of specializers: TinyCLOS assumes that every method added to a generic function
will have the same number of specializers. SWIG generates functions with different lengths of specializers
when C/C++ functions are overloaded. For example, the code</p>
<div class="code">
<pre>
class Foo {};
int foo(int a, Foo *b);
int foo(int a);
</pre></div>
<p>will produce scheme code</p>
<div class="targetlang">
<pre>
(define-method (foo (arg0 &lt;top&gt;) (arg1 &lt;Foo&gt;)) (<i>call primitive function</i>))
(define-method (foo (arg0 &lt;top&gt;)) (<i>call primitive function</i>))
</pre></div>
<p>Using unpatched TinyCLOS, the second <code>(define-method)</code> will replace the first one,
so calling <code>(foo 3 f)</code> will produce an error.</p>
<p>There are three solutions to this. The easist is to upgrade to the latest Chicken version. Otherwise, the
file <tt>Lib/chicken/tinyclos-multi-generic.patch</tt> in the SWIG source contains a patch against
tinyclos.scm inside the 1.92 chicken source to add support into TinyCLOS for multi-argument generics. (This patch was accepted into Chicken)
This requires chicken to be rebuilt and custom install of chicken. An alternative is the <tt>Lib/chicken/multi-generic.scm</tt>
file in the SWIG source. This file can be loaded after TinyCLOS is loaded, and it will override some functions
inside TinyCLOS to correctly support multi-argument generics. Please see the comments at the top of both files for more information.</p>
</body>
</html>

1914
Doc/Manual/Contents.html Normal file

File diff suppressed because it is too large Load Diff

275
Doc/Manual/Contract.html Normal file
View File

@ -0,0 +1,275 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Contract Checking</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Contract">15 Contracts</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Contract_nn2">The %contract directive</a>
<li><a href="#Contract_nn3">%contract and classes</a>
<li><a href="#Contract_nn4">Constant aggregation and %aggregate_check</a>
<li><a href="#Contract_nn5">Notes</a>
</ul>
</div>
<!-- INDEX -->
<p>
A common problem that arises when wrapping C libraries is that of maintaining
reliability and checking for errors. The fact of the matter is that many
C programs are notorious for not providing error checks. Not only that,
when you expose the internals of an application as a library, it
often becomes possible to crash it simply by providing bad inputs or
using it in a way that wasn't intended.
</p>
<p>
This chapter describes SWIG's support for software contracts. In the context
of SWIG, a contract can be viewed as a runtime constraint that is attached
to a declaration. For example, you can easily attach argument checking rules,
check the output values of a function and more.
When one of the rules is violated by a script, a runtime exception is
generated rather than having the program continue to execute.
</p>
<H2><a name="Contract_nn2">15.1 The %contract directive</a></H2>
<p>
Contracts are added to a declaration using the %contract directive. Here
is a simple example:
</p>
<div class="code">
<pre>
%contract sqrt(double x) {
require:
x &gt;= 0;
ensure:
sqrt &gt;= 0;
}
...
double sqrt(double);
</pre>
</div>
<p>
In this case, a contract is being added to the <tt>sqrt()</tt> function.
The <tt>%contract</tt> directive must always appear before the declaration
in question. Within the contract there are two sections, both of which
are optional. The <tt>require:</tt>
section specifies conditions that must hold before the function is called.
Typically, this is used to check argument values. The <tt>ensure:</tt> section
specifies conditions that must hold after the function is called. This is
often used to check return values or the state of the program. In both
cases, the conditions that must hold must be specified as boolean expressions.
</p>
<p>
In the above example, we're simply making sure that sqrt() returns a non-negative
number (if it didn't, then it would be broken in some way).
</p>
<p>
Once a contract has been specified, it modifies the behavior of the
resulting module. For example:
</p>
<div class="shell">
<pre>
&gt;&gt;&gt; example.sqrt(2)
1.4142135623730951
&gt;&gt;&gt; example.sqrt(-2)
Traceback (most recent call last):
File "&lt;stdin&gt;", line 1, in ?
RuntimeError: Contract violation: require: (arg1&gt;=0)
&gt;&gt;&gt;
</pre>
</div>
<H2><a name="Contract_nn3">15.2 %contract and classes</a></H2>
<p>
The <tt>%contract</tt> directive can also be applied to class methods and constructors. For example:
</p>
<div class="code">
<pre>
%contract Foo::bar(int x, int y) {
require:
x &gt; 0;
ensure:
bar &gt; 0;
}
%contract Foo::Foo(int a) {
require:
a &gt; 0;
}
class Foo {
public:
Foo(int);
int bar(int, int);
};
</pre>
</div>
<p>
The way in which <tt>%contract</tt> is applied is exactly the same as the <tt>%feature</tt> directive.
Thus, any contract that you specified for a base class will also be attached to inherited methods. For example:
</p>
<div class="code">
<pre>
class Spam : public Foo {
public:
int bar(int, int); // Gets contract defined for Foo::bar(int, int)
};
</pre>
</div>
<p>
In addition to this, separate contracts can be applied to both the base class and a derived class. For example:
</p>
<div class="code">
<pre>
%contract Foo::bar(int x, int) {
require:
x &gt; 0;
}
%contract Spam::bar(int, int y) {
require:
y &gt; 0;
}
class Foo {
public:
int bar(int, int); // Gets Foo::bar contract.
};
class Spam : public Foo {
public:
int bar(int, int); // Gets Foo::bar and Spam::bar contract
};
</pre>
</div>
<p>
When more than one contract is applied, the conditions specified in a
"require:" section are combined together using a logical-AND operation.
In other words conditions specified for the base class and conditions
specified for the derived class all must hold. In the above example,
this means that both the arguments to <tt>Spam::bar</tt> must be positive.
</p>
<H2><a name="Contract_nn4">15.3 Constant aggregation and %aggregate_check</a></H2>
<p>
Consider an interface file that contains the following code:
</p>
<div class="code">
<pre>
#define UP 1
#define DOWN 2
#define RIGHT 3
#define LEFT 4
void move(SomeObject *, int direction, int distance);
</pre>
</div>
<p>
One thing you might want to do is impose a constraint on the direction parameter to
make sure it's one of a few accepted values. To do that, SWIG provides an easy to
use macro %aggregate_check() that works like this:
</p>
<div class="code">
<pre>
%aggregate_check(int, check_direction, UP, DOWN, LEFT, RIGHT);
</pre>
</div>
<p>
This merely defines a utility function of the form
</p>
<div class="code">
<pre>
int check_direction(int x);
</pre>
</div>
<p>
That checks the argument x to see if it is one of the values listed. This utility
function can be used in contracts. For example:
</p>
<div class="code">
<pre>
%aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT);
%contract move(SomeObject *, int direction, in) {
require:
check_direction(direction);
}
#define UP 1
#define DOWN 2
#define RIGHT 3
#define LEFT 4
void move(SomeObject *, int direction, int distance);
</pre>
</div>
<p>
Alternatively, it can be used in typemaps and other directives. For example:
</p>
<div class="code">
<pre>
%aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT);
%typemap(check) int direction {
if (!check_direction($1)) SWIG_exception(SWIG_ValueError, "Bad direction");
}
#define UP 1
#define DOWN 2
#define RIGHT 3
#define LEFT 4
void move(SomeObject *, int direction, int distance);
</pre>
</div>
<p>
Regrettably, there is no automatic way to perform similar checks with enums values. Maybe in a future
release.
</p>
<H2><a name="Contract_nn5">15.4 Notes</a></H2>
<p>
Contract support was implemented by Songyan (Tiger) Feng and first appeared
in SWIG-1.3.20.
</p>
</body>
</html>

File diff suppressed because it is too large Load Diff

458
Doc/Manual/D.html Normal file
View File

@ -0,0 +1,458 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and D</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#FFFFFF">
<H1><a name="D">23 SWIG and D</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#D_introduction">Introduction</a>
<li><a href="#D_command_line_invocation">Command line invocation</a>
<li><a href="#D_typemaps">Typemaps</a>
<ul>
<li><a href="#D_typemap_name_comparison">C# &lt;-&gt; D name comparison</a>
<li><a href="#D_ctype_imtype_dtype">ctype, imtype, dtype</a>
<li><a href="#D_in_out_directorin_direcetorout">in, out, directorin, directorout</a>
<li><a href="#D_din_dout_ddirectorin_ddirectorout">din, dout, ddirectorin, ddirectorout</a>
<li><a href="#D_typecheck_typemaps">typecheck typemaps</a>
<li><a href="#D_code_injection_typemaps">Code injection typemaps</a>
<li><a href="#D_special_variables">Special variable macros</a>
</ul>
<li><a href="#D_features">D and %feature</a>
<li><a href="#D_pragmas">Pragmas</a>
<li><a href="#D_exceptions">D Exceptions</a>
<li><a href="#D_directors">D Directors</a>
<li><a href="#D_other_features">Other features</a>
<ul>
<li><a href="#D_nspace">Extended namespace support (nspace)</a>
<li><a href="#D_native_pointer_support">Native pointer support</a>
<li><a href="#D_operator_overloading">Operator overloading</a>
<li><a href="#D_test_suite">Running the test-suite</a>
</ul>
<li><a href="#D_typemap_examples">D Typemap examples</a>
<li><a href="#D_planned_features">Work in progress and planned features</a>
</ul>
</div>
<!-- INDEX -->
<H2><a name="D_introduction">23.1 Introduction</a></H2>
<p>From the <a href="http://www.digitalmars.com/d/">D Programming Language</a> web site: <em>D is a systems programming language. Its focus is on combining the power and high performance of C and C++ with the programmer productivity of modern languages like Ruby and Python. [...] The D language is statically typed and compiles directly to machine code.</em> As such, it is not very surprising that D is able to directly <a href="http://www.digitalmars.com/d/1.0/interfaceToC.html">interface with C libraries</a>. Why would a SWIG module for D be needed then in the first place?</p>
<p>Well, besides the obvious downside that the C header files have to be manually converted to D modules for this to work, there is one major inconvenience with this approach: D code usually is on a higher abstraction level than C, and many of the features that make D interesting are simply not available when dealing with C libraries, requiring you e.g. to manually convert strings between pointers to <tt>\0</tt>-terminated char arrays and D char arrays, making the algorithms from the D2 standard library unusable with C arrays and data structures, and so on.</p>
<p>While these issues can be worked around relatively easy by hand-coding a thin wrapper layer around the C library in question, there is another issue where writing wrapper code per hand is not feasible: C++ libraries. D did not support interfacing to C++ in version 1 at all, and even if <tt>extern(C++)</tt> has been added to D2, the support is still very limited, and a custom wrapper layer is still required in many cases. </p>
<p>To help addressing these issues, the SWIG C# module has been forked to support D. Is has evolved quite a lot since then, but there are still many similarities, so if you do not find what you are looking for on this page, it might be worth having a look at the chapter on <a href="CSharp.html#CSharp">C#</a> (and also on <a href="Java.html#Java">Java</a>, since the C# module was in turn forked from it).</p>
<H2><a name="D_command_line_invocation">23.2 Command line invocation</a></H2>
<p>To activate the D module, pass the <tt>-d</tt> option to SWIG at the command line. The same standard command line options as with any other language module are available, plus the following D specific ones:</p>
<dl>
<dt><tt>-d2</tt></dt>
<dd>
<p>By default, SWIG generates code for D1/Tango. Use the <tt>-d2</tt> flag to target D2/Phobos instead.</p>
</dd>
<dt><a name="D_splitproxy"></a><tt>-splitproxy</tt></dt>
<dd>
<p>By default, SWIG generates two D modules: the <em>proxy</em> module, named like the source module (either specified via the <tt>%module</tt> directive or via the <tt>module</tt> command line option), which contains all the proxy classes, functions, enums, etc., and the <em>intermediary</em> module (named like the proxy module, but suffixed with <tt>_im</tt>), which contains all the <tt>extern(C)</tt> function declarations and other private parts only used internally by the proxy module.</p>
<p>If the split proxy mode is enabled by passing this option at the command line, all proxy classes and enums are emitted to their own D module instead. The main proxy module only contains free functions and constants in this case.</p>
</dd>
<dt><tt>-package &lt;pkg&gt;</tt></dt>
<dd>
<p>By default, the proxy D modules and the intermediary D module are written to the root package. Using this option, you can specify another target package instead.</p>
</dd>
<dt><tt>-wrapperlibrary &lt;wl&gt;</tt></dt>
<dd>
<p>The code SWIG generates to dynamically load the C/C++ wrapper layer looks for a library called <tt>$module_wrap</tt> by default. With this option, you can override the name of the file the wrapper code loads at runtime (the <tt>lib</tt> prefix and the suffix for shared libraries are appended automatically, depending on the OS).</p>
<p>This might especially be useful if you want to invoke SWIG several times on separate modules, but compile the resulting code into a single shared library.</p>
</dd>
</dl>
<H2><a name="D_typemaps">23.3 Typemaps</a></H2>
<H3><a name="D_typemap_name_comparison">23.3.1 C# &lt;-&gt; D name comparison</a></H3>
<p>If you already know the SWIG C# module, you might find the following name comparison table useful:</p>
<div class="diagram"><pre>
ctype &lt;-&gt; ctype
imtype &lt;-&gt; imtype
cstype &lt;-&gt; dtype
csin &lt;-&gt; din
csout &lt;-&gt; dout
csdirectorin &lt;-&gt; ddirectorin
csdirectorout &lt;-&gt; ddirectorout
csinterfaces &lt;-&gt; dinterfaces
csinterfaces_derived &lt;-&gt; dinterfaces_derived
csbase &lt;-&gt; dbase
csclassmodifiers &lt;-&gt; dclassmodifiers
cscode &lt;-&gt; dcode
csimports &lt;-&gt; dimports
csbody &lt;-&gt; dbody
csfinalize &lt;-&gt; ddestructor
csdisposing &lt;-&gt; ddispose
csdisposing_derived &lt;-&gt; ddispose_derived
</pre></div>
<H3><a name="D_ctype_imtype_dtype">23.3.2 ctype, imtype, dtype</a></H3>
<p>Mapping of types between the C/C++ library, the C/C++ library wrapper exposing the C functions, the D wrapper module importing these functions and the D proxy code.</p>
<p>The <tt>ctype</tt> typemap is used to determine the types to use in the C wrapper functions. The types from the <tt>imtype</tt> typemap are used in the extern(C) declarations of these functions in the intermediary D module. The <tt>dtype</tt> typemap contains the D types used in the D proxy module/class.</p>
<H3><a name="D_in_out_directorin_direcetorout">23.3.3 in, out, directorin, directorout</a></H3>
<p>Used for converting between the types for C/C++ and D when generating the code for the wrapper functions (on the C++ side).</p>
<p>The code from the <tt>in</tt> typemap is used to convert arguments to the C wrapper function to the type used in the wrapped code (<tt>ctype</tt>-&gt;original C++ type), the <tt>out</tt> typemap is utilized to convert values from the wrapped code to wrapper function return types (original C++ type-&gt;<tt>ctype</tt>).</p>
<p>The <tt>directorin</tt> typemap is used to convert parameters to the type used in the D director callback function, its return value is processed by <tt>directorout</tt> (see below).</p>
<H3><a name="D_din_dout_ddirectorin_ddirectorout">23.3.4 din, dout, ddirectorin, ddirectorout</a></H3>
<p>Typemaps for code generation in D proxy and type wrapper classes.</p>
<p><a name="D_din"></a>The <tt>din</tt> typemap is used for converting function parameter types from the type used in the proxy module or class to the type used in the intermediary D module (the <a href="D.html#D_dinput">$dinput</a> macro is replaced). To inject further parameter processing code before or after the call to the intermediary layer, the <tt>pre</tt>, <tt>post</tt> and <tt>terminator</tt> attributes can be used (please refer to the <a href="CSharp.html#CSharp_date_marshalling">C# date marshalling example</a> for more information on these).</p>
<p><a name="D_dout"></a>The <tt>dout</tt> typemap is used for converting function return values from the return type used in the intermediary D module to the type returned by the proxy function. The <tt>$excode</tt> special variable in <tt>dout</tt> typemaps is replaced by the <tt>excode</tt> typemap attribute code if the method can throw any exceptions from unmanaged code, otherwise by nothing (the <a href="D.html#D_imcall"><tt>$imcall</tt> and <tt>$owner</tt></a> macros are replaced).</p>
<p><a name="D_ddirectorinout"></a>The code from the <tt>ddirectorin</tt> and <tt>ddirectorout</tt> typemaps is used for conversion in director callback functions. Arguments are converted to the type used in the proxy class method they are calling by using the code from <tt>ddirectorin</tt>, the proxy class method return value is converted to the type the C++ code expects via the <tt>ddirectorout</tt> typemap (the <a href="D.html#D_dpcall"><tt>$dcall</tt> and <tt>$winput</tt></a> macros are replaced).</p>
<p>The full chain of type conversions when a director callback is invoked looks like this:</p>
<div class="diagram"><pre>
type CPPClass::method(type a)
&uarr; &darr;
&lt;directorout&gt; &lt;directorin&gt;
&uarr; &darr;
ctype methodCallback(ctype a) C++
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
imtype methodCallback(imtype a) D
&uarr; &darr;
&lt;ddirectorout&gt; &lt;ddirectorin&gt;
&uarr; &darr;
dtype DClass.method(dtype a)</pre></div>
<H3><a name="D_typecheck_typemaps">23.3.5 typecheck typemaps</a></H3>
<p>Because, unlike many scripting languages supported by SWIG, D does not need any dynamic dispatch helper to access an overloaded function, the purpose of these is merely to issue a warning for overloaded C++ functions that cannot be overloaded in D (as more than one C++ type maps to a single D type).</p>
<H3><a name="D_code_injection_typemaps">23.3.6 Code injection typemaps</a></H3>
<p>These typemaps are used for generating the skeleton of proxy classes for C++ types.</p>
<p>By overriding <tt>dbase</tt>, <tt>dinterfaces</tt> or <tt>dinterfaces_derived</tt>, the inheritance chain of the generated proxy class for a type can be modified. <tt>dclassmodifiers</tt> allows you to add any custom modifiers around the class keyword.</p>
<p>Using <tt>dcode</tt> and <tt>dimports</tt>, you can specify additional D code which will be emitted into the class body respectively the imports section of the D module the class is written to.</p>
<p><a name="D_class_code_typemaps"></a><tt>dconstructor</tt>, <tt>ddestructor</tt>, <tt>ddispose</tt> and <tt>ddispose_derived</tt> are used to generate the class constructor, destructor and <tt>dispose()</tt> method, respectively. The auxiliary code for handling the pointer to the C++ object is stored in <tt>dbody</tt> and <tt>dbody_derived</tt>. You can override them for specific types.</p>
<p>
Code can also be injected into the D proxy class using <tt>%proxycode</tt>.
</p>
<H3><a name="D_special_variables">23.3.7 Special variable macros</a></H3>
<p>The standard SWIG special variables are available for use within typemaps as described in the <a href="Typemaps.html#Typemaps">Typemaps documentation</a>, for example <tt>$1</tt>, <tt>$input</tt>, <tt>$result</tt> etc.</p>
<p>When generating D wrappers, a few additional macros are available:</p>
<dl>
<dt><tt>$dclassname</tt> (C#: <tt>$csclassname</tt>)</dt>
<dd>
<p>This special variable works similar to <a href="Typemaps.html#Typemaps_special_variables"><tt>$n_type</tt></a> in that it returns the name of a type - it expands to the D proxy class name of the type being wrapped. If the type does not have an associated proxy class, it expands to the type wrapper class name, for example, <tt>SWIGTYPE_p_p_SomeCppClass</tt> is generated when wrapping <tt>SomeCppClass **</tt>.</p>
<p>There are two other variants available, <tt>$&amp;dclassname</tt> and <tt>$*dclassname</tt>. The former adds a level of indirection, while the latter removes one. For instance, when wrapping <tt>Foo **</tt>, <tt>$*dclassname</tt> would be replaced by the proxy class name corresponding to <tt>Foo *</tt>.</p>
</dd>
<dt><tt>$dclazzname</tt> (C#: <tt>$csclazzname</tt>)</dt>
<dd>
<p>This special variable expands the fully qualified C++ class into the package name, if used by the <a href="SWIGPlus.html#SWIGPlus_nspace"><tt>nspace</tt> feature</a>, and the proxy class name, mangled for use as a function name. For example, <tt>Namespace1::Namespace2::Klass</tt> is expanded into <tt>Namespace1_Namespace2_Klass_</tt>.</p>
<p>This special variable might be useful for calling certain functions in the wrapper layer (e.g. upcast wrappers) which are mangled like this.</p>
</dd>
<dt><tt>$null</tt></dt>
<dd><p>In code inserted into the generated C/C++ wrapper functions, this variable is replaced by either <tt>0</tt> or nothing at all, depending on whether the function has a return value or not. It can be used to bail out early e.g. in case of errors (<tt>return $null;</tt>).</p></dd>
<dt><a name="D_dinput"></a><tt>$dinput</tt> (C#: <tt>$csinput</tt>)</dt>
<dd>
<p>This variable is used in <tt><a href="D.html#D_din">din</a></tt> typemaps and is replaced by the expression which is to be passed to C/C++.</p>
<p>For example, this input</p>
<div class="code"><pre>
%typemap(din) SomeClass * "SomeClass.getCPointer($dinput)"
%inline %{
class SomeClass {};
void foo(SomeClass *arg);
%}</pre></div>
<p>leads to the following D proxy code being generated:</p>
<div class="targetlang"><pre>
void foo(SomeClass arg) {
example_im.foo(SomeClass.getCPointer(arg));
}</pre></div></dd>
<dt><a name="D_imcall"></a><tt>$imcall</tt> and <tt>$owner</tt> (C#: <tt>$imcall</tt>)</dt>
<dd>
<p>These variables are used in <tt><a href="D.html#D_dout">dout</a></tt> typemaps. <tt>$imcall</tt> contains the call to the intermediary module which provides the value to be used, and <tt>$owner</tt> signals if the caller is responsible for managing the object lifetime (that is, if the called method is a constructor or has been marked via <tt>%newobject</tt>).</p>
<p>Consider the following example:</p>
<div class="code"><pre>
%typemap(dout) SomeClass * {
return new SomeClass($imcall, $owner);
}
%inline %{
class SomeClass;
SomeClass *foo();
%newobject bar();
SomeClass *bar();
%}
</pre></div>
<p>The code generated for <tt>foo()</tt> and <tt>bar()</tt> looks like this:</p>
<div class="targetlang"><pre>
SomeClass foo() {
return new SomeClass(example_im.foo(), false);
}
SomeClass bar() {
return new SomeClass(example_im.bar(), true);
}
</pre></div>
</dd>
<dt><tt>$dcall</tt> and <tt>$winput</tt> (C#: <tt>$cscall</tt>, <tt>$iminput</tt>)</dt>
<dd><a name="D_dpcall"></a><p>These variables are used in the director-specific typemaps <a href="D.html#D_ddirectorinout"><tt>ddirectorin</tt></a> and <a href="D.html#D_ddirectorinout"><tt>ddirectorout</tt></a>. They are more or less the reverse of the <tt>$imcall</tt> and <tt>$dinput</tt> macros: <tt>$dcall</tt> contains the invocation of the D proxy method of which the return value is to be passed back to C++, <tt>$winput</tt> contains the parameter value from C++.</p></dd>
<dt><tt>$excode</tt></dt>
<dd><p>This variable is used in <tt>dout</tt> and <tt>dconstructor</tt> typemaps and is filled with the contents of the <tt>excode</tt> typemap attribute if an exception could be thrown from the C++ side. See the <a href="CSharp.html#CSharp_exceptions">C# documentation</a> for details.</p></dd>
<dt><tt>$dbaseclass</tt></dt>
<dd><p>Currently for internal use only, it contains the D name of the C++ base class (if any) inside proxy classes.</p></dd>
<dt><tt>$directorconnect</tt></dt>
<dd>
<p>This macro is only valid inside the <tt><a href="D.html#D_class_code_typemaps">dconstructor</a></tt> typemap and contains the value of the <tt>dconstructor</tt> typemap attribute if the currently wrapped class has directors enabled.</p>
<p>This is how the default <tt>dconstructor</tt> typemap looks like (you usually do not want to specify a custom one):</p>
<div class="code"><pre>
%typemap(dconstructor, excode=SWIGEXCODE,
directorconnect="\n swigDirectorConnect();") SWIGTYPE {
this($imcall, true);$excode$directorconnect
}
</pre></div>
</dd>
<dt><a name="D_importtype"></a><tt>$importtype(SomeDType)</tt></dt>
<dd>
<p>This macro is used in the <tt>dimports</tt> typemap if a dependency on another D type generated by SWIG is added by a custom typemap.</p>
<p>Consider the following code snippet:</p>
<div class="code"><pre>
%typemap(dinterfaces) SomeClass "AnInterface, AnotherInterface";
</pre></div>
<p>This causes SWIG to add <tt>AnInterface</tt> and <tt>AnotherInterface</tt> to the base class list of <tt>SomeClass</tt>:</p>
<div class="targetlang"><pre>
class SomeClass : AnInterface, AnotherInterface {
...
}
</pre></div>
<p>For this to work, <tt>AnInterface</tt> and <tt>AnotherInterface</tt> have to be in scope. If SWIG is not in split proxy mode, this is already the case, but if it is, they have to be added to the import list via the <tt>dimports</tt> typemap. Additionally, the import statement depends on the package SWIG is configured to emit the modules to.</p>
<p>The <tt>$importtype</tt> macro helps you to elegantly solve this problem:</p>
<div class="code"><pre>
%typemap(dimports) RemoteMpe %{
$importtype(AnInterface)
$importtype(AnotherInterface)
%}
</pre></div>
<p>If SWIG is in split proxy mode, it expands to an <tt>import</tt> statement for the specified type, to nothing if not.</p>
</dd>
<dt><tt>$module</tt></dt>
<dd><p>Expands to the name of the main proxy D module.</p></dd>
<dt><tt>$imdmodule</tt></dt>
<dd><p>Contains the fully qualified name of the intermediary D module.</p></dd>
</dl>
<H2><a name="D_features">23.4 D and %feature</a></H2>
<p>The D module defines a number of directives which modify the <a href="Customization.html#Customization_features">SWIG features</a> set globally or for a specific declaration:</p>
<dl>
<dt><tt>%dmanifestconst</tt> and <tt>%dconstvalue(value)</tt></dt>
<dd>
<p>Out of the box, SWIG generates accessor methods for C <tt>#defines</tt> and C++ constants. The <tt>%dmanifestconst</tt> directive enables wrapping these constants as D manifest constants (<tt>const</tt> in D1, <tt>enum</tt> in D2).</p>
<p>For this to work, the C/C++ code for the constant value must directly compile as D code, though. If this is not the case, you can manually override the expression written to the D proxy module using the <tt>%dconstvalue</tt> directive, passing the new value as parameter.</p>
<p>For <tt>enum</tt>s, again <tt>%dconstvalue</tt> can be used to override the value of an enum item if the initializer should not compile in D.</p>
</dd>
<dt><tt>%dmethodmodifiers</tt></dt>
<dd>
<p>This directive can be used to override the modifiers for a proxy function. For instance, you could make a <tt>public</tt> C++ member function <tt>private</tt> in D like this:</p>
<div class="code"><pre>
%dmethodmodifiers A::foo "private";
%inline %{
struct A {
void foo();
};
%}
</pre></div>
</dd>
</dl>
<H2><a name="D_pragmas">23.5 Pragmas</a></H2>
<p>There are a few SWIG pragmas specific to the D module, which you can use to influence the D code SWIG generates:</p>
<dl>
<dt><tt>%pragma(d) imdmodulecode</tt></dt>
<dd><p>The passed text (D code) is copied verbatim to the intermediary D module. For example, it can be (and is, internally) used to emit additional private helper code for the use by proxy typemaps.</p></dd>
<dt><tt>%pragma(d) imdmoduleimports</tt></dt>
<dd><p>Additional code to be emitted to the imports section of the intermediary D module (the <a href="D.html#D_importtype">$importtype</a> macro can be used here). You probably want to use this in conjunction with the <tt>imdmodulecode</tt> pragma.</p></dd>
<dt><tt>%pragma(d) proxydmodulecode</tt></dt>
<dd><p>Just like <tt>proxydmodulecode</tt>, the argument is copied to the proxy D module (if SWIG is in <a href="D.html#D_splitproxy">split proxy mode</a> and/or the <tt>nspace</tt> feature is used, it is emitted to the main proxy D module only).</p></dd>
<dt><tt>%pragma(d) globalproxyimports</tt></dt>
<dd>
<p>The D module currently does not support specifying dependencies on external modules (e.g. from the standard library) for the D typemaps. To add the import statements to the proxy modules (resp. to <em>all</em> proxy modules if in split proxy mode), you can use the <tt>globalproxyimports</tt> directive.</p>
<p>For example:</p>
<div class="code"><pre>
%typemap(din) char[] "($dinput ? tango.stdc.stringz.toStringz($dinput) : null)"
%pragma(d) globalproxyimports = "static import tango.stdc.stringz;";
</pre></div>
</dd>
<dt><tt>%pragma(d) wrapperloadercode</tt></dt>
<dd>
<p>The D code for loading the wrapper library (it is copied to the intermediary D module). The <tt>$wrapperloaderbindcode</tt> variable is replaced by the list of commands for binding the functions from the wrapper library to the symbols in the intermediary D module.</p>
<p>Each time this pragma is specified, the previous value is overwritten.</p>
</dd>
<dt><tt>%pragma(d) wrapperloaderbindcommand</tt></dt>
<dd>
<p>The D command to use for binding the wrapper functions from the C/C++ library to the symbols in the intermediary D module. The <tt>$function</tt> variable contains the name of the D function in the wrap module, the <tt>$symbol</tt> variable is replaced by the name of the symbol in the library.</p>
<p>Each time this pragma is specified, the previous value is overwritten.</p>
</dd>
</dl>
<H2><a name="D_exceptions">23.6 D Exceptions</a></H2>
<p>Out of the box, C++ exceptions are fundamentally incompatible to their equivalent in the D world and cannot simply be propagated to a calling D method. There is, however, an easy way to solve this problem: Just catch the exception in the C/C++ wrapper layer, pass the contents to D, and make the wrapper code rethrow the exception in the D world.</p>
<p>The implementation details of this are a bit crude, but the SWIG D module automatically takes care of this, as long as it is able to detect that an exception could potentially be thrown (e.g. because the C++ method has a <tt>throw(...)</tt> exception specification).</p>
<p>As this feature is implemented in exactly the same way it is for C#, please see the <a href="CSharp.html#CSharp_exceptions">C# documentation</a> for a more detailed explanation.</p>
<H2><a name="D_directors">23.7 D Directors</a></H2>
<p>When the directors feature is activated, SWIG generates extra code on both the C++ and the D side to enable cross-language polymorphism. Essentially, this means that if you subclass a proxy class in D, C++ code can access any overridden virtual methods just as if you created a derived class in C++.</p>
<p>There is no D specific documentation yet, but the way the feature is implemented is very similar to how it is done in <a href="Java.html#Java_directors">Java</a> and <a href="CSharp.html#CSharp_directors">C#</a>.
</p>
<H2><a name="D_other_features">23.8 Other features</a></H2>
<H3><a name="D_nspace">23.8.1 Extended namespace support (nspace)</a></H3>
<p>By default, SWIG flattens all C++ namespaces into a single target language namespace, but as for Java and C#, the <a href="SWIGPlus.html#SWIGPlus_nspace"><tt>nspace</tt></a> feature is supported for D. If it is active, C++ namespaces are mapped to D packages/modules. Note, however, that like for the other languages, <em>free</em> variables and functions are not supported yet; currently, they are all allows written to the main proxy D module.</p>
<H3><a name="D_native_pointer_support">23.8.2 Native pointer support</a></H3>
<p>Contrary to many of the scripting languages supported by SWIG, D fully supports C-style pointers. The D module thus includes a custom mechanism to wrap C pointers directly as D pointers where applicable, that is, if the type that is pointed to is represented the same in C and D (on the bit-level), dubbed a <em>primitive type</em> below.</p>
<p>Central to this custom pointer handling scheme are two typemap attributes: the <tt>cprimitive</tt> attribute on the <tt>dtype</tt> typemap and the <tt>nativepointer</tt> attribute on all the typemaps which influence the D side of the code (<tt>dtype</tt>, <tt>din</tt>, <tt>dout</tt>, ...). When a D typemap is looked up, the following happens behind the scenes:</p>
<p>First, the matching typemap is determined by the usual typemap lookup rules. Then, it is checked if the result has the <tt>nativepointer</tt> attribute set. If it is present, it means that its value should replace the typemap value <em>if and only if</em> the actual type the typemap is looked up for is a primitive type, a pointer to a primitive type (through an arbitrary level of indirections), or a function pointer with only primitive types in its signature.</p>
<p>To determine if a type should be considered primitive, the <tt>cprimitive</tt> attribute on its <tt>dtype</tt> attribute is used. For example, the <tt>dtype</tt> typemap for <tt>float</tt> has <tt>cprimitive="1"</tt>, so the code from the <tt>nativepointer</tt> attribute is taken into account e.g. for <tt>float **</tt> or the function pointer <tt>float (*)(float *)</tt>.</p>
<H3><a name="D_operator_overloading">23.8.3 Operator overloading</a></H3>
<p>The D module comes with basic operator overloading support for both D1 and D2. There are, however, a few limitations arising from conceptual differences between C++ and D:</p>
<p>The first key difference is that C++ supports free functions as operators (along with argument-dependent lookup), while D requires operators to be member functions of the class they are operating on. SWIG can only automatically generate wrapping code for member function operators; if you want to use operators defined as free functions in D, you need to handle them manually.</p>
<p>Another set of differences between C++ and D concerns individual operators. For example, there are quite a few operators which are overloadable in C++, but not in D, for example <tt>&amp;&amp;</tt> and <tt>||</tt>, but also <tt>!</tt>, and prefix increment/decrement operators in <a href="http://www.digitalmars.com/d/1.0/operatoroverloading.html">D1</a> resp. their postfix pendants in <a href="http://www.digitalmars.com/d/2.0/operatoroverloading.html">D2</a>.</p>
<p>There are also some cases where the operators can be translated to D, but the differences in the implementation details are big enough that a rather involved scheme would be required for automatic wrapping them, which has not been implemented yet. This affects, for example, the array subscript operator, <tt>[]</tt>, in combination with assignments - while <tt>operator []</tt> in C++ simply returns a reference which is then written to, D resorts to a separate <tt>opIndexAssign</tt> method -, or implicit casting (which was introduced in D2 via <tt>alias this</tt>). Despite the lack of automatic support, manually handling these cases should be perfectly possible.</p>
<H3><a name="D_test_suite">23.8.4 Running the test-suite</a></H3>
<p>As with any other language, the SWIG test-suite can be built for D using the <tt>*-d-test-suite</tt> targets of the top-level Makefile. By default, D1 is targeted, to build it with D2, use the optional <tt>D_VERSION</tt> variable, e.g. <tt>make check-d-test-suite D_VERSION=2</tt>.</p>
<p>Note: If you want to use GDC on Linux or another platform which requires you to link <tt>libdl</tt> for dynamically loading the shared library, you might have to add <tt>-ldl</tt> manually to the <tt>d_compile</tt> target in <tt>Examples/Makefile</tt>, because GDC does not currently honor the <tt>pragma(lib, ...)</tt> statement.</p>
<H2><a name="D_typemap_examples">23.9 D Typemap examples</a></H2>
<p>There are no D-specific typemap examples yet. However, with the above <a href="D.html#D_typemap_name_comparison">name comparison table</a>, you should be able to get an idea what can be done by looking at the <a href="CSharp.html#CSharp_typemap_examples">corresponding C# section</a>.</p>
<H2><a name="D_planned_features">23.10 Work in progress and planned features</a></H2>
<p>There are a couple of features which are not implemented yet, but would be very useful and might be added in the near future:</p>
<ul>
<li><em>Static linking:</em> Currently, the C wrapper code is compiled into a dynamic library, out of which the symbol addresses are looked up at runtime by the D part. If statically linking the different languages into one binary was supported, a tool-chain capable of performing IPO at link time could inline the wrapping code, effectively reducing the overhead for simple calls to zero.</li>
<li><em>C array handling:</em> Many data structures in some C/C++ libraries contain array containing of a pointer to the first element and the element count. Currently, one must manually writing wrapper code to be able to access these from D. It should be possible to add a set of SWIG macros to semi-automatically generate conversion code.</li>
</ul>
<p>Some generated code might also be a bit rough around the edges, particularly in the following areas:</p>
<ul>
<li><em>Memory management:</em> Although the currently generated wrapper code works fine with regard to the GC for the test-suite, there might be issues coming up in real-world multi-threaded usage.</li>
<li><em>D2 support</em>: Originally, the module has been developed for the use with D1, D2/Phobos support has been added in later. The basic features should work equally well for both, but there <em>could</em> be issues concerning const-correctness etc.</li>
</ul>
</body>
</html>

1750
Doc/Manual/Doxygen.html Normal file

File diff suppressed because it is too large Load Diff

4195
Doc/Manual/Extending.html Normal file

File diff suppressed because it is too large Load Diff

1558
Doc/Manual/Go.html Normal file

File diff suppressed because it is too large Load Diff

859
Doc/Manual/Guile.html Normal file
View File

@ -0,0 +1,859 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Guile</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Guile">25 SWIG and Guile</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Guile_nn1">Supported Guile Versions</a>
<li><a href="#Guile_nn2">Meaning of "Module"</a>
<li><a href="#Guile_nn3">Old GH Guile API</a>
<li><a href="#Guile_nn4">Linkage</a>
<ul>
<li><a href="#Guile_nn5">Simple Linkage</a>
<li><a href="#Guile_nn6">Passive Linkage</a>
<li><a href="#Guile_nn7">Native Guile Module Linkage</a>
<li><a href="#Guile_nn8">Old Auto-Loading Guile Module Linkage</a>
<li><a href="#Guile_nn9">Hobbit4D Linkage</a>
</ul>
<li><a href="#Guile_nn10">Underscore Folding</a>
<li><a href="#Guile_nn11">Typemaps</a>
<li><a href="#Guile_nn12">Representation of pointers as smobs</a>
<ul>
<li><a href="#Guile_nn14">Smobs</a>
<li><a href="#Guile_nn15">Garbage Collection</a>
</ul>
<li><a href="#Guile_nn16">Native Guile pointers</a>
<li><a href="#Guile_nn17">Exception Handling</a>
<li><a href="#Guile_nn18">Procedure documentation</a>
<li><a href="#Guile_nn19">Procedures with setters</a>
<li><a href="#Guile_nn20">GOOPS Proxy Classes</a>
<ul>
<li><a href="#Guile_nn21">Naming Issues</a>
<li><a href="#Guile_nn22">Linking</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
This section details guile-specific support in SWIG.
<H2><a name="Guile_nn1">25.1 Supported Guile Versions</a></H2>
<p>
SWIG works with Guile versions 1.8.x and 2.0.x. Support for version
1.6.x has been dropped. The last version of SWIG that still works with
Guile version 1.6.x is SWIG 2.0.9.
<p>
Note that starting with guile 2.0, the guile sources can be compiled for
improved performance. This is currently not tested with swig
so your mileage may vary. To be safe set environment variable
GUILE_AUTO_COMPILE to 0 when using swig generated guile code.
<H2><a name="Guile_nn2">25.2 Meaning of "Module"</a></H2>
<p>
There are three different concepts of "module" involved, defined
separately for SWIG, Guile, and Libtool. To avoid horrible confusion,
we explicitly prefix the context, e.g., "guile-module".
<H2><a name="Guile_nn3">25.3 Old GH Guile API</a></H2>
<p>Guile 1.8 and older could be interfaced using two different api's, the SCM
or the GH API. The GH interface to guile is deprecated. Read more about why in the
<a href="http://www.gnu.org/software/guile/docs/docs-1.6/guile-ref/GH.html#GH">Guile manual</a>.
<p>Support for the guile GH wrapper code generation has been dropped from SWIG. The last
version of SWIG that can still generate guile GH wrapper code is 2.0.9. Please
use that version if you really need the GH wrapper code.
<H2><a name="Guile_nn4">25.4 Linkage</a></H2>
<p>
Guile support is complicated by a lack of user community cohesiveness,
which manifests in multiple shared-library usage conventions. A set of
policies implementing a usage convention is called a <b>linkage</b>.
<H3><a name="Guile_nn5">25.4.1 Simple Linkage</a></H3>
<p>
The default linkage is the simplest; nothing special is done. In this
case the function <code>SWIG_init()</code> is exported. Simple linkage
can be used in several ways:
</p>
<ul>
<li><b>Embedded Guile, no modules.</b> You want to embed a Guile
interpreter into your program; all bindings made by SWIG shall show up
in the root module. Then call <code>SWIG_init()</code> in the
<code>inner_main()</code> function. See the "simple" and "matrix" examples under
<code>Examples/guile</code>.
<li><p><b>Dynamic module mix-in.</b> You want to create a Guile module
using <code>define-module</code>, containing both Scheme code and
bindings made by SWIG; you want to load the SWIG modules as shared
libraries into Guile.</p>
<div class="targetlang">
<pre>
(define-module (my module))
(define my-so (dynamic-link "./libexample.so"))
(dynamic-call "SWIG_init" my-so) ; make SWIG bindings
;; Scheme definitions can go here
</pre>
</div>
<p>
Newer Guile versions provide a shorthand for <code>dynamic-link</code>
and <code>dynamic-call</code>:
</p>
<div class="targetlang">
<pre>
(load-extension "./libexample.so" "SWIG_init")
</pre>
</div>
<p>
A more portable approach would be to drop the shared library extension:
</p>
<div class="targetlang">
<pre>
(load-extension "./libexample" "SWIG_init")
</pre>
</div>
<p>
You need to explicitly export those bindings made by SWIG that you
want to import into other modules:
</p>
<div class="targetlang">
<pre>
(export foo bar)
</pre>
</div>
<p>
In this example, the procedures <code>foo</code> and <code>bar</code>
would be exported. Alternatively, you can export all bindings with the
following module-system hack:
</p>
<div class="targetlang">
<pre>
(module-map (lambda (sym var)
(module-export! (current-module) (list sym)))
(current-module))
</pre>
</div>
<p>SWIG can also generate this Scheme stub (from
<code>define-module</code> up to <code>export</code>)
semi-automagically if you pass it the command-line argument
<code>-scmstub</code>. The code will be exported in a file called
<code><i>module</i>.scm</code> in the directory specified by <code>-outdir</code>
or the current directory if <code>-outdir</code> is not specified.
Since SWIG doesn't know how
to load your extension module (with <code>dynamic-link</code> or
<code>load-extension</code>), you need to supply this
information by including a directive like this in the interface file:
</p>
<div class="code">
<pre>
%scheme %{ (load-extension "./libexample.so" "SWIG_init") %}
</pre>
</div>
<p>
(The <code>%scheme</code> directive allows to insert arbitrary Scheme
code into the generated file <code><var>module.scm</var></code>; it is
placed between the <code>define-module</code> form and the
<code>export</code> form.)
</p>
</ul>
<p>If you want to include several SWIG modules, you would need to rename
<code>SWIG_init</code> via a preprocessor define to avoid symbol
clashes. For this case, however, passive linkage is available.
<H3><a name="Guile_nn6">25.4.2 Passive Linkage</a></H3>
<p>Passive linkage is just like simple linkage, but it generates an
initialization function whose name is derived from the module and
package name (see below).
<p>You should use passive linkage rather than simple linkage when you
are using multiple modules.
<H3><a name="Guile_nn7">25.4.3 Native Guile Module Linkage</a></H3>
<p>SWIG can also generate wrapper code that does all the Guile module
declarations on its own if you pass it the <code>-Linkage
module</code> command-line option.
<p>The module name is set with the <code>-package</code> and
<code>-module</code> command-line options. Suppose you want to define
a module with name <code>(my lib foo)</code>; then you would have to
pass the options <code>-package <var>my</var>/<var>lib</var> -module
<var>foo</var></code>. Note that the last part of the name can also be set
via the SWIG directive <code>%module</code>.
<p>You can use this linkage in several ways:
<ul>
<li><b>Embedded Guile with SWIG modules.</b> You want to embed a Guile
interpreter into your program; the SWIG bindings shall be put into
different modules. Simply call the function
<code>scm_init_<var>my</var>_<var>modules</var>_<var>foo</var>_module</code>
in the <code>inner_main()</code> function.
<li><b>Dynamic Guile modules.</b> You want to load the SWIG modules as
shared libraries into Guile; all bindings are automatically put in
newly created Guile modules.
<div class="targetlang">
<pre>
(define my-so (dynamic-link "./libfoo"))
;; create new module and put bindings there:
(dynamic-call "scm_init_my_modules_foo_module" my-so)
</pre>
</div>
Newer Guile versions have a shorthand procedure for this:
<div class="targetlang">
<pre>
(load-extension "./libfoo.so" "scm_init_my_modules_foo_module")
</pre>
</div>
</ul>
<H3><a name="Guile_nn8">25.4.4 Old Auto-Loading Guile Module Linkage</a></H3>
<p>Guile used to support an autoloading facility for object-code
modules. This support has been marked deprecated in version 1.4.1 and
is going to disappear sooner or later. SWIG still supports building
auto-loading modules if you pass it the <code>-Linkage ltdlmod</code>
command-line option.
<p>Auto-loading worked like this: Suppose a module with name <code>(my
lib foo)</code> is required and not loaded yet. Guile will then search
all directories in its search path
for a Scheme file <code>my/modules/foo.scm</code> or a shared library
<code><var>my</var>/<var>modules</var>/lib<var>foo</var>.so</code> (or
<code><var>my</var>/<var>modules</var>/lib<var>foo</var>.la</code>;
see the GNU libtool documentation). If a
shared library is found that contains the symbol
<code>scm_init_<var>my</var>_<var>modules</var>_<var>foo</var>_module</code>,
the library is loaded, and the function at that symbol is called with
no arguments in order to initialize the module.
<p>When invoked with the <code>-Linkage ltdlmod</code> command-line
option, SWIG generates an exported module initialization function with
an appropriate name.
<H3><a name="Guile_nn9">25.4.5 Hobbit4D Linkage</a></H3>
<p>
The only other linkage supported at this time creates shared object
libraries suitable for use by hobbit's <code>(hobbit4d link)</code>
guile module. This is called the "hobbit" linkage, and requires also
using the "-package" command line option to set the part of the module
name before the last symbol. For example, both command lines:
</p>
<div class="shell">
<pre>
swig -guile -package my/lib foo.i
swig -guile -package my/lib -module foo foo.i
</pre>
</div>
<p>
would create module <code>(my lib foo)</code> (assuming in the first
case foo.i declares the module to be "foo"). The installed files are
my/lib/libfoo.so.X.Y.Z and friends. This scheme is still very
experimental; the (hobbit4d link) conventions are not well understood.
</p>
<H2><a name="Guile_nn10">25.5 Underscore Folding</a></H2>
<p>
Underscores are converted to dashes in identifiers. Guile support may
grow an option to inhibit this folding in the future, but no one has
complained so far.
<p>You can use the SWIG directives <code>%name</code> and
<code>%rename</code> to specify the Guile name of the wrapped
functions and variables (see CHANGES).
<H2><a name="Guile_nn11">25.6 Typemaps</a></H2>
<p>
The Guile module handles all types via typemaps. This
information is read from <code>Lib/guile/typemaps.i</code>.
Some non-standard typemap substitutions are supported:
<ul>
<li><code>$descriptor</code> expands to a type descriptor for use with
the <code>SWIG_NewPointerObj()</code> and
<code>SWIG_ConvertPtr</code> functions.
<li>For pointer types, <code>$*descriptor</code> expands to a
descriptor for the direct base type (i.e., one pointer is stripped),
whereas <code>$basedescriptor</code> expands to a
descriptor for the base type (i.e., all pointers are stripped).
</ul>
<p>A function returning <code>void</code> (more precisely, a function
whose <code>out</code> typemap returns <code>SCM_UNSPECIFIED</code>) is
treated as returning no values. In <code>argout</code> typemaps, one
can use the macro <code>GUILE_APPEND_RESULT</code> in order to append
a value to the list of function return values.
<p>Multiple values can be passed up to Scheme in one of three ways:
<ul>
<li><p><em>Multiple values as lists.</em>
By default, if more than one value is to
be returned, a list of the values is created and returned; to switch
back to this behavior, use</p>
<div class="code">
<pre>
%values_as_list;</pre>
</div>
<li><p><em>Multiple values as vectors.</em>
By issuing
</p>
<div class="code">
<pre>
%values_as_vector;</pre>
</div>
<p>
vectors instead of lists will be used.
<li><p><em>Multiple values for multiple-value continuations.</em>
<strong>This is the most elegant way.</strong> By issuing
</p>
<div class="code">
<pre>
%multiple_values;</pre>
</div>
<p>
multiple values are passed to the multiple-value
continuation, as created by <code>call-with-values</code> or the
convenience macro <code>receive</code>. The latter is available if you
issue <code>(use-modules (srfi srfi-8))</code>. Assuming that your
<code>divide</code> function
wants to return two values, a quotient and a remainder, you can write:
</p>
<div class="targetlang">
<pre>
(receive (quotient remainder)
(divide 35 17)
<var>body</var>...)
</pre>
</div>
<p>
In <code><var>body</var></code>, the first result of
<code>divide</code> will be bound to the variable
<code>quotient</code>, and the second result to <code>remainder</code>.
</p>
</ul>
<p>
See also the "multivalue" example.
</p>
<p>Constants are exported as a function that returns the value. The
%feature("constasvar") can be applied to any constant, immutable variable, or enum.
Instead of exporting the constant as a function that must be called, the
constant will appear as a scheme variable. See
<a href="Customization.html#Customization_features">Features and the %feature directive</a>
for info on how to apply the %feature.</p>
<H2><a name="Guile_nn12">25.7 Representation of pointers as smobs</a></H2>
<p>
For pointer types, SWIG uses Guile smobs. SWIG smobs print
like this: <code>#&lt;swig struct xyzzy * 0x1234affe&gt;</code> Two of
them are <code>equal?</code> if and only if they have the same type
and value.
<p>
To construct a Scheme object from a C pointer, the wrapper code calls
the function <code>SWIG_NewPointerObj()</code>, passing a pointer to a
struct representing the pointer type. The type index to store in the
upper half of the CAR is read from this struct.
To get the pointer represented by a smob, the wrapper code calls the
function <code>SWIG_ConvertPtr()</code>, passing a pointer to a struct
representing the expected pointer type. See also
<a href="Typemaps.html#Typemaps_runtime_type_checker">The run-time type checker</a>.
If the Scheme object passed was not a SWIG smob representing a compatible
pointer, a <code>wrong-type-arg</code> exception is raised.
<H3><a name="Guile_nn14">25.7.1 Smobs</a></H3>
<p>
In earlier versions of SWIG, C pointers were represented as Scheme
strings containing a hexadecimal rendering of the pointer value and a
mangled type name. As Guile allows registering user types, so-called
"smobs" (small objects), a much cleaner representation has been
implemented now. The details will be discussed in the following.
</p>
<p>The whole type system, when it is first initialized, creates two smobs named "swig" and "collected_swig".
The swig smob is used for non-garbage collected smobs, while the collected_swig smob is used as described
below. Each smob has the same format, which is a double cell created by SCM_NEWSMOB2()
The first word of data is the pointer to the object and the second word of data is the swig_type_info *
structure describing this type. If a generated GOOPS module has been loaded, smobs will be wrapped by
the corresponding GOOPS class.</p>
<H3><a name="Guile_nn15">25.7.2 Garbage Collection</a></H3>
<p>Garbage collection is a feature of Guile since version 1.6. As SWIG now requires Guile &gt; 1.8,
it is automatically included.
Garbage collection works like this. Every swig_type_info structure stores in its clientdata field a pointer
to the destructor for this type. The destructor is the generated wrapper around the delete function.
So swig still exports a wrapper for the destructor, it just does not call scm_c_define_gsubr() for
the wrapped delete function. So the only way to delete an object is from the garbage collector, since the
delete function is not available to scripts. How swig determines if a type should be garbage collected
is exactly like described in <a href="Customization.html#Customization_ownership">
Object ownership and %newobject</a> in the SWIG manual. All typemaps use an $owner var, and
the guile module replaces $owner with 0 or 1 depending on feature:new.</p>
<H2><a name="Guile_nn16">25.8 Native Guile pointers</a></H2>
<p>
In addition to SWIG smob pointers, <a href="https://www.gnu.org/software/guile/manual/html_node/Foreign-Pointers.html">Guile's native pointer type</a> are accepted as arguments to wrapped SWIG functions. This can be useful for passing <a href="https://www.gnu.org/software/guile/manual/html_node/Void-Pointers-and-Byte-Access.html#">pointers to bytevector data</a> to wrapped functions.
</p>
<H2><a name="Guile_nn17">25.9 Exception Handling</a></H2>
<p>
SWIG code calls <code>scm_error</code> on exception, using the following
mapping:
<div class="code">
<pre>
MAP(SWIG_MemoryError, "swig-memory-error");
MAP(SWIG_IOError, "swig-io-error");
MAP(SWIG_RuntimeError, "swig-runtime-error");
MAP(SWIG_IndexError, "swig-index-error");
MAP(SWIG_TypeError, "swig-type-error");
MAP(SWIG_DivisionByZero, "swig-division-by-zero");
MAP(SWIG_OverflowError, "swig-overflow-error");
MAP(SWIG_SyntaxError, "swig-syntax-error");
MAP(SWIG_ValueError, "swig-value-error");
MAP(SWIG_SystemError, "swig-system-error");
</pre>
</div>
<p>
The default when not specified here is to use "swig-error".
See Lib/exception.i for details.
<H2><a name="Guile_nn18">25.10 Procedure documentation</a></H2>
<p>If invoked with the command-line option <code>-procdoc
<var>file</var></code>, SWIG creates documentation strings for the
generated wrapper functions, describing the procedure signature and
return value, and writes them to <var>file</var>.
<p>SWIG can generate documentation strings in three formats, which are
selected via the command-line option <code>-procdocformat
<var>format</var></code>:
<ul>
<li><code>guile-1.4</code> (default): Generates a format suitable for Guile 1.4.
<li><code>plain</code>: Generates a format suitable for Guile 1.4.1 and
later.
<li><code>texinfo</code>: Generates texinfo source, which must be run
through texinfo in order to get a format suitable for Guile 1.4.1 and
later.
</ul>
<p>You need to register the generated documentation file with Guile
like this:
<div class="targetlang">
<pre>
(use-modules (ice-9 documentation))
(set! documentation-files
(cons "<var>file</var>" documentation-files))
</pre>
</div>
<p>Documentation strings can be configured using the Guile-specific
typemap argument <code>doc</code>. See <code>Lib/guile/typemaps.i</code> for
details.
<H2><a name="Guile_nn19">25.11 Procedures with setters</a></H2>
<p>For global variables, SWIG creates a single wrapper procedure
<code>(<var>variable</var> :optional value)</code>, which is used for
both getting and setting the value. For struct members, SWIG creates
two wrapper procedures <code>(<var>struct</var>-<var>member</var>-get
pointer)</code> and <code>(<var>struct-member</var>-set pointer value)</code>.
<p>If invoked with the command-line option <code>-emit-setters</code>
(<em>recommended</em>),
SWIG will additionally create procedures with setters. For global
variables, the procedure-with-setter <code><var>variable</var></code>
is created, so you can use <code>(<var>variable</var>)</code> to get
the value and <code>(set! (<var>variable</var>)
<var>value</var>)</code> to set it. For struct members, the
procedure-with-setter <code><var>struct</var>-<var>member</var></code>
is created, so you can use <code>(<var>struct</var>-<var>member</var>
<var>pointer</var>)</code> to get the value and <code>(set!
(<var>struct</var>-<var>member</var> <var>pointer</var>)
<var>value</var>)</code> to set it.
<p>If invoked with the command-line option <code>-only-setters</code>,
SWIG will <em>only</em> create procedures with setters, i.e., for
struct members, the procedures <code>(<var>struct</var>-<var>member</var>-get
pointer)</code> and <code>(<var>struct-member</var>-set pointer
value)</code> are <em>not</em> generated.
<H2><a name="Guile_nn20">25.12 GOOPS Proxy Classes</a></H2>
<p>SWIG can also generate classes and generic functions for use with
Guile's Object-Oriented Programming System (GOOPS). GOOPS is a
sophisticated object system in the spirit of the Common Lisp Object
System (CLOS).
<p>To enable GOOPS support, pass the <code>-proxy</code> argument to
swig. This will export the GOOPS wrapper definitions into the
<code><i>module</i>.scm</code> file in the directory specified by -outdir or the
current directory. GOOPS support requires either passive or module linkage.</p>
<p>The generated file will contain definitions of GOOPS classes mimicking the C++ class hierarchy.
<p>Enabling GOOPS support implies <code>-emit-setters</code>.
<p>If <code>-emit-slot-accessors</code> is also passed as an argument,
then the generated file will contain accessor methods for all the
slots in the classes and for global variables. The input class</p>
<div class="code"><pre>
class Foo {
public:
Foo(int i) : a(i) {}
int a;
int getMultBy(int i) { return a * i; }
Foo getFooMultBy(int i) { return Foo(a * i); }
};
Foo getFooPlus(int i) { return Foo(a + i); }
</pre></div>
<p>
will produce (if <code>-emit-slot-accessors</code> is not passed as a parameter)
</p>
<div class="targetlang"><pre>
(define-class &lt;Foo&gt; (&lt;swig&gt;)
(a #:allocation #:swig-virtual
#:slot-ref primitive:Foo-a-get
#:slot-set! primitive:Foo-a-set)
#:metaclass &lt;swig-metaclass&gt;
#:new-function primitive:new-Foo
)
(define-method (getMultBy (swig_smob &lt;Foo&gt;) i)
(primitive:Foo-getMultBy (slot-ref swig_smob 'smob) i))
(define-method (getFooMultBy (swig_smob &lt;Foo&gt;) i)
(make &lt;Foo&gt; #:init-smob (primitive:Foo-getFooMultBy (slot-ref swig_smob 'smob) i)))
(define-method (getFooPlus i)
(make &lt;Foo&gt; #:init-smob (primitive:getFooPlus i)))
(export &lt;Foo&gt; getMultBy getFooMultBy getFooPlus )
</pre></div>
<p>
and will produce (if <code>-emit-slot-accessors</code> is passed as a parameter)
</p>
<div class="targetlang"><pre>
(define-class &lt;Foo&gt; (&lt;swig&gt;)
(a #:allocation #:swig-virtual
#:slot-ref primitive:Foo-a-get
#:slot-set! primitive:Foo-a-set
<b>#:accessor a</b>)
#:metaclass &lt;swig-metaclass&gt;
#:new-function primitive:new-Foo
)
(define-method (getMultBy (swig_smob &lt;Foo&gt;) i)
(primitive:Foo-getMultBy (slot-ref swig_smob 'smob) i))
(define-method (getFooMultBy (swig_smob &lt;Foo&gt;) i)
(make &lt;Foo&gt; #:init-smob (primitive:Foo-getFooMultBy (slot-ref swig_smob 'smob) i)))
(define-method (getFooPlus i)
(make &lt;Foo&gt; #:init-smob (primitive:getFooPlus i)))
(export &lt;Foo&gt; <b>a</b> getMultBy getFooMultBy getFooPlus )
</pre></div>
<p>
which can then be used by this code
</p>
<div class="targetlang"><pre>
;; not using getters and setters
(define foo (make &lt;Foo&gt; #:args '(45)))
(slot-ref foo 'a)
(slot-set! foo 'a 3)
(getMultBy foo 4)
(define foo2 (getFooMultBy foo 7))
(slot-ref foo 'a)
(slot-ref (getFooPlus foo 4) 'a)
;; using getters and setters
(define foo (make &lt;Foo&gt; #:args '(45)))
(a foo)
(set! (a foo) 5)
(getMultBy foo 4)
(a (getFooMultBy foo 7))
</pre></div>
<p>Notice that constructor arguments are passed as a list after the <code>#:args</code> keyword. Hopefully in
the future the following will be valid <code>(make &lt;Foo&gt; #:a 5 #:b 4)</code></p>
<p>Also note that the order the declarations occur in the .i file make a difference. For example,
</p>
<div class="code"><pre>
%module test
%{ #include "foo.h" %}
%inline %{
int someFunc(Foo &amp;a) {
...
}
%}
%include "foo.h"
</pre></div>
<p>
This is a valid SWIG file it will work as you think it will for primitive support, but the generated
GOOPS file will be broken. Since the <code>someFunc</code> definition is parsed by SWIG before all the
declarations in foo.h, the generated GOOPS file will contain the definition of <code>someFunc()</code>
before the definition of &lt;Foo&gt;. The generated GOOPS file would look like
</p>
<div class="targetlang"><pre>
;;...
(define-method (someFunc (swig_smob &lt;Foo&gt;))
(primitive:someFunc (slot-ref swig_smob 'smob)))
;;...
(define-class &lt;Foo&gt; (&lt;swig&gt;)
;;...
)
;;...
</pre></div>
<p>
Notice that &lt;Foo&gt; is used before it is defined. The fix is to just put the
<code>%import "foo.h"</code> before the <code>%inline</code> block.
</p>
<H3><a name="Guile_nn21">25.12.1 Naming Issues</a></H3>
<p>As you can see in the example above, there are potential naming conflicts. The default exported
accessor for the <code>Foo::a</code> variable is named <code>a</code>. The name of the wrapper global
function is <code>getFooPlus</code>.
If the <code>-useclassprefix</code> option is passed to swig, the name of all accessors and member
functions will be prepended with the class name. So the accessor will be called <code>Foo-a</code> and
the member functions will be called <code>Foo-getMultBy</code>. Also, if the
<code>-goopsprefix goops:</code> argument is passed to swig, every identifier will be prefixed by
<code>goops:</code></p>
<p>Two guile-modules are created by SWIG. The first module contains the primitive definitions
of all the wrapped functions and variables, and is located either in the _wrap.cxx file (with <code>-Linkage
module</code>) or in the scmstub file (if <code>-Linkage passive -scmstub</code>). The name of this
guile-module is the swig-module name (given on the command line with the -module argument or with the
%module directive) concatenated with the string "-primitive". For
example, if <code>%module Test</code> is set in the swig interface file, the name of the guile-module in
the scmstub or <code>-Linkage module</code> will be <code>Test-primitive</code>. Also, the scmstub
file will be named <code>Test-primitive.scm</code>.
The string "primitive" can be changed by the <code>-primsuffix</code> swig
argument. So the same interface, with the <code>-primsuffix base</code> will produce a module called
<code>Test-base</code>.
The second generated guile-module contains all the GOOPS class definitions and is located in
a file named <i>module</i>.scm in the directory specified with -outdir or the current directory.
The name of this guile-module is the name of the
swig-module (given on the command line or with the <code>%module</code> directive).
In the previous example, the GOOPS definitions will be in a file named Test.scm.</p>
<p>Because of the naming conflicts, you can't in general use both the <code>-primitive</code> and the GOOPS
guile-modules at the same time. To do this, you need to rename the exported symbols from one or both
guile-modules. For example,</p>
<div class="targetlang"><pre>
(use-modules ((Test-primitive) #:renamer (symbol-prefix-proc 'primitive:)))
(use-modules ((Test) #:renamer (symbol-prefix-proc 'goops:)))
</pre></div>
<H3><a name="Guile_nn22">25.12.2 Linking</a></H3>
<p>The guile-modules generated above all need to be linked together. GOOPS support requires
either passive or module linkage. The exported GOOPS guile-module will be the name of the swig-module
and should be located in a file called <i>Module</i>.scm. This should be installed on the autoload
path for guile, so that <code>(use-modules (<i>Package Module</i>))</code> will load everything needed.
Thus, the top of the GOOPS guile-module will contain code to load everything needed by the interface
(the shared library, the scmstub module, etc.).
The <code>%goops</code> directive inserts arbitrary code into the generated GOOPS guile-module, and
should be used to load the dependent libraries.</p>
<p>This breaks up into three cases</p>
<ul>
<li><b>Passive Linkage without -scmstub</b>: Note that this linkage style has the potential for naming
conflicts, since the primitive exported function and variable names are not wrapped in a guile-module
and might conflict with names from the GOOPS guile-module (see above). Pass the -goopsprefix
argument to solve this problem. If the <code>-exportprimitive</code> option is passed to SWIG the
<code>(export ...)</code> code that would be exported into the scmstub file is exported at the bottom
of the generated GOOPS guile-module.
The <code>%goops</code> directive should contain code to load the shared library.
<div class="code"><pre>
%goops %{ (load-extension "./libfoo.so" "scm_init_my_modules_foo_module") %}
</pre></div>
<p>
Produces the following code at the top of the generated GOOPS guile-module
(with the <code>-package my/modules -module foo</code> command line arguments)
</p>
<div class="targetlang"><pre>
(define-module (my modules foo))
;; %goops directive goes here
(load-extension "./libfoo.so" "scm_init_my_modules_foo_module")
(use-modules (oop goops) (Swig common))
</pre></div>
</li>
<li><p><b>Passive Linkage with -scmstub</b>: Here, the name of the scmstub file should be
<code>Module-primitive.scm</code> (with <i>primitive</i> replaced with whatever is given with the <code>-primsuffix</code>
argument. The code to load the shared library should be located in the <code>%scheme</code> directive,
which will then be added to the scmstub file.
SWIG will automatically generate the line <code>(use-modules (<i>Package</i> <i>Module-primitive</i>))</code>
into the GOOPS guile-module. So if <i>Module-primitive.scm</i> is on the autoload path for guile, the
<code>%goops</code> directive can be empty. Otherwise, the <code>%goops</code> directive should contain
whatever code is needed to load the <i>Module-primitive.scm</i> file into guile.</p>
<div class="targetlang"><pre>
%scheme %{ (load-extension "./libfoo.so" "scm_init_my_modules_foo_module") %}
// only include the following definition if (my modules foo) cannot
// be loaded automatically
%goops %{
(primitive-load "/path/to/foo-primitive.scm")
(primitive-load "/path/to/Swig/common.scm")
%}
</pre></div>
<p>
Produces the following code at the top of the generated GOOPS guile-module
</p>
<div class="targetlang"><pre>
(define-module (my modules foo))
;; %goops directive goes here (if any)
(primitive-load "/path/to/foo-primitive.scm")
(primitive-load "/path/to/Swig/common.scm")
(use-modules (oop goops) (Swig common))
(use-modules ((my modules foo-primitive) :renamer (symbol-prefix-proc
'primitive:)))
</pre></div>
</li>
<li><p><b>Module Linkage</b>: This is very similar to passive linkage with a scmstub file.
SWIG will also automatically generate the line <code>(use-modules
(<i>Package</i> <i>Module-primitive</i>))</code> into the GOOPS guile-module. Again the <code>%goops</code>
directive should contain whatever code is needed to get that module loaded into guile.</p>
<div class="code"><pre>
%goops %{ (load-extension "./libfoo.so" "scm_init_my_modules_foo_module") %}
</pre></div>
<p>
Produces the following code at the top of the generated GOOPS guile-module
</p>
<div class="targetlang"><pre>
(define-module (my modules foo))
;; %goops directive goes here (if any)
(load-extension "./libfoo.so" "scm_init_my_modules_foo_module")
(use-modules (oop goops) (Swig common))
(use-modules ((my modules foo-primitive) :renamer (symbol-prefix-proc
'primitive:)))
</pre></div>
</li>
</ul>
<p><b>(Swig common)</b>: The generated GOOPS guile-module also imports definitions from the
(Swig common) guile-module.
This module is included with SWIG and should be installed by SWIG into the autoload path for
guile (based on the configure script and whatever arguments are passed). If it is not, then the
<code>%goops</code> directive also needs to contain code to load the <code>common.scm</code> file
into guile. Also note that if you are trying to install the generated wrappers on a computer without
SWIG installed, you will need to include the common.swg file along with the install.</p>
<p><b>Multiple Modules</b>: Type dependencies between modules is supported. For example, if
<code>mod1</code> includes definitions of some classes, and <code>mod2</code> includes some classes
derived from classes in <code>mod1</code>, the generated GOOPS file for <code>mod2</code> will declare
the correct superclasses. The only problem is that since <code>mod2</code> uses symbols from
<code>mod1</code>, the <code>mod2</code> GOOPS file must include a <code>(use-modules (mod2))</code>.
Currently, SWIG does not automatically export this line; it must be included in the <code>%goops</code>
directive of <code>mod2</code>. Maybe in the future SWIG can detect dependencies and export this line.
(how do other language modules handle this problem?)</p>
</body>
</html>

View File

@ -0,0 +1,549 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Introduction</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Introduction">2 Introduction</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Introduction_nn2">What is SWIG?</a>
<li><a href="#Introduction_nn3">Why use SWIG?</a>
<li><a href="#Introduction_target_languages">Target languages</a>
<ul>
<li><a href="#Introduction_supported_status">Supported status</a>
<li><a href="#Introduction_experimental_status">Experimental status</a>
</ul>
<li><a href="#Introduction_nn4">A SWIG example</a>
<ul>
<li><a href="#Introduction_nn5">SWIG interface file</a>
<li><a href="#Introduction_nn6">The swig command</a>
<li><a href="#Introduction_nn7">Building a Perl5 module</a>
<li><a href="#Introduction_nn8">Building a Python module</a>
<li><a href="#Introduction_nn9">Shortcuts</a>
</ul>
<li><a href="#Introduction_nn10">Supported C/C++ language features</a>
<li><a href="#Introduction_nn11">Non-intrusive interface building</a>
<li><a href="#Introduction_build_system">Incorporating SWIG into a build system</a>
<li><a href="#Introduction_nn12">Hands off code generation</a>
<li><a href="#Introduction_nn13">SWIG and freedom</a>
</ul>
</div>
<!-- INDEX -->
<H2><a name="Introduction_nn2">2.1 What is SWIG?</a></H2>
<p>
SWIG is a software development tool that simplifies the task of
interfacing different languages to C and C++ programs. In a
nutshell, SWIG is a compiler that takes C/C++ declarations and creates
the wrappers needed to access those declarations from other languages
including Perl, Python, Tcl, Ruby, Guile, and Java. SWIG normally
requires no modifications to existing code and can often be used to
build a usable interface in only a few minutes. Possible applications
of SWIG include:
</p>
<ul>
<li>Building interpreted interfaces to existing C programs.
<li>Rapid prototyping and application development.
<li>Interactive debugging.
<li>Reengineering or refactoring of legacy software into scripting language components.
<li>Making a graphical user interface (using Tk for example).
<li>Testing of C libraries and programs (using scripts).
<li>Building high performance C modules for scripting languages.
<li>Making C programming more enjoyable (or tolerable depending on your point of view).
<li>Impressing your friends.
<li>Obtaining vast sums of research funding (although obviously not applicable to the author).
</ul>
<p>
SWIG was originally designed to make it extremely easy for scientists
and engineers to build extensible scientific software without having to get a
degree in software engineering. Because of this, the use of
SWIG tends to be somewhat informal and ad-hoc (e.g., SWIG does not
require users to provide formal interface specifications as you would find in
a dedicated IDL compiler). Although
this style of development isn't appropriate for every
project, it is particularly well suited to software development in the
small; especially the research and development work that is commonly found
in scientific and engineering projects. However, nowadays SWIG is known to be used in many
large open source and commercial projects.
<H2><a name="Introduction_nn3">2.2 Why use SWIG?</a></H2>
<p>
As stated in the previous section, the primary purpose of SWIG is to simplify
the task of integrating C/C++ with other programming languages. However, why would
anyone want to do that? To answer that question, it is useful to list a few strengths
of C/C++ programming:
</p>
<ul>
<li>Excellent support for writing programming libraries.
<li>High performance (number crunching, data processing, graphics, etc.).
<li>Systems programming and systems integration.
<li>Large user community and software base.
</ul>
<p>
Next, let's list a few problems with C/C++ programming
</p>
<ul>
<li>Writing a user interface is rather painful (i.e., consider programming with MFC, X11, GTK, or any number
of other libraries).
<li>Testing is time consuming (the compile/debug cycle).
<li>Not easy to reconfigure or customize without recompilation.
<li>Modularization can be tricky.
<li>Security concerns (buffer overflows for instance).
</ul>
<p>
To address these limitations, many programmers have arrived at the
conclusion that it is much easier to use different programming
languages for different tasks. For instance, writing a graphical user
interface may be significantly easier in a scripting language like
Python or Tcl (consider the reasons why millions of programmers have used languages like
Visual Basic if you need more proof). An interactive interpreter might also serve as a
useful debugging and testing tool. Other languages like Java might
greatly simplify the task of writing distributed computing software.
The key point is that different programming languages offer different
strengths and weaknesses. Moreover, it is extremely unlikely that any
programming is ever going to be perfect. Therefore, by combining
languages together, you can utilize the best features of each language
and greatly simplify certain aspects of software development.
</p>
<p>
From the standpoint of C/C++, a lot of people use SWIG because they want to break
out of the traditional monolithic C programming model which usually results
in programs that resemble this:
<ul>
<li>A collection of functions and variables that do something useful.
<li>A <tt>main()</tt> program that starts everything.
<li>A horrible collection of hacks that form some kind of user interface (but
which no-one really wants to touch).
</ul>
<p>
Instead of going down that route, incorporating C/C++ into a higher level language
often results in a more modular design, less code, better flexibility, and increased
programmer productivity.
</p>
<p>
SWIG tries to make the problem of C/C++ integration as painless as possible.
This allows you to focus on the underlying C
program and using the high-level language interface, but not
the tedious and complex chore of making the two languages talk to each
other. At the same time, SWIG recognizes that all applications are different. Therefore,
it provides a wide variety of customization features that let you change almost
every aspect of the language bindings. This is the main reason why SWIG has such a large
user manual ;-).
<H2><a name="Introduction_target_languages">2.3 Target languages</a></H2>
<p>
SWIG in essence is a tool to generate code for making C/C++ code available to various other programming languages.
These higher level programming languages are the target languages for the SWIG code generator and C or C++ are the input languages.
A single target language must be specified when SWIG is run.
This results in generating code for C/C++ and the specified target language to interface with each other.
SWIG can be invoked multiple times, but with a different target language specified on each invocation.
This ability to interface C/C++ to many different target languages is one of SWIG's core strengths and features.
</p>
<p>
SWIG is very broadly composed of two components.
A core component creates a parse tree from the input ISO C/C++ and SWIG directives (extensions to the C/C++ standards).
The parse tree is then passed to a second component, one of the target language modules for generating code specific to a higher level language.
SWIG supports many different target languages.
These target languages are given a status of either Supported or Experimental.
This status is provided to indicate the level of maturity to expect when using a particular target language as not all target languages are fully developed.
</p>
<p>
The second part of the SWIG documentation contains a chapter for each target level language.
Each chapter will state the status (Supported or Experimental) for that language.
</p>
<H3><a name="Introduction_supported_status">2.3.1 Supported status</a></H3>
<p>
A target language is given the 'Supported' status when
</p>
<ul>
<li>It is in a mature, well functioning state.</li>
<li>It has its own comprehensive chapter in the documentation.</li>
<li>It passes all of the main SWIG test-suite and has a range of working examples.</li>
<li>It supports the vast majority of SWIG features.</li>
<li>It provides strong backwards compatibility between releases.</li>
</ul>
<p>
The above is a short summary and further details are outlined in the <a href="Extending.html#Extending_supported_status">Supported status</a> section in the Extending chapter.
The good news is that all the well-known and most popular languages have this status.
</p>
<H3><a name="Introduction_experimental_status">2.3.2 Experimental status</a></H3>
<p>
A target language is given the 'Experimental' status when
</p>
<ul>
<li>It is of sub-standard quality, failing to meet the above 'Supported' status.</li>
<li>It is somewhere between the mid to mature stage of development.</li>
<li>It does not guarantee any backwards compatibility between releases.</li>
<li>It is in need of help to finish development.</li>
</ul>
<p>
Anyone using an experimental target language is strongly urged to assist with development of the target language module if they wish to use it.
</p>
<p>
SWIG displays a warning when an experimental target language is used in order to set expectations and emphasize the experimental status of the target language.
The usual <a href="Warnings.html#Warnings_suppression">warning suppression</a> techniques can be used if required.
</p>
<p>
The above is a short summary and further details are outlined in the <a href="Extending.html#Extending_experimental_status">Experimental status</a> section in the Extending chapter.
</p>
<H2><a name="Introduction_nn4">2.4 A SWIG example</a></H2>
<p>
The best way to illustrate SWIG is with a simple example. Consider the
following C code:
</p>
<div class="code"><pre>
/* File : example.c */
double My_variable = 3.0;
/* Compute factorial of n */
int fact(int n) {
if (n &lt;= 1)
return 1;
else
return n*fact(n-1);
}
/* Compute n mod m */
int my_mod(int n, int m) {
return(n % m);
}
</pre></div>
<p>
Suppose that you wanted to access these functions and the global
variable <tt>My_variable</tt> from Tcl. You start by making a SWIG
interface file as shown below (by convention, these files carry a .i
suffix) :
<H3><a name="Introduction_nn5">2.4.1 SWIG interface file</a></H3>
<div class="code"><pre>
/* File : example.i */
%module example
%{
/* Put headers and other declarations here */
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
%}
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
</pre></div>
<p>
The interface file contains ISO C function prototypes and variable
declarations. The <tt>%module</tt> directive defines the name of the
module that will be created by SWIG. The <tt>%{ %}</tt> block
provides a location for inserting additional code, such as C header
files or additional C declarations, into the generated C wrapper code.
<H3><a name="Introduction_nn6">2.4.2 The swig command</a></H3>
<p>
SWIG is invoked using the <tt>swig</tt> command. We can use this to
build a Tcl module (under Linux) as follows :
</p>
<div class="shell"><pre>
unix &gt; <b>swig -tcl example.i</b>
unix &gt; <b>gcc -c -fpic example.c example_wrap.c -I/usr/local/include</b>
unix &gt; <b>gcc -shared example.o example_wrap.o -o example.so</b>
unix &gt; <b>tclsh</b>
% <b>load ./example.so</b>
% <b>fact 4</b>
24
% <b>my_mod 23 7</b>
2
% <b>expr $My_variable + 4.5</b>
7.5
%
</pre></div>
<p>
The <tt>swig</tt> command produced a new file called
<tt>example_wrap.c</tt> that should be compiled along with the
<tt>example.c</tt> file. Most operating systems and scripting
languages now support dynamic loading of modules. In our example, our
Tcl module has been compiled into a shared library that can be loaded
into Tcl. When loaded, Tcl can now access the functions
and variables declared in the SWIG interface. A look at the file
<tt>example_wrap.c</tt> reveals a hideous mess. However, you
almost never need to worry about it.
<H3><a name="Introduction_nn7">2.4.3 Building a Perl5 module</a></H3>
<p>
Now, let's turn these functions into a Perl5 module. Without making
any changes type the following (shown for Solaris):
</p>
<div class="shell"><pre>
unix &gt; <b>swig -perl5 example.i</b>
unix &gt; <b>gcc -c example.c example_wrap.c \
-I/usr/local/lib/perl5/sun4-solaris/5.003/CORE</b>
unix &gt; <b>ld -G example.o example_wrap.o -o example.so</b> # This is for Solaris
unix &gt; <b>perl5.003
use example;
print example::fact(4), "\n";
print example::my_mod(23, 7), "\n";
print $example::My_variable + 4.5, "\n";
&lt;ctrl-d&gt;</b>
24
2
7.5
unix &gt;
</pre></div>
<H3><a name="Introduction_nn8">2.4.4 Building a Python module</a></H3>
<p>
Finally, let's build a module for Python (shown for Irix).
</p>
<div class="shell"><pre>
unix &gt; <b>swig -python example.i</b>
unix &gt; <b>gcc -c -fpic example.c example_wrap.c -I/usr/local/include/python2.0</b>
unix &gt; <b>gcc -shared example.o example_wrap.o -o _example.so</b>
unix &gt; <b>python</b>
Python 2.0 (#6, Feb 21 2001, 13:29:45)
[GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2
Type "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; <b>import example</b>
&gt;&gt;&gt; <b>example.fact(4)</b>
24
&gt;&gt;&gt; <b>example.my_mod(23, 7)</b>
2
&gt;&gt;&gt; <b>example.cvar.My_variable + 4.5</b>
7.5
</pre></div>
<H3><a name="Introduction_nn9">2.4.5 Shortcuts</a></H3>
<p>
To the truly lazy programmer, one may wonder why we needed the extra
interface file at all. As it turns out, you can often do without
it. For example, you could also build a Perl5 module by just running
SWIG on the C header file and specifying a module name as follows
</p>
<div class="shell"><pre>
unix &gt; <b>swig -perl5 -module example example.h</b>
unix &gt; <b>gcc -c example.c example_wrap.c \
-I/usr/local/lib/perl5/sun4-solaris/5.003/CORE</b>
unix &gt; <b>ld -G example.o example_wrap.o -o example.so</b>
unix &gt; <b>perl5.003
use example;
print example::fact(4), "\n";
print example::my_mod(23, 7), "\n";
print $example::My_variable + 4.5, "\n";
&lt;ctrl-d&gt;</b>
24
2
7.5
</pre></div>
<H2><a name="Introduction_nn10">2.5 Supported C/C++ language features</a></H2>
<p>
A primary goal of the SWIG project is to make the language binding
process extremely easy. Although a few simple examples have been shown,
SWIG is quite capable in supporting most of C++. Some of the
major features include:
</p>
<ul>
<li>Full C99 preprocessing.
<li>All ISO C and C++ datatypes.
<li>Functions, variables, and constants.
<li>Classes.
<li>Single and multiple inheritance.
<li>Overloaded functions and methods.
<li>Overloaded operators.
<li>C++ templates (including member templates, specialization, and partial specialization).
<li>Namespaces.
<li>Variable length arguments.
<li>C++ smart pointers.
</ul>
<p>
Most of C++11 is also supported. Details are in the <a href="CPlusPlus11.html#CPlusPlus11">C++11</a> chapter.
C++14 support is covered in the <a href="CPlusPlus14.html#CPlusPlus14">C++14</a> chapter.
C++17 support is covered in the <a href="CPlusPlus17.html#CPlusPlus17">C++17</a> chapter.
</p>
<p>
It is important to stress that SWIG is not a simplistic C++ lexing
tool like several apparently similar wrapper generation tools. SWIG
not only parses C++, it implements the full C++ type system and it is
able to understand C++ semantics. SWIG generates its wrappers with
full knowledge of this information. As a result, you will find SWIG
to be just as capable of dealing with nasty corner cases as it is in
wrapping simple C++ code. In fact, SWIG is able to handle C++ code that
stresses the very limits of many C++ compilers.
<H2><a name="Introduction_nn11">2.6 Non-intrusive interface building</a></H2>
<p>
When used as intended, SWIG requires minimal (if any) modification to
existing C or C++ code. This makes SWIG extremely easy to use with existing
packages and promotes software reuse and modularity. By making
the C/C++ code independent of the high level interface, you can change the
interface and reuse the code in other applications. It is also
possible to support different types of interfaces depending on the application.
</p>
<H2><a name="Introduction_build_system">2.7 Incorporating SWIG into a build system</a></H2>
<p>
SWIG is a command line tool and as such can be incorporated into any build system that supports invoking external tools/compilers.
SWIG is most commonly invoked from within a Makefile, but is also known to be invoked from popular IDEs such as
Microsoft Visual Studio.
</p>
<p>
If you are using the GNU Autotools
(<a href="http://www.gnu.org/software/autoconf/">Autoconf</a>/
<a href="http://www.gnu.org/software/automake/">Automake</a>/
<a href="http://www.gnu.org/software/libtool/">Libtool</a>)
to configure SWIG use in your project, the SWIG Autoconf macros can be used.
The primary macro is <tt>ax_pkg_swig</tt>, see
<a href="http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html#ax_pkg_swig">http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html#ax_pkg_swig</a>.
The <tt>ax_python_devel</tt> macro is also helpful for generating Python extensions. See the
<a href="http://www.gnu.org/software/autoconf-archive/">Autoconf Archive</a>
for further information on this and other Autoconf macros.
</p>
<p>
There is growing support for SWIG in some build tools, for example <a href="https://cmake.org">CMake</a>
is a cross-platform, open-source build manager with built in support for SWIG. CMake can detect the SWIG executable
and many of the target language libraries for linking against.
CMake knows how to build shared libraries and loadable modules on many different operating systems.
This allows easy cross platform SWIG development. It can also generate the custom commands necessary for
driving SWIG from IDEs and makefiles. All of this can be done from a single cross platform input file.
The following example is a CMake input file for creating a Python wrapper for the SWIG interface file, example.i:
</p>
<div class="code"><pre>
# This is a CMake example for Python
FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})
FIND_PACKAGE(PythonLibs)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET(CMAKE_SWIG_FLAGS "")
SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON)
SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall")
SWIG_ADD_MODULE(example python example.i example.cxx)
SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES})
</pre></div>
<p>
The above example will generate native build files such as makefiles, nmake files and Visual Studio projects
which will invoke SWIG and compile the generated C++ files into _example.so (UNIX) or _example.pyd (Windows).
For other target languages on Windows a dll, instead of a .pyd file, is usually generated.
</p>
<H2><a name="Introduction_nn12">2.8 Hands off code generation</a></H2>
<p>
SWIG is designed to produce working code that needs no
hand-modification (in fact, if you look at the output, you probably
won't want to modify it). You should think of your target language interface being
defined entirely by the input to SWIG, not the resulting output
file. While this approach may limit flexibility for hard-core hackers,
it allows others to forget about the low-level implementation
details.
</p>
<H2><a name="Introduction_nn13">2.9 SWIG and freedom</a></H2>
<p>
No, this isn't a special section on the sorry state of world politics.
However, it may be useful to know that SWIG was written with a
certain "philosophy" about programming---namely that programmers are
smart and that tools should just stay out of their way. Because of
that, you will find that SWIG is extremely permissive in what it lets
you get away with. In fact, you can use SWIG to go well beyond
"shooting yourself in the foot" if dangerous programming is your goal.
On the other hand, this kind of freedom may be exactly what is needed
to work with complicated and unusual C/C++ applications.
</p>
<p>
Ironically, the freedom that SWIG provides is countered by an
extremely conservative approach to code generation. At its core, SWIG
tries to distill even the most advanced C++ code down to a small
well-defined set of interface building techniques based on ISO C
programming. Because of this, you will find that SWIG interfaces can
be easily compiled by virtually every C/C++ compiler and that they can
be used on any platform. Again, this is an important part of staying out
of the programmer's way----the last thing any developer wants to do is
to spend their time debugging the output of a tool that relies on
non-portable or unreliable programming features.
Dependencies are often a source of incompatibilities and problems and so
additional third party libraries are not used in the generated code.
SWIG will also generally avoid generating code that introduces a dependency
on the C++ Standard Template Library (STL).
SWIG will generate code that depends on the C libraries though.
</p>
</body>
</html>

9119
Doc/Manual/Java.html Normal file

File diff suppressed because it is too large Load Diff

998
Doc/Manual/Javascript.html Normal file
View File

@ -0,0 +1,998 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<title></title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<H1><a name="Javascript">27 SWIG and Javascript</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Javascript_overview">Overview</a>
<li><a href="#Javascript_preliminaries">Preliminaries</a>
<ul>
<li><a href="#Javascript_running_swig">Running SWIG</a>
<li><a href="#Javascript_running_tests_examples">Running Tests and Examples</a>
<li><a href="#Javascript_known_issues">Known Issues</a>
</ul>
<li><a href="#Javascript_integration">Integration</a>
<ul>
<li><a href="#Javascript_node_extensions">Creating node.js Extensions</a>
<ul>
<li><a href="#Javascript_troubleshooting">Troubleshooting</a>
</ul>
<li><a href="#Javascript_embedded_webkit">Embedded Webkit</a>
<ul>
<li><a href="#Javascript_osx">Mac OS X</a>
<li><a href="#Javascript_gtk">GTK</a>
</ul>
<li><a href="#Javascript_applications_webkit">Creating Applications with node-webkit</a>
</ul>
<li><a href="#Javascript_examples">Examples</a>
<ul>
<li><a href="#Javascript_simple_example">Simple</a>
<li><a href="#Javascript_class_example">Class</a>
</ul>
<li><a href="#Javascript_implementation">Implementation</a>
<ul>
<li><a href="#Javascript_source_code">Source Code</a>
<li><a href="#Javascript_code_templates">Code Templates</a>
<li><a href="#Javascript_emitter">Emitter</a>
<li><a href="#Javascript_emitter_states">Emitter states</a>
<li><a href="#Javascript_jsc_exceptions">Handling Exceptions in JavascriptCore</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>This chapter describes SWIG's support of Javascript. It does not cover SWIG basics, but only information that is specific to this module.</p>
<H2><a name="Javascript_overview">27.1 Overview</a></H2>
<p>Javascript is a prototype-based scripting language that is dynamic, weakly typed and has first-class functions. Its arguably the most popular language for web development.
Javascript has gone beyond being a browser-based scripting language and with <a href="https://nodejs.org">node.js</a>, it is also used as a backend development language.</p>
<p>Native Javascript extensions can be used for applications that embed a web-browser view or that embed a Javascript engine (such as <em>node.js</em>). Extending a general purpose web-browser is not possible as this would be a severe security issue.</p>
<p>SWIG Javascript currently supports <strong>JavascriptCore</strong>, the Javascript engine used by <code>Safari/Webkit</code>, and <a href="https://v8.dev/"><strong>v8</strong></a>, which is used by <code>Chromium</code> and <code>node.js</code>.</p>
<p><a href="https://webkit.org/">WebKit</a> is a modern browser implementation available as open-source which can be embedded into an application.
With <a href="https://github.com/rogerwang/node-webkit">node-webkit</a> there is a platform which uses Google's <code>Chromium</code> as Web-Browser widget and <code>node.js</code> for javascript extensions.
</p>
<H2><a name="Javascript_preliminaries">27.2 Preliminaries</a></H2>
<H3><a name="Javascript_running_swig">27.2.1 Running SWIG</a></H3>
<p>Suppose that you defined a SWIG module such as the following:</p>
<div class="code">
<pre>
%module example
%{
#include "example.h"
%}
int gcd(int x, int y);
extern double Foo;</pre>
</div>
<p>To build a Javascript module, run SWIG using the <code>-javascript</code> option and a desired target engine <code>-jsc</code>, <code>-v8</code>, or <code>-node</code>. The generator for <code>node</code> is essentially delegating to the <code>v8</code> generator and adds some necessary preprocessor definitions.</p>
<div class="shell">
<pre>
$ swig -javascript -jsc example.i</pre>
</div>
<p>If building a C++ extension, add the -c++ option:</p>
<div class="shell">
<pre>
$ swig -c++ -javascript -jsc example.i</pre>
</div>
<p>The V8 code that SWIG generates should work with most versions from 3.11.10 up to 3.29.14 and later.</p>
<p>The API headers for V8 &gt;= 4.3.0 define constants which SWIG can use to
determine the V8 version it is compiling for. For versions &lt; 4.3.0, you
need to specify the V8 version when running SWIG. This is specified as a hex
constant, but the constant is read as pairs of decimal digits, so for V8
3.25.30 use constant 0x032530. This scheme can't represent components &gt; 99,
but this constant is only useful for V8 &lt; 4.3.0, and no V8 versions from
that era had a component &gt; 99. For example:</p>
<div class="shell">
<pre>
$ swig -c++ -javascript -v8 -DV8_VERSION=0x032530 example.i</pre>
</div>
<p>If you're targeting V8 &gt;= 4.3.0, you would just run swig like so:</p>
<div class="shell">
<pre>
$ swig -c++ -javascript -v8 example.i</pre>
</div>
<p>This creates a C/C++ source file <code>example_wrap.c</code> or <code>example_wrap.cxx</code>. The generated C source file contains the low-level wrappers that need to be compiled and linked with the rest of your C/C++ application to create an extension module.</p>
<p>The name of the wrapper file is derived from the name of the input file. For example, if the input file is <code>example.i</code>, the name of the wrapper file is <code>example_wrap.c</code>. To change this, you can use the -o option. The wrapped module will export one function which must be called to register the module with the Javascript interpreter. For example, if your module is named <code>example</code> the corresponding initializer for JavascriptCore would be</p>
<div class="code">
<pre>
bool example_initialize(JSGlobalContextRef context, JSObjectRef *exports)</pre>
</div>
<p>and for v8:</p>
<div class="code">
<pre>
void example_initialize(v8::Handle&lt;v8::Object&gt; exports)</pre>
</div>
<p>
<b>Note</b>: be aware that <code>v8</code> has a C++ API, and thus, the generated modules must be compiled as C++.
</p>
<H3><a name="Javascript_running_tests_examples">27.2.2 Running Tests and Examples</a></H3>
<p>The configuration for tests and examples currently supports Linux and Mac only and not MinGW (Windows) yet.</p>
<p>The default interpreter is <code>node.js</code> as it is available on all platforms and convenient to use.</p>
<p>Running the examples with JavascriptCore requires <code>libjavascriptcoregtk-1.0</code> to be installed, e.g., under Ubuntu with</p>
<div class="shell">
<pre>
$ sudo apt-get install libjavascriptcoregtk-1.0-dev</pre>
</div>
<p>Running with <code>V8</code> requires <code>libv8</code>:</p>
<div class="shell">
<pre>
$ sudo apt-get install libv8-dev</pre>
</div>
<p>Examples can be run using</p>
<div class="shell">
<pre>
$ make check-javascript-examples ENGINE=jsc</pre>
</div>
<p><code>ENGINE</code> can be <code>node</code>, <code>jsc</code>, or <code>v8</code>.</p>
<p>The test-suite can be run using</p>
<div class="shell">
<pre>
$ make check-javascript-test-suite ENGINE=jsc</pre>
</div>
<p>You can specify a specific <code>V8</code> version for running the examples and tests</p>
<div class="shell">
<pre>
$ make check-javascript-examples V8_VERSION=0x032530 ENGINE=v8</pre>
</div>
<H3><a name="Javascript_known_issues">27.2.3 Known Issues</a></H3>
<p>At the moment, the Javascript generators pass all tests syntactically, i.e., the generated source code compiles. However, there are still remaining runtime issues.</p>
<ul>
<li><p>Default optional arguments do not work for all targeted interpreters</p></li>
<li><p>Multiple output arguments do not work for JSC</p></li>
<li><p>C89 incompatibility: the JSC generator might still generate C89 violating code</p></li>
<li><p><code>long long</code> is not supported</p></li>
<li><p>Javascript callbacks are not supported</p></li>
<li><p><code>instanceOf</code> does not work under JSC</p></li>
</ul>
<p>The primary development environment has been Linux (Ubuntu 12.04). Windows and Mac OS X have been tested sporadically. Therefore, the generators might have more issues on those platforms. Please report back any problem you observe to help us improving this module quickly.</p>
<H2><a name="Javascript_integration">27.3 Integration</a></H2>
<p>This chapter gives a short introduction how to use a native Javascript extension: as a <code>node.js</code> module, and as an extension for an embedded Webkit.</p>
<H3><a name="Javascript_node_extensions">27.3.1 Creating node.js Extensions</a></H3>
<p>To install <code>node.js</code> you can download an installer from their <a href="https://launchpad.net/~chris-lea/+archive/node.js">web-site</a> for Mac OS X and Windows. For Linux you can either build the source yourself and run <code>sudo checkinstall</code> or keep to the (probably stone-age) packaged version. For Ubuntu there is a <a href="https://launchpad.net/~chris-lea/+archive/ubuntu/node.js/">PPA</a> available.</p>
<div class="shell">
<pre>
$ sudo add-apt-repository ppa:chris-lea/node.js
$ sudo apt-get update
$ sudo apt-get install nodejs</pre>
</div>
<p>As <code>v8</code> is written in C++ and comes as a C++ library it is crucial to compile your module using the same compiler flags as used for building v8. To make things easier, <code>node.js</code> provides a build tool called <code>node-gyp</code>.</p>
<p>You have to install it using <code>npm</code>:</p>
<div class="shell">
<pre>
$ sudo npm install -g node-gyp</pre>
</div>
<p><code>node-gyp</code> expects a configuration file named <code>binding.gyp</code> which is basically in JSON format and conforms to the same format that is used with Google's build-tool <code>gyp</code>.</p>
<p><code>binding.gyp</code>:</p>
<div class="code">
<pre>
{
"targets": [
{
"target_name": "example",
"sources": [ "example.cxx", "example_wrap.cxx" ]
}
]
}</pre>
</div>
<p>First create the wrapper using SWIG:</p>
<div class="shell">
<pre>
$ swig -javascript -node -c++ example.i</pre>
</div>
<p>Then run <code>node-gyp build</code> to actually create the module:</p>
<div class="shell">
<pre>
$ node-gyp build</pre>
</div>
<p>This will create a <code>build</code> folder containing the native module. To use the extension you need to 'require' it in your Javascript source file:</p>
<div class="code">
<pre>
require("./build/Release/example")</pre>
</div>
<p>A more detailed explanation is given in the <a href="#Javascript_examples">Examples</a> section.</p>
<H4><a name="Javascript_troubleshooting">27.3.1.1 Troubleshooting</a></H4>
<ul>
<li><em>'module' object has no attribute 'script_main'</em></li>
</ul>
<p>This error happens when <code>gyp</code> is installed as a distribution package. It seems to be outdated. Removing it resolves the problem.</p>
<div class="shell">
<pre>
$ sudo apt-get remove gyp</pre>
</div>
<H3><a name="Javascript_embedded_webkit">27.3.2 Embedded Webkit</a></H3>
<p>Webkit is pre-installed on Mac OS X and available as a library for GTK.</p>
<H4><a name="Javascript_osx">27.3.2.1 Mac OS X</a></H4>
<p>There is general information about programming with WebKit on <a href="https://developer.apple.com/library/mac/documentation/cocoa/conceptual/DisplayWebContent/DisplayWebContent.html">Apple Developer Documentation</a>. Details about <code>Cocoa</code> programming are not covered here.</p>
<p>An integration of a native extension 'example' would look like this:</p>
<div class="code">
<pre>
#import "appDelegate.h"
extern bool example_initialize(JSGlobalContextRef context, JSObjectRef* exports);
@implementation ExampleAppDelegate
@synthesize webView;
- (void)addGlobalObject:(JSContextRef) context:(NSString *)objectName:(JSObjectRef) theObject {
JSObjectRef global = JSContextGetGlobalObject(context);
JSStringRef objectJSName = JSStringCreateWithCFString( (CFStringRef) objectName )
if ( objectJSName != NULL ) {
JSObjectSetProperty(context, global, objectJSName, theObject, kJSPropertyAttributeReadOnly, NULL);
JSStringRelease( objectJSName );
}
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Start a webview with the bundled index.html file
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *url = [NSString stringWithFormat: @"file://%@/Contents/Assets/index.html", path];
WebFrame *webframe = [webView mainFrame];
JSGlobalContextRef context = [webframe globalContext];
JSObjectRef example;
example_initialize(context, &amp;example);
[self addGlobalObject:context:@"example":example]
JSObjectSetProperty(context, global, JSStringRef propertyName, example, JSPropertyAttributes attributes, NULL);
[ [webView mainFrame] loadRequest:
[NSURLRequest requestWithURL: [NSURL URLWithString:url] ]
];
}
@end</pre>
</div>
<H4><a name="Javascript_gtk">27.3.2.2 GTK</a></H4>
<p>There is general information about programming GTK at <a href="https://developer.gnome.org/gtk2/">GTK documentation</a> and in the <a href="https://developer.gnome.org/gtk-tutorial/">GTK tutorial</a>, and for Webkit there is a <a href="http://webkitgtk.org/reference/webkitgtk/stable/index.html">Webkit GTK+ API Reference</a>.</p>
<p>An integration of a native extension 'example' would look like this:</p>
<div class="code">
<pre>
#include &lt;gtk/gtk.h&gt;
#include &lt;webkit/webkit.h&gt;
extern bool example_initialize(JSGlobalContextRef context);
int main(int argc, char* argv[])
{
// Initialize GTK+
gtk_init(&amp;argc, &amp;argv);
...
// Create a browser instance
WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
WebFrame *webframe = webkit_web_view_get_main_frame(webView);
JSGlobalContextRef context = webkit_web_frame_get_global_context(webFrame);
JSObjectRef global = JSContextGetGlobalObject(context);
JSObjectRef exampleModule;
example_initialize(context, &amp;exampleModule);
JSStringRef jsName = JSStringCreateWithUTF8CString("example");
JSObjectSetProperty(context, global, jsName, exampleModule, kJSPropertyAttributeReadOnly, NULL);
JSStringRelease(jsName);
...
// Load a web page into the browser instance
webkit_web_view_load_uri(webView, "http://www.webkitgtk.org/");
...
// Run the main GTK+ event loop
gtk_main();
return 0;
}</pre>
</div>
<H3><a name="Javascript_applications_webkit">27.3.3 Creating Applications with node-webkit</a></H3>
<p>To get started with <code>node-webkit</code> there is a very informative set of <a href="https://github.com/rogerwang/node-webkit/wiki">wiki pages</a>.</p>
<p>Similar to <code>node.js</code>, <code>node-webkit</code> is started from command line within a <code>node.js</code> project directory.
Native extensions are created in the very same way as for <code>node.js</code>, except that a customized <code>gyp</code> derivate has to be used: <a href="https://github.com/rogerwang/nw-gyp">nw-gyp</a>.
</p>
<p>
A simple example would have the following structure:
</p>
<div class="code">
<pre>
- package.json
- app.html
- app.js
- node_modules
/ example
... (as known from node.js)
</pre>
</div>
<p>
The configuration file essentially conforms to <code>node.js</code> syntax.
It has some extras to configure <code>node-webkit</code>. See the <a href="https://github.com/rogerwang/node-webkit/wiki/Manifest-format">Manifest</a> specification for more details.
</p>
<p>
<code>package.json</code>:
</p>
<div class="code">
<pre>
{
"name": "example",
"main": "app.html",
"window": {
"show": true,
"width": 800,
"height": 600
}
}</pre>
</div>
<p>
The <code>'main'</code> property of <code>package.json</code> specifies a web-page to be rendered in
the main window.</p>
<p>
<code>app.html</code>:
</p>
<div class="code">
<pre>
&lt;html&gt;
&lt;head&gt;
&lt;script src="app.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div&gt;
The greatest common divisor of
&lt;span id="x"&gt;&lt;/span&gt; and
&lt;span id="y"&gt;&lt;/span&gt; is
&lt;span id="z"&gt;&lt;/span&gt;.
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
</div>
<p>
As known from <code>node.js</code> one can use <code>require</code> to load javascript modules.
Additionally, <code>node-webkit</code> provides an API that allows to manipulate the window's menu,
open new windows, and many more things.
</p>
<p>
<code>app.js</code>:
</p>
<div class="code">
<pre>window.onload = function() {
var example = require("example");
var x = 18;
var y = 24;
var z = example.gcd(x, y);
document.querySelector('#x').innerHTML = x;
document.querySelector('#y').innerHTML = y;
document.querySelector('#z').innerHTML = z;
};</pre>
</div>
<H2><a name="Javascript_examples">27.4 Examples</a></H2>
<p>Some basic examples are shown here in more detail.</p>
<H3><a name="Javascript_simple_example">27.4.1 Simple</a></H3>
<p>The common example <code>simple</code> looks like this:</p>
<div class="code">
<pre>
/* File : example.i */
%module example
%inline %{
extern int gcd(int x, int y);
extern double Foo;
%}</pre>
</div>
<p>To make this available as a node extension a <code>binding.gyp</code> has to be created:</p>
<div class="code">
<pre>
{
"targets": [
{
"target_name": "example",
"sources": [ "example.cxx", "example_wrap.cxx" ]
}
]
}</pre>
</div>
<p>Then <code>node-gyp</code> is used to build the extension:</p>
<div class="shell">
<pre>
$ node-gyp configure build</pre>
</div>
<p>From a 'nodejs` application the extension would be used like this:</p>
<div class="code">
<pre>
// import the extension via require
var example = require("./build/Release/example");
// calling the global method
var x = 42;
var y = 105;
var g = example.gcd(x, y);
// Accessing the global variable
var f = example.Foo;
example.Foo = 3.1415926;</pre>
</div>
<p>First the module <code>example</code> is loaded from the previously built extension. Global methods and variables are available in the scope of the module.</p>
<p><b>Note</b>: ECMAScript 5, the currently implemented Javascript standard, does not have modules. <code>node.js</code> and other implementations provide this mechanism defined by the <a href="http://wiki.commonjs.org/wiki/CommonJS">CommonJS</a> group. For browsers this is provided by <a href="http://browserify.org">Browserify</a>, for instance.</p>
<H3><a name="Javascript_class_example">27.4.2 Class</a></H3>
<p>The common example <code>class</code> defines three classes, <code>Shape</code>, <code>Circle</code>, and <code>Square</code>:</p>
<div class="code">
<pre>
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
}
double x, y;
void move(double dx, double dy);
virtual double area(void) = 0;
virtual double perimeter(void) = 0;
static int nshapes;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { }
virtual double area(void);
virtual double perimeter(void);
};
class Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { }
virtual double area(void);
virtual double perimeter(void);
};</pre>
</div>
<p><code>Circle</code> and <code>Square</code> inherit from <code>Shape</code>. <code>Shape</code> has a static variable <code>nshapes</code>, a function <code>move</code> that can't be overridden (non-virtual), and two abstract functions <code>area</code> and <code>perimeter</code> (pure virtual) that must be overridden by the sub-classes.</p>
<p>A <code>nodejs</code> extension is built the same way as for the <code>simple</code> example.</p>
<p>In Javascript it can be used as follows:</p>
<div class="code">
<pre>
var example = require("./build/Release/example");
// local aliases for convenience
var Shape = example.Shape;
var Circle = example.Circle;
var Square = example.Square;
// creating new instances using the 'new' operator
var c = new Circle(10);
var s = new Square(10);
// accessing a static member
Shape.nshapes;
// accessing member variables
c.x = 20;
c.y = 30;
s.x = -10;
s.y = 5;
// calling some methods
c.area();
c.perimeter();
s.area();
s.perimeter();
// instantiation of Shape is not permitted
new Shape();</pre>
</div>
<p>Running these commands in an interactive node shell results in the following output:</p>
<div class="shell">
<pre>
$ node -i
&amp; var example = require("./build/Release/example");
undefined
&amp; var Shape = example.Shape;
undefined
&amp; var Circle = example.Circle;
undefined
&amp; var Square = example.Square;
undefined
&amp; var c = new Circle(10);
undefined
&amp; var s = new Square(10);
undefined
&amp; Shape.nshapes;
2
&amp; c.x = 20;
20
&amp; c.y = 30;
30
&amp; s.x = -10;
-10
&amp; s.y = 5;
5
&amp; c.area();
314.1592653589793
&amp; c.perimeter();
62.83185307179586
&amp; s.area();
100
&amp; s.perimeter();
40
&amp; c.move(40, 40)
undefined
&amp; c.x
60
&amp; c.y
70
&amp; new Shape()
Error: Class Shape can not be instantiated
at repl:1:2
at REPLServer.self.eval (repl.js:110:21)
at Interface.&lt;anonymous&gt; (repl.js:239:12)
at Interface.EventEmitter.emit (events.js:95:17)
at Interface._onLine (readline.js:202:10)
at Interface._line (readline.js:531:8)
at Interface._ttyWrite (readline.js:760:14)
at ReadStream.onkeypress (readline.js:99:10)
at ReadStream.EventEmitter.emit (events.js:98:17)
at emitKey (readline.js:1095:12)</pre>
</div>
<p>
<b>Note</b>: In ECMAScript 5 there is no concept for classes. Instead each function can be used as a constructor function which is executed by the 'new' operator. Furthermore, during construction the key property <code>prototype</code> of the constructor function is used to attach a prototype instance to the created object. A prototype is essentially an object itself that is the first-class delegate of a class used whenever the access to a property of an object fails. The very same prototype instance is shared among all instances of one type. Prototypal inheritance is explained in more detail on in <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain">Inheritance and the prototype chain</a>, for instance.
</p>
<H2><a name="Javascript_implementation">27.5 Implementation</a></H2>
<p>The Javascript Module implementation has taken a very different approach compared to other language modules in order to support different Javascript interpreters.</p>
<H3><a name="Javascript_source_code">27.5.1 Source Code</a></H3>
<p>The Javascript module is implemented in <code>Source/Modules/javascript.cxx</code>. It dispatches the code generation to a <code>JSEmitter</code> instance, <code>V8Emitter</code> or <code>JSCEmitter</code>. Additionally there are some helpers: <code>Template</code>, for templated code generation, and <code>JSEmitterState</code>, which is used to manage state information during AST traversal. This rough map shall make it easier to find a way through this huge source file:</p>
<div class="code">
<pre>
// module wide defines
#define NAME "name"
...
// ###############################
// # Helper class declarations
class JSEmitterState { ... };
class Template { ... };
// ###############################
// # JSEmitter declaration
class JSEmitter { ... };
// Emitter factory declarations
JSEmitter *swig_javascript_create_JSCEmitter();
JSEmitter *swig_javascript_create_V8Emitter();
// ###############################
// # Javascript module
// Javascript module declaration
class JAVASCRIPT:public Language { ... };
// Javascript module implementation
int JAVASCRIPT::functionWrapper(Node *n) { ... }
...
// Module factory implementation
static Language *new_swig_javascript() { ... }
extern "C" Language *swig_javascript(void) { ... }
// ###############################
// # JSEmitter base implementation
JSEmitter::JSEmitter() { ... }
Template JSEmitter::getTemplate(const String *name) { ... }
...
// ###############################
// # JSCEmitter
// JSCEmitter declaration
class JSCEmitter: public JSEmitter { ... };
// JSCEmitter implementation
JSCEmitter::JSCEmitter() { ... }
void JSCEmitter::marshalInputArgs(Node *n, ParmList *parms, Wrapper *wrapper, MarshallingMode mode, bool is_member, bool is_static) { ... }
...
// JSCEmitter factory
JSEmitter *swig_javascript_create_JSCEmitter() { ... }
// ###############################
// # V8Emitter
// V8Emitter declaration
class V8Emitter: public JSEmitter { ... };
// V8Emitter implementation
V8Emitter::V8Emitter() { ... }
int V8Emitter::initialize(Node *n) { ... }
// V8Emitter factory
JSEmitter *swig_javascript_create_V8Emitter() { ... }
// ###############################
// # Helper implementation (JSEmitterState, Template)
JSEmitterState::JSEmitterState() { ... }
...
Template::Template(const String *code_) { ... }
...</pre>
</div>
<H3><a name="Javascript_code_templates">27.5.2 Code Templates</a></H3>
<p>All generated code is created on the basis of code templates. The templates for <em>JavascriptCore</em> can be found in <code>Lib/javascript/jsc/javascriptcode.swg</code>, for <em>v8</em> in <code>Lib/javascript/v8/javascriptcode.swg</code>.</p>
<p>To track the originating code template for generated code you can run</p>
<div class="shell">
<pre>
$ swig -javascript -jsc -debug-codetemplates</pre>
</div>
<p>which wraps generated code with a descriptive comment</p>
<div class="code">
<pre>
/* begin fragment("template_name") */
...generated code ...
/* end fragment("template_name") */</pre>
</div>
<p>The Template class is used like this:</p>
<div class="code">
<pre>
Template t_register = getTemplate("jsv8_register_static_variable");
t_register.replace("$jsparent", state.clazz(NAME_MANGLED))
.replace("$jsname", state.variable(NAME))
.replace("$jsgetter", state.variable(GETTER))
.replace("$jssetter", state.variable(SETTER))
.trim().
print(f_init_static_wrappers);</pre>
</div>
<p>A code template is registered with the <em>JSEmitter</em> via <code>fragment(name, &quot;template&quot;)</code>, e.g., </p>
<div class="code">
<pre>
%fragment ("jsc_variable_declaration", "templates")
%{
{"$jsname", $jsgetter, $jssetter, kJSPropertyAttributeNone},
%}</pre>
</div>
<p><code>Template</code> creates a copy of that string and <code>Template::replace</code> uses Swig's <code>Replaceall</code> to replace variables in the template. <code>Template::trim</code> can be used to eliminate leading and trailing whitespaces. <code>Template::print</code> is used to write the final template string to a Swig <code>DOH</code> (based on <code>Printv</code>). All methods allow chaining.</p>
<H3><a name="Javascript_emitter">27.5.3 Emitter</a></H3>
<p>The Javascript module delegates code generation to a <code>JSEmitter</code> instance. The following extract shows the essential interface:</p>
<div class="code">
<pre>
class JSEmitter {
...
/**
* Opens output files and temporary output DOHs.
*/
virtual int initialize(Node *n);
/**
* Writes all collected code into the output file(s).
*/
virtual int dump(Node *n) = 0;
/**
* Cleans up all open output DOHs.
*/
virtual int close() = 0;
...
/**
* Invoked at the beginning of the classHandler.
*/
virtual int enterClass(Node *);
/**
* Invoked at the end of the classHandler.
*/
virtual int exitClass(Node *) {
return SWIG_OK;
}
/**
* Invoked at the beginning of the variableHandler.
*/
virtual int enterVariable(Node *);
/**
* Invoked at the end of the variableHandler.
*/
virtual int exitVariable(Node *) {
return SWIG_OK;
}
/**
* Invoked at the beginning of the functionHandler.
*/
virtual int enterFunction(Node *);
/**
* Invoked at the end of the functionHandler.
*/
virtual int exitFunction(Node *) {
return SWIG_OK;
}
/**
* Invoked by functionWrapper callback after call to Language::functionWrapper.
*/
virtual int emitWrapperFunction(Node *n);
/**
* Invoked from constantWrapper after call to Language::constantWrapper.
**/
virtual int emitConstant(Node *n);
/**
* Registers a given code snippet for a given key name.
*
* This method is called by the fragmentDirective handler
* of the JAVASCRIPT language module.
**/
int registerTemplate(const String *name, const String *code);
/**
* Retrieve the code template registered for a given name.
*/
Template getTemplate(const String *name);
State &amp;getState();
...
}</pre>
</div>
<p>The module calls <code>initialize</code>, <code>dump</code>, and <code>close</code> from within the <code>top</code> method:</p>
<div class="code">
<pre>
int JAVASCRIPT::top(Node *n) {
emitter-&gt;initialize(n);
Language::top(n);
emitter-&gt;dump(n);
emitter-&gt;close();
return SWIG_OK;
}</pre>
</div>
<p>The methods <code>enterClass</code> and <code>exitClass</code> are called from within the <code>classHandler</code> method:</p>
<div class="code">
<pre>
int JAVASCRIPT::classHandler(Node *n) {
emitter-&gt;enterClass(n);
Language::classHandler(n);
emitter-&gt;exitClass(n);
return SWIG_OK;
}</pre>
</div>
<p>In <code>enterClass</code> the emitter stores state information that is necessary when processing class members. In <code>exitClass</code> the wrapper code for the whole class is generated.</p>
<H3><a name="Javascript_emitter_states">27.5.4 Emitter states</a></H3>
<p>For storing information during the AST traversal the emitter provides a <code>JSEmitterState</code> with different slots to store data representing the scopes global, class, function, and variable.</p>
<div class="code">
<pre>
class JSEmitterState {
public:
JSEmitterState();
~JSEmitterState();
DOH *global();
DOH *global(const char* key, DOH *initial = 0);
DOH *clazz(bool reset = false);
DOH *clazz(const char* key, DOH *initial = 0);
DOH *function(bool reset = false);
DOH *function(const char* key, DOH *initial = 0);
DOH *variable(bool reset = false);
DOH *variable(const char* key, DOH *initial = 0);
static int IsSet(DOH *val);
...
};</pre>
</div>
<p>When entering a scope, such as in <code>enterClass</code>, the corresponding state is reset and new data is stored:</p>
<div class="code">
<pre>
state.clazz(RESET);
state.clazz(NAME, Getattr(n, "sym:name"));</pre>
</div>
<p>State information can be retrieved using <code>state.clazz(NAME)</code> or with <code>Getattr</code> on <code>state.clazz()</code> which actually returns a <code>Hash</code> instance.</p>
<H3><a name="Javascript_jsc_exceptions">27.5.5 Handling Exceptions in JavascriptCore</a></H3>
<p>Applications with an embedded JavascriptCore should be able to present detailed exception messages that occur in the Javascript engine. Below is an example derived from code provided by Brian Barnes on how these exception details can be extracted.</p>
<div class="code">
<pre>
void script_exception_to_string(JSContextRef js_context, JSValueRef exception_value_ref, char* return_error_string, int return_error_string_max_length)
{
JSObjectRef exception_object;
JSValueRef value_ref;
JSStringRef jsstring_property_name = NULL;
JSValueRef temporary_exception = NULL;
JSStringRef js_return_string = NULL;
size_t bytes_needed;
char* c_result_string = NULL;
exception_object = JSValueToObject(js_context, exception_value_ref, NULL);
/* source url */
strcpy(return_error_string, &quot;[&quot;);
jsstring_property_name = JSStringCreateWithUTF8CString(&quot;sourceURL&quot;);
value_ref = JSObjectGetProperty(js_context, exception_object, jsstring_property_name, &amp;temporary_exception);
JSStringRelease(jsstring_property_name);
js_return_string = JSValueToStringCopy(js_context, value_ref, NULL);
bytes_needed = JSStringGetMaximumUTF8CStringSize(js_return_string);
c_result_string = (char*)calloc(bytes_needed, sizeof(char));
JSStringGetUTF8CString(js_return_string, c_result_string, bytes_needed);
JSStringRelease(js_return_string);
strncat(return_error_string, c_result_string, return_error_string_max_length-1);
free(c_result_string);
strncat(return_error_string, &quot;:&quot;, return_error_string_max_length-1);
/* line number */
jsstring_property_name = JSStringCreateWithUTF8CString(&quot;line&quot;);
value_ref = JSObjectGetProperty(js_context, exception_object, jsstring_property_name, &amp;temporary_exception);
JSStringRelease(jsstring_property_name);
js_return_string = JSValueToStringCopy(js_context, value_ref, NULL);
bytes_needed = JSStringGetMaximumUTF8CStringSize(js_return_string);
c_result_string = (char*)calloc(bytes_needed, sizeof(char));
JSStringGetUTF8CString(js_return_string, c_result_string, bytes_needed);
JSStringRelease(js_return_string);
strncat(return_error_string, c_result_string, return_error_string_max_length-1);
free(c_result_string);
strncat(return_error_string, &quot;]&quot;, return_error_string_max_length-1);
/* error message */
jsstring_property_name = JSStringCreateWithUTF8CString(&quot;message&quot;);
value_ref = JSObjectGetProperty(js_context, exception_object, jsstring_property_name, &amp;temporary_exception);
JSStringRelease(jsstring_property_name);
if(NULL == value_ref)
{
strncat(return_error_string, &quot;Unknown Error&quot;, return_error_string_max_length-1);
}
else
{
js_return_string = JSValueToStringCopy(js_context, value_ref, NULL);
bytes_needed = JSStringGetMaximumUTF8CStringSize(js_return_string);
c_result_string = (char*)calloc(bytes_needed, sizeof(char));
JSStringGetUTF8CString(js_return_string, c_result_string, bytes_needed);
JSStringRelease(js_return_string);
strncat(return_error_string, c_result_string, return_error_string_max_length-1);
free(c_result_string);
}
}</pre>
</div>
<p>It would be used in the following way:</p>
<div class="code">
<pre>
if(js_exception)
{
char return_error_string[256];
script_exception_to_string(js_context, js_exception, return_error_string, 256);
printf("Compile error is %s", return_error_string);
}</pre>
</div>
</body>
</html>

2112
Doc/Manual/Library.html Normal file

File diff suppressed because it is too large Load Diff

604
Doc/Manual/Lisp.html Normal file
View File

@ -0,0 +1,604 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Common Lisp</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Lisp">29 SWIG and Common Lisp</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Lisp_nn3">Common Foreign Function Interface(CFFI)</a>
<ul>
<li><a href="#Lisp_nn4">Additional Commandline Options </a>
<li><a href="#Lisp_nn5">Generating CFFI bindings</a>
<li><a href="#Lisp_nn6">Generating CFFI bindings for C++ code</a>
<li><a href="#Lisp_nn7">Inserting user code into generated files</a>
</ul>
<ul>
<li><a href="#Lisp_nn9">Additional Commandline Options </a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
Common Lisp is a high-level, all-purpose, object-oriented,
dynamic, functional programming language with long history.
Common Lisp is used in many fields, ranging from web development to
finance, and also common in computer science education.
There are more than 9 different implementations of common lisp which
are available, all have different foreign function
interfaces. SWIG currently supports the
Common Foreign Function Interface(CFFI).
</p>
<H2><a name="Lisp_nn3">29.2 Common Foreign Function Interface(CFFI)</a></H2>
<p>
CFFI, the Common Foreign Function Interface, is a portable foreign
function interface for ANSI Common Lisp systems.
CFFI requires only a small set of
low-level functionality from the Lisp implementation, such as
calling a foreign function by name, allocating foreign memory,
and dereferencing pointers.
</p>
<p>
To run the cffi module of SWIG requires very little effort, you
just need to run:
</p>
<div class="code"><pre>
swig -cffi -module <i>module-name</i> <i>file-name</i>
</pre></div>
<p>
But a better was of using all the power of SWIG is to write SWIG
interface files. Below we will explain how to write interface
files and the various things which you can do with them.
</p>
<H3><a name="Lisp_nn4">29.2.1 Additional Commandline Options </a></H3>
<table summary="CFFI specific options">
<tr>
<th> CFFI specific options</th>
</tr>
<tr>
<td>-generate-typedef</td>
<td>If this option is given then defctype will be used to generate<br/>
shortcuts according to the typedefs in the input.
</td>
</tr>
<tr>
<td>-[no]cwrap</td>
<td>Turn on or turn off generation of an intermediate C file when<br/>
creating a C interface. By default this is only done for C++ code.
</td>
</tr>
<tr>
<td>-[no]swig-lisp</td>
<td>Turns on or off generation of code for helper lisp macro, functions,
etc. which SWIG uses while generating wrappers. These macros, functions
may still be used by generated wrapper code.
</td>
</tr>
</table>
<H3><a name="Lisp_nn5">29.2.2 Generating CFFI bindings</a></H3>
<p>
As we mentioned earlier the ideal way to use SWIG is to use interface
files. To illustrate the use of it, let's assume that we have a
file named <i>test.h</i> with the following C code:
</p>
<div class="code"><pre>
#define y 5
#define x (y &gt;&gt; 1)
typedef int days;
struct bar {
short p, q;
char a, b;
int *z[1000];
struct bar * n;
};
struct bar * my_struct;
struct foo {
int a;
struct foo * b[100];
};
int pointer_func(void (*ClosureFun)( void* _fun, void* _data, void* _evt ), int p);
int func123(div_t * p, int **q[100], int r[][1000][10]);
void lispsort_double (int n, double * array);
enum color { RED, BLUE, GREEN};
</pre></div>
<p>
Corresponding to this we will write a simple interface file:
</p>
<div class="code"><pre>
%module test
%include "test.h"
</pre></div>
<p>
The generated SWIG Code will be:
</p>
<div class="targetlang"><pre>
;;;SWIG wrapper code starts here
(cl:defmacro defanonenum (&amp;body enums)
"Converts anonymous enums to defconstants."
`(cl:progn , @(cl:loop for value in enums
for index = 0 then (cl:1+ index)
when (cl:listp value) do (cl:setf index (cl:second value)
value (cl:first value))
collect `(cl:defconstant , value , index))))
(cl:eval-when (:compile-toplevel :load-toplevel)
(cl:unless (cl:fboundp 'swig-lispify)
(cl:defun swig-lispify (name flag cl:&amp;optional (package cl:*package*))
(cl:labels ((helper (lst last rest cl:&amp;aux (c (cl:car lst)))
(cl:cond
((cl:null lst)
rest)
((cl:upper-case-p c)
(helper (cl:cdr lst) 'upper
(cl:case last
((lower digit) (cl:list* c #\- rest))
(cl:t (cl:cons c rest)))))
((cl:lower-case-p c)
(helper (cl:cdr lst) 'lower (cl:cons (cl:char-upcase c) rest)))
((cl:digit-char-p c)
(helper (cl:cdr lst) 'digit
(cl:case last
((upper lower) (cl:list* c #\- rest))
(cl:t (cl:cons c rest)))))
((cl:char-equal c #\_)
(helper (cl:cdr lst) '_ (cl:cons #\- rest)))
(cl:t
(cl:error "Invalid character: ~A" c)))))
(cl:let ((fix (cl:case flag
((constant enumvalue) "+")
(variable "*")
(cl:t ""))))
(cl:intern
(cl:concatenate
'cl:string
fix
(cl:nreverse (helper (cl:concatenate 'cl:list name) cl:nil cl:nil))
fix)
package))))))
;;;SWIG wrapper code ends here
(cl:defconstant y 5)
(cl:defconstant x (cl:ash 5 -1))
(cffi:defcstruct bar
(p :short)
(q :short)
(a :char)
(b :char)
(z :pointer)
(n :pointer))
(cffi:defcvar ("my_struct" my_struct)
:pointer)
(cffi:defcstruct foo
(a :int)
(b :pointer))
(cffi:defcfun ("pointer_func" pointer_func) :int
(ClosureFun :pointer)
(p :int))
(cffi:defcfun ("func123" func123) :int
(p :pointer)
(q :pointer)
(r :pointer))
(cffi:defcfun ("lispsort_double" lispsort_double) :void
(n :int)
(array :pointer))
(cffi:defcenum color
:RED
:BLUE
:GREEN)
</pre></div>
<p>
The <i>SWIG wrapper</i> code refers to the special code which SWIG
may need to use while wrapping C code. You can turn on/off the
generation of this code by using the <i>-[no]swig-lisp</i>
option. You must have noticed that SWIG goes one extra step to
ensure that CFFI does not do automatic lispification of the C
function names. The reason SWIG does this is because quite often
developers want to build a nice CLOS based lispy API, and this one
to one correspondence between C function names and lisp function
name helps.
</p>
<p> Maybe you want to have your own convention for generating lisp
function names for corresponding C function names, or you just
want to lispify the names, also, before we forget you want to
export the generated lisp names. To do this, we will use the
SWIG <a
href="Customization.html#Customization_features">feature directive</a>.
Let's edit the interface file such that the C type "div_t*" is changed
to Lisp type ":my-pointer", we lispify all names,
export everything, and do some more stuff.
</p>
<div class="code"><pre>
%module test
%typemap(cin) div_t* ":my-pointer";
%feature("intern_function", "1");
%feature("export");
%feature("inline") lispsort_double;
%feature("intern_function", "my-lispify") lispsort_double;
%feature("export", package="'some-other-package") lispsort_double;
%rename func123 renamed_cool_func;
%ignore "pointer_func";
%include "test.h"
</pre></div>
<p>
The <i>typemap(cin)</i> ensures that for all arguments which are input
to C with the type "div_t*", the ":my-pointer" type be
used. Similarly <i>typemap(cout)</i> are used for all types which
are returned from C.
</p>
<p>
The feature <i>intern_function</i> ensures that all C names are
interned using the <b>swig-lispify</b> function. The "1" given
to the feature is optional. The use of feature like
<i>%feature("intern_function", "1");</i> globally enables
interning for everything. If you want to target a single
function, or declaration then use the targeted version of
feature, <i>%feature("intern_function", "my-lispify")
lispsort_double;</i>, here we are using an additional feature
which allows us to use our lispify function.
</p>
<p>The <i>export</i> feature allows us to export the symbols. If
the <i>package</i> argument is given, then the symbol will be exported to
the specified Lisp package. The <i>inline</i> feature declaims the
declared function as inline. The <i>rename</i> directive allows us to
change the name(it is useful when generating C wrapper code for handling
overloaded functions). The <i>ignore</i> directive ignores a certain
declaration.
</p>
<p>There are several other things which are possible, to see some
example of usage of SWIG look at the Lispbuilder and wxCL
projects. The generated code with 'noswig-lisp' option is:
</p>
<div class="targetlang"><pre>
(cl:defconstant #.(swig-lispify "y" 'constant) 5)
(cl:export '#.(swig-lispify "y" 'constant))
(cl:defconstant #.(swig-lispify "x" 'constant) (cl:ash 5 -1))
(cl:export '#.(swig-lispify "x" 'constant))
(cffi:defcstruct #.(swig-lispify "bar" 'classname)
(#.(swig-lispify "p" 'slotname) :short)
(#.(swig-lispify "q" 'slotname) :short)
(#.(swig-lispify "a" 'slotname) :char)
(#.(swig-lispify "b" 'slotname) :char)
(#.(swig-lispify "z" 'slotname) :pointer)
(#.(swig-lispify "n" 'slotname) :pointer))
(cl:export '#.(swig-lispify "bar" 'classname))
(cl:export '#.(swig-lispify "p" 'slotname))
(cl:export '#.(swig-lispify "q" 'slotname))
(cl:export '#.(swig-lispify "a" 'slotname))
(cl:export '#.(swig-lispify "b" 'slotname))
(cl:export '#.(swig-lispify "z" 'slotname))
(cl:export '#.(swig-lispify "n" 'slotname))
(cffi:defcvar ("my_struct" #.(swig-lispify "my_struct" 'variable))
:pointer)
(cl:export '#.(swig-lispify "my_struct" 'variable))
(cffi:defcstruct #.(swig-lispify "foo" 'classname)
(#.(swig-lispify "a" 'slotname) :int)
(#.(swig-lispify "b" 'slotname) :pointer))
(cl:export '#.(swig-lispify "foo" 'classname))
(cl:export '#.(swig-lispify "a" 'slotname))
(cl:export '#.(swig-lispify "b" 'slotname))
(cffi:defcfun ("renamed_cool_func" #.(swig-lispify "renamed_cool_func" 'function)) :int
(p :my-pointer)
(q :pointer)
(r :pointer))
(cl:export '#.(swig-lispify "renamed_cool_func" 'function))
(cl:declaim (cl:inline #.(my-lispify "lispsort_double" 'function)))
(cffi:defcfun ("lispsort_double" #.(my-lispify "lispsort_double" 'function)) :void
(n :int)
(array :pointer))
(cl:export '#.(my-lispify "lispsort_double" 'function) 'some-other-package)
(cffi:defcenum #.(swig-lispify "color" 'enumname)
#.(swig-lispify "RED" 'enumvalue :keyword)
#.(swig-lispify "BLUE" 'enumvalue :keyword)
#.(swig-lispify "GREEN" 'enumvalue :keyword))
(cl:export '#.(swig-lispify "color" 'enumname))
</pre></div>
<H3><a name="Lisp_nn6">29.2.3 Generating CFFI bindings for C++ code</a></H3>
<p>This feature to SWIG (for CFFI) is very new and still far from
complete. Pitch in with your patches, bug reports and feature
requests to improve it.
</p>
<p> Generating bindings for C++ code, requires <i>-c++</i> option to be
present and it first generates C binding which will wrap the C++
code, and then generates the
corresponding CFFI wrapper code. In the generated C wrapper
code, you will often want to put your own C code, such as the
code to include various files. This can be done by making use of
"%{" and "%}" as shown below.
</p>
<div class="code"><pre>
%{
#include "Test/test.h"
%}
</pre></div>
<p>
Also, while parsing the C++ file and generating C wrapper code SWIG
may need to be able to understand various symbols used in other
header files. To help SWIG in doing this while ensuring that
wrapper code is generated for the target file, use the "import"
directive. The "include" directive specifies the target file for
which wrapper code will be generated.
</p>
<div class="code"><pre>
%import "ancillary/header.h"
%include "target/header.h"
</pre></div>
<p>
Various features which were available for C headers can also be used
here. The target header which we are going to use here is:
</p>
<div class="code"><pre>
namespace OpenDemo {
class Test
{
public:
float x;
// constructors
Test (void) {x = 0;}
Test (float X) {x = X;}
// vector addition
Test operator+ (const Test&amp; v) const {return Test (x+v.x);}
// length squared
float lengthSquared (void) const {return this-&gt;dot (*this);}
static float distance (const Test&amp; a, const Test&amp; b){return(a-b).length();}
inline Test parallelComponent (const Test&amp; unitBasis) const {
return unitBasis * projection;
}
Test setYtoZero (void) const {return Test (this-&gt;x);}
static const Test zero;
};
inline Test operator* (float s, const Test&amp; v) {return v*s;}
inline std::ostream&amp; operator&lt;&lt; (std::ostream&amp; o, const Test&amp; v)
{
return o &lt;&lt; "(" &lt;&lt; v.x &lt;&lt; ")";
}
inline Test RandomUnitVectorOnXZPlane (void)
{
return RandomVectorInUnitRadiusSphere().setYtoZero().normalize();
}
}
</pre></div>
<p>The interface used is: </p>
<div class="code"><pre>
%module test
%include "test.cpp"
</pre></div>
<p>
SWIG generates 3 files, the first one is a C wrap which we don't show,
the second is the plain CFFI wrapper which is as shown below:
</p>
<div class="targetlang"><pre>
(cffi:defcfun ("_wrap_Test_x_set" Test_x_set) :void
(self :pointer)
(x :float))
(cffi:defcfun ("_wrap_Test_x_get" Test_x_get) :float
(self :pointer))
(cffi:defcfun ("_wrap_new_Test__SWIG_0" new_Test) :pointer)
(cffi:defcfun ("_wrap_new_Test__SWIG_1" new_Test) :pointer
(X :float))
(cffi:defcfun ("_wrap_Test___add__" Test___add__) :pointer
(self :pointer)
(v :pointer))
(cffi:defcfun ("_wrap_Test_lengthSquared" Test_lengthSquared) :float
(self :pointer))
(cffi:defcfun ("_wrap_Test_distance" Test_distance) :float
(a :pointer)
(b :pointer))
(cffi:defcfun ("_wrap_Test_parallelComponent" Test_parallelComponent) :pointer
(self :pointer)
(unitBasis :pointer))
(cffi:defcfun ("_wrap_Test_setYtoZero" Test_setYtoZero) :pointer
(self :pointer))
(cffi:defcvar ("Test_zero" Test_zero)
:pointer)
(cffi:defcfun ("_wrap_delete_Test" delete_Test) :void
(self :pointer))
(cffi:defcfun ("_wrap___mul__" __mul__) :pointer
(s :float)
(v :pointer))
(cffi:defcfun ("_wrap___lshift__" __lshift__) :pointer
(o :pointer)
(v :pointer))
(cffi:defcfun ("_wrap_RandomUnitVectorOnXZPlane" RandomUnitVectorOnXZPlane) :pointer)
</pre></div>
<p>
The output is pretty good but it fails in disambiguating overloaded
functions such as the constructor, in this case. One way of
resolving this problem is to make the interface use the rename
directiv, but hopefully there are better solutions.
In addition SWIG also generates, a CLOS file
</p>
<div class="targetlang"><pre>
(clos:defclass test()
((ff :reader ff-pointer)))
(clos:defmethod (cl:setf x) (arg0 (obj test))
(Test_x_set (ff-pointer obj) arg0))
(clos:defmethod x ((obj test))
(Test_x_get (ff-pointer obj)))
(cl:shadow "+")
(clos:defmethod + ((obj test) (self test) (v test))
(Test___add__ (ff-pointer obj) (ff-pointer self) (ff-pointer v)))
(clos:defmethod length-squared ((obj test) (self test))
(Test_lengthSquared (ff-pointer obj) (ff-pointer self)))
(clos:defmethod parallel-component ((obj test) (self test) (unitBasis test))
(Test_parallelComponent (ff-pointer obj) (ff-pointer self) (ff-pointer unitBasis)))
(clos:defmethod set-yto-zero ((obj test) (self test))
(Test_setYtoZero (ff-pointer obj) (ff-pointer self)))
</pre></div>
<p>I agree that the CFFI C++ module needs lot more work. But I hope it
provides a starting point, on which you can base your work of
importing C++ libraries to Lisp.
</p>
<p>
If you have any questions, suggestions, patches, etc., related to CFFI
module feel free to contact us on the SWIG mailing list, and
also please add a "[CFFI]" tag in the subject line.
<H3><a name="Lisp_nn7">29.2.4 Inserting user code into generated files</a></H3>
<p>
It is often necessary to <a href="SWIG.html#SWIG_nn40">include user-defined code</a>
into the automatically generated interface files. For example, when building
a C++ interface, example_wrap.cxx will likely not compile unless
you add a <tt>#include "header.h"</tt> directive. This can be done
using the SWIG <tt>%insert(section) %{ ...code... %}</tt> directive:
</p>
<div class="code">
<pre>
%module example
%{
#include "header.h"
%}
%include "header.h"
int fact(int n);
</pre>
</div>
<p>
Additional sections have been added for inserting into the
generated lisp interface file:
</p>
<ul>
<li><tt>lisphead</tt> - inserts before type declarations</li>
<li><tt>swiglisp</tt> - inserts after type declarations according to
where it appears in the .i file</li>
</ul>
<p>
Note that the block <tt>%{ ... %}</tt> is effectively a shortcut for
<tt>%insert("header") %{ ... %}</tt>.
</p>
</body>
</html>

2018
Doc/Manual/Lua.html Normal file

File diff suppressed because it is too large Load Diff

97
Doc/Manual/Makefile Normal file
View File

@ -0,0 +1,97 @@
# Makefile for generating the SWIG documentation
#
# Note that the htmldoc package needs to be installed. wkhtmltopdf patched with qt is also required
# and can be installed from http://wkhtmltopdf.org/downloads.html.
#
# The .html files are first processed and updated with chapter numbering and anchor names
# are added to the HTML headings using the python scripts. The htmldoc program is then
# used to generate the single page HTML version of the documentation.
# wkhtmltopdf is used to generate the pdf document from the single page html file.
# HTML TIDY (package also known as tidy) is also required and is used as an aid to HTML
# validation.
#
# Additional html validation can be done using the validate target.
# Additional link checking can be done using the linkchecker1 and linkchecker2 target.
#
# Note the # and " are escaped
HTMLDOC_OPTIONS = "--book --toclevels 4 --no-numbered --toctitle \"Table of Contents\" --title --titleimage swig16.png --linkcolor \#0000ff --linkstyle underline --size Universal --left 0.50in --right 0.50in --top 0.50in --bottom 0.50in --header .t. --footer h.1 --nup 1 --tocheader .t. --tocfooter ..i --portrait --color --no-pscommands --no-xrxcomments --compression=1 --jpeg=0 --fontsize 10.0 --fontspacing 1.2 --headingfont Helvetica --bodyfont Times --headfootsize 10.0 --headfootfont Helvetica --charset iso-8859-1 --links --no-embedfonts --pagemode outline --pagelayout single --firstpage c1 --pageeffect none --pageduration 10 --effectduration 1.0 --no-encryption --permissions all --owner-password \"\" --user-password \"\" --browserwidth 680"
.PHONY: maketoc check generate all maintainer-clean validate test
all: maketoc check generate
maketoc:
python maketoc.py
# Use this to regenerate CCache.html should this ever be needed
CCache.html: ../../CCache/ccache.yo
yodl2html -o CCache.html ../../CCache/ccache.yo
# Tabs in the html files will stop the build as wkhtmltopdf does not expand them correctly - replace them with the appropriate number of tabs
# Use htmltidy to warn about some HTML errors. Note that it is not used to clean/tidy the HTML,
# it is just used as a primitive HTML checker.
# CCache.html is generated by yodl2html and has a few insignificant problems, so we don't put it through tidy
check:
all="index.html Sections.html `sed '/^#/d' chapters | grep -v CCache.html`" && for a in $$all; do echo "Check for tabs $$a" && if grep -P '\t' $$a; then echo "Please delete the tabs from the lines above" && exit 1; fi; done && for a in $$all; do echo "HTML tidy check $$a" && tidy -errors --gnu-emacs yes -quiet $$a; done;
# Note wkhtmltopdf limitations for generating pdf docs:
# 1) <H1><a name="X"></a>Text</H1> style links don't work and need changing to
# <H1><a name="X">Text</a></H1>
# 2) Tabs in <pre> elements should be expanded to 8 spaces by default, but
# are expanded to just one space and css tab-size is not working.
# 3) <pre> <tt> <code> elements do not always select a fixed-width font - try installing the
# Courier font to fix - these have been added to style.css.
generate: SWIGDocumentation.html
wkhtmltopdf --version | grep "with patched qt" || (echo "wkhtmltopdf is not the patched qt version and so cannot be used - download it from http://wkhtmltopdf.org/downloads.html" && false)
wkhtmltopdf --margin-top 20mm --margin-bottom 20mm --margin-left 10mm --margin-right 10mm --header-font-size 6 --footer-font-size 6 --header-spacing 6 --footer-spacing 6 --header-center '[doctitle]' --footer-left '[subsection]' --footer-right '[page]' SWIGDocumentation.html SWIGDocumentation.pdf
SWIGDocumentation.html: swightml.book
htmldoc --batch swightml.book || true
python fixstyle.py SWIGDocumentation.html
swightml.book: chapters Sections.html
echo "#HTMLDOC 1.8.24" > swightml.book
echo -t html -f SWIGDocumentation.html $(HTMLDOC_OPTIONS) >> swightml.book
echo "Sections.html" >> swightml.book
cat chapters >> swightml.book
maintainer-clean: clean-baks
rm -f swightml.book
rm -f SWIGDocumentation.html
rm -f SWIGDocumentation.pdf
rm -rf linkchecker-tmp
clean-baks:
rm -f *.bak
test:
grep "href=\".*\.html\"" index.html
grep "href=\".*\.html\"" Sections.html
all=`sed '/^#/d' chapters`; for a in $$all; do grep -l "href=\".*\.html\"" $$a; done;
# Validating using the WDG offline validator - http://www.htmlhelp.com/tools/validator/offline/
validate:
all=`sed '/^#/d' chapters`; for a in $$all; do validate --emacs $$a; done;
# Link checking using linkchecker of the index.html only file (including anchors)
linkchecker1:
@echo -----------------------------------------------------------------------
@echo Note linkchecker versions prior to 6.1 do not work properly wrt anchors
@echo -----------------------------------------------------------------------
linkchecker --config=./linkchecker.config --anchors index.html
# Check for links which don't work including those generated from the individual .html files into SWIGDocumentation.html
linkchecker2:
rm -rf linkchecker-tmp
mkdir linkchecker-tmp
cp SWIGDocumentation.html linkchecker-tmp
cp *.png linkchecker-tmp
(cd linkchecker-tmp && linkchecker --config=../linkchecker.config -F text --no-warnings SWIGDocumentation.html)
# Simple check for relative links (there shouldn't be any), they don't translate properly creating the .pdf doc
# with wkhtmltopdf. For example, href="SWIG.html" needs to be href="SWIG.html#SWIG"
linkchecker3:
@echo "The following list should just contain SWIGDocumentation.html and SWIGDocumentation.pdf,"
@echo "as all links should have an anchor (with a #) or be a full url beginning http."
grep 'href="' *.html | sed -e 's/.*href="\(.*\)">.*$$/\1/' | grep -v "#" | grep -v "^http" | grep -v "^style.css"

942
Doc/Manual/Modula3.html Normal file
View File

@ -0,0 +1,942 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Modula-3</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#FFFFFF">
<H1><a name="Modula3">31 SWIG and Modula-3</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Modula3_modula3_overview">Overview</a>
<ul>
<li><a href="#Modula3_motivation">Motivation</a>
</ul>
<li><a href="#Modula3_conception">Conception</a>
<ul>
<li><a href="#Modula3_cinterface">Interfaces to C libraries</a>
<li><a href="#Modula3_cppinterface">Interfaces to C++ libraries</a>
</ul>
<li><a href="#Modula3_preliminaries">Preliminaries</a>
<ul>
<li><a href="#Modula3_compilers">Compilers</a>
<li><a href="#Modula3_commandline">Additional Commandline Options</a>
</ul>
<li><a href="#Modula3_typemaps">Modula-3 typemaps</a>
<ul>
<li><a href="#Modula3_inoutparam">Inputs and outputs</a>
<li><a href="#Modula3_ordinals">Subranges, Enumerations, Sets</a>
<li><a href="#Modula3_class">Objects</a>
<li><a href="#Modula3_imports">Imports</a>
<li><a href="#Modula3_exceptions">Exceptions</a>
<li><a href="#Modula3_typemap_example">Example</a>
</ul>
<li><a href="#Modula3_hints">More hints to the generator</a>
<ul>
<li><a href="#Modula3_features">Features</a>
<li><a href="#Modula3_pragmas">Pragmas</a>
</ul>
<li><a href="#Modula3_remarks">Remarks</a>
</ul>
</div>
<!-- INDEX -->
<p>
This chapter describes SWIG's support for
<a href="http://modula3.org/">Modula-3</a>.
You should be familiar with the
<a href="SWIG.html#SWIG">basics</a>
of SWIG,
especially
<a href="Typemaps.html#Typemaps">typemaps</a>.
</p>
<H2><a name="Modula3_modula3_overview">31.1 Overview</a></H2>
<p>
Modula-3 is a compiled language in the tradition of Niklaus Wirth's Modula 2,
which is in turn a successor to Pascal.
</p>
<p>
SWIG's Modula-3 support is currently very basic and highly experimental!
Many features are still not designed satisfyingly
and I need more discussion about the odds and ends.
Don't rely on any feature, incompatible changes are likely in the future!
However, the Modula-3 generator was already useful for interfacing
to the libraries:
</p>
<ol>
<li>
<a href="http://www.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-libs/plplot/">
PLPlot
</a>
</li>
<li>
<a href="http://www.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-libs/fftw/">
FFTW
</a>
</li>
</ol>
<H3><a name="Modula3_motivation">31.1.1 Motivation</a></H3>
<p>
Although it is possible to write Modula-3 code that performs as well as C/C++
most existing libraries are not written in Modula-3 but in C or C++, and
even libraries in other languages may provide C header files.
</p>
<p>
Fortunately Modula-3 can call C functions, but you have to write Modula-3
interfaces to them, and to make things comfortable you will also need
wrappers that convert between high-level features of Modula-3 (garbage
collecting, exceptions) and the explicit tracking of allocated memory and
exception codes used by C APIs.
</p>
<p>
SWIG converts C headers to Modula-3 interfaces for you, and using typemaps
you can pass <tt>TEXT</tt>s or open arrays, and convert error return codes
into exceptions.
</p>
<p>
If the library API is ill designed
writing appropriate typemaps can still be time-consuming.
E.g. C programmers are very creative to work-around
missing data types like (real) enumerations and sets.
You should turn such work-arounds back to the Modula-3 way
otherwise you lose static safety and consistency.
</p>
<p>
Without SWIG you would probably never consider trying to call C++ libraries
from Modula-3, but with SWIG this is becomes feasible.
SWIG can generate C wrappers to C++ functions and object methods
that may throw exceptions, and then wrap these C wrappers for Modula-3.
To make it complete you can then hide the C interface with Modula-3 classes and
exceptions.
</p>
<p>
SWIG allows you to call C and C++ libraries from Modula-3 (even with call back
functions), but it doesn't allow you to easily integrate a Modula-3 module into
a C/C++ project.
</p>
<H2><a name="Modula3_conception">31.2 Conception</a></H2>
<H3><a name="Modula3_cinterface">31.2.1 Interfaces to C libraries</a></H3>
<p>
Modula-3 has integrated support for calling C functions.
This is also extensively used by the standard Modula-3 libraries
to call OS functions.
The Modula-3 part of SWIG and the corresponding SWIG library
modula3.swg
contain code that uses these features.
Because of the built-in support there is no need
for calling the SWIG kernel to generate wrappers written in C.
All conversion and argument checking can be done in Modula-3
and the interfacing is quite efficient.
All you have to do is to write pieces of Modula-3 code
that SWIG puts together.
</p>
<table border summary="Modula-3 C library support">
<tr><th colspan=2>C library support integrated in Modula-3<th></tr>
<tr>
<td>Pragma <tt>&lt;* EXTERNAL *&gt;</tt></td>
<td>Precedes a declaration of a PROCEDURE that is implemented
in an external library instead of a Modula-3 module.</td>
</tr>
<tr>
<td>Pragma <tt>&lt;* CALLBACK *&gt;</tt></td>
<td>Precedes a declaration of a PROCEDURE that should be called
by external library code.</td>
</tr>
<tr>
<td>Module <tt>Ctypes</tt></td>
<td>Contains Modula-3 types that match some basic C types.</td>
</tr>
<tr>
<td>Module <tt>M3toC</tt></td>
<td>Contains routines that convert between Modula-3's <tt>TEXT</tt> type
and C's <tt>char *</tt> type.</td>
</tr>
</table>
<p>
In each run of SWIG the Modula-3 part
generates several files:
</p>
<table border summary="Modula-3 generated files">
<tr>
<th>Module name scheme</th>
<th>Identifier for <tt>%insert</tt></th>
<th>Description</th>
</tr>
<tr>
<td>Module<tt>Raw.i3</tt></td>
<td><tt>m3rawintf</tt></td>
<td>Declaration of types that are equivalent to those of the C library,
<tt>EXTERNAL</tt> procedures as interface to the C library functions</td>
</tr>
<tr>
<td>Module<tt>Raw.m3</tt></td>
<td><tt>m3rawimpl</tt></td>
<td>Almost empty.</td>
</tr>
<tr>
<td>Module<tt>.i3</tt></td>
<td><tt>m3wrapintf</tt></td>
<td>Declaration of comfortable wrappers to the C library functions.</td>
</tr>
<tr>
<td>Module<tt>.m3</tt></td>
<td><tt>m3wrapimpl</tt></td>
<td>Implementation of the wrappers that
convert between Modula-3 and C types,
check for validity of values,
hand-over resource management to the garbage collector using <tt>WeakRef</tt>s
and raises exceptions.</td>
</tr>
<tr>
<td><tt>m3makefile</tt></td>
<td><tt>m3makefile</tt></td>
<td>Add the modules above to the Modula-3 project and
specify the name of the Modula-3 wrapper library
to be generated.
Today I'm not sure if it is a good idea
to create a <tt>m3makefile</tt> in each run,
because SWIG must be started for each Modula-3 module it creates.
Thus the m3makefile is overwritten each time. :-(
</td>
</tr>
</table>
<p>
Here's a scheme of how the function calls to Modula-3 wrappers
are redirected to C library functions:
</p>
<table summary="Modula-3 C library">
<tr>
<td align=center>
Modula-3 wrapper<br>
Module<tt>.i3</tt><br>
generated by Modula-3 part of SWIG
</td>
<td></td>
<td align=center></td>
</tr>
<tr>
<td align=center>
<!-- pre tag overrides centering -->
|<br>
v
</td>
<td></td>
<td align=center></td>
</tr>
<tr>
<td align=center>
Modula-3 interface to C<br>
Module<tt>Raw.i3</tt><br>
generated by Modula-3 part of SWIG
</td>
<td>--&gt;</td>
<td align=center>
C library
</td>
</tr>
</table>
<p>
I have still no good conception how one can split C library interfaces
into type oriented interfaces.
A Module in Modula-3 represents an Abstract DataType
(or call it a static classes, i.e. a class without virtual methods).
E.g. if you have a principal type, say <tt>Database</tt>,
it is good Modula-3 style to set up one Module with the name <tt>Database</tt>
where the database type is declared with the name <tt>T</tt>
and where all functions are declared that operates on it.
</p>
<p>
The normal operation of SWIG is to generate a fixed set of files per call.
To generate multiple modules one has to write one SWIG interface
(different SWIG interfaces can share common data) per module.
Identifiers belonging to a different module may ignored (<tt>%ignore</tt>)
and the principal type must be renamed (<tt>%typemap</tt>).
</p>
<H3><a name="Modula3_cppinterface">31.2.2 Interfaces to C++ libraries</a></H3>
<p>
Interfaces to C++ files are much more complicated and
there are some more design decisions that are not made, yet.
Modula-3 has no support for C++ functions
but C++ compilers should support generating C++ functions
with a C interface.
</p>
<p>
Here's a scheme of how the function calls to Modula-3 wrappers
are redirected to C library functions:
</p>
<table summary="Modula-3 C++ library">
<tr>
<td align=center>
Modula-3 wrapper<br>
Module<tt>.i3</tt><br>
generated by Modula-3 part of SWIG
</td>
<td></td>
<td align=center>C++ library</td>
</tr>
<tr>
<td align=center>
<!-- pre tag overrides centering -->
|<br>
v
</td>
<td></td>
<td align=center>
^<br>
|
</td>
</tr>
<tr>
<td align=center>
Modula-3 interface to C<br>
Module<tt>Raw.i3</tt><br>
generated by Modula-3 part of SWIG
</td>
<td>--&gt;</td>
<td align=center>
C interface to C++<br>
module<tt>_wrap.cxx</tt><br>
generated by the SWIG core
</td>
</tr>
</table>
<p>
Wrapping C++ libraries arises additional problems:
</p>
<ul>
<li>
Is it sensible to wrap C++ classes with Modula-3 classes?
</li>
<li>
How to find the wrapping Modula-3 class
for a class pointer that is returned by a C++ routine?
</li>
<li>
How to deal with multiple inheritance
which was neglected for Modula-3 for good reasons?
</li>
<li>
Is it possible to sub-class C++ classes with Modula-3 code?
This issue is addressed by directors,
a feature that was experimentally added to some Language modules
like
<a href="Java.html#Java_directors">Java</a> and
<a href="Python.html#Python_directors">Python</a>.
</li>
<li>
How to manage storage with the garbage collector of Modula-3?
Support for
<a href="Customization.html#Customization_ownership">
<tt>%newobject</tt> and <tt>%typemap(newfree)</tt></a>
isn't implemented, yet.
What's about resources that are managed by the garbage collector
but shall be passed back to the storage management of the C++ library?
This is a general issue which is not solved in a satisfying fashion
as far as I know.
</li>
<li>
How to turn C++ exceptions into Modula-3 exceptions?
There's also no support for
<a href="Customization.html#Customization_exception">
<tt>%exception</tt></a>, yet.
</li>
</ul>
<p>
Be warned:
There is no C++ library I wrote a SWIG interface for,
so I'm not sure if this is possible or sensible, yet.
</p>
<H2><a name="Modula3_preliminaries">31.3 Preliminaries</a></H2>
<H3><a name="Modula3_compilers">31.3.1 Compilers</a></H3>
<p>
There are different Modula-3 compilers around:
cm3, pm3, ezm3, Klagenfurth Modula-3, Cambridge Modula-3.
SWIG itself does not contain compiler specific code
but the modula3.swg library file
may do so.
For testing examples I use Critical Mass cm3.
</p>
<H3><a name="Modula3_commandline">31.3.2 Additional Commandline Options</a></H3>
<p>
There are some experimental command line options
that prevent SWIG from generating interface files.
Instead files are emitted that may assist you
when writing SWIG interface files.
</p>
<table border summary="Modula-3 specific options">
<tr>
<th>Modula-3 specific options</th>
<th>Description</th>
</tr>
<tr>
<td valign=top>-generateconst &lt;file&gt;</td>
<td>
Disable generation of interfaces and wrappers.
Instead write code for computing numeric values of constants
to the specified file.
<br>
C code may contain several constant definitions
written as preprocessor macros.
Other language modules of SWIG use
compute-once-use-readonly variables or
functions to wrap such definitions.
All of them can invoke C code dynamically
for computing the macro values.
But if one wants to turn them into Modula-3
integer constants, enumerations or set types,
the values of these expressions has to be known statically.
Although definitions like <tt>(1 &lt;&lt; FLAG_MAXIMIZEWINDOW)</tt>
must be considered as good C style
they are hard to convert to Modula-3
since the value computation can use every feature of C.
<br>
Thus I implemented these switch
to extract all constant definitions
and write a C program that output the values of them.
It works for numeric constants only
and treats all of them as <tt>double</tt>.
Future versions may generate a C++ program
that can detect the type of the macros
by overloaded output functions.
Then strings can also be processed.
</td>
</tr>
<tr>
<td valign=top>-generaterename &lt;file&gt;</td>
<td>
Disable generation of interfaces and wrappers.
Instead generate suggestions for <tt>%rename</tt>.
<br>
C libraries use a naming style
that is neither homogeneous nor similar to that of Modula-3.
C function names often contain a prefix denoting the library
and some name components separated by underscores
or capitalization changes.
To get library interfaces that are really Modula-3 like
you should rename the function names with the <tt>%rename</tt> directive.
This switch outputs a list of such directives
with a name suggestion generated by a simple heuristic.
</td>
</tr>
<tr>
<td valign=top>-generatetypemap &lt;file&gt;</td>
<td>
Disable generation of interfaces and wrappers.
Instead generate templates for some basic typemaps.
</td>
</tr>
</table>
<H2><a name="Modula3_typemaps">31.4 Modula-3 typemaps</a></H2>
<H3><a name="Modula3_inoutparam">31.4.1 Inputs and outputs</a></H3>
<p>
Each C procedure has a bunch of inputs and outputs.
Inputs are passed as function arguments,
outputs are updated referential arguments and
the function value.
</p>
<p>
Each C type can have several typemaps
that apply only in case if a type is used
for an input argument, for an output argument,
or for a return value.
A further typemap may specify
the direction that is used for certain parameters.
I have chosen this separation
in order to be able to write general typemaps for the modula3.swg typemap library.
In the library code the final usage of the type is not known.
Using separate typemaps for each possible use
allows appropriate definitions for each case.
If these pre-definitions are fine
then the direction of the function parameter
is the only hint the user must give.
</p>
<p>
The typemaps specific to Modula-3 have a common name scheme:
A typemap name starts with "m3",
followed by "raw" or "wrap"
depending on whether it controls the generation
of the Module<tt>Raw.i3</tt> or the Module<tt>.i3</tt>, respectively.
It follows an "in" for typemaps applied to input argument,
"out" for output arguments, "arg" for all kind of arguments,
"ret" for returned values.
</p>
<p>
The main task of SWIG is to build wrapper function,
i.e. functions that convert values between C and Modula-3
and call the corresponding C function.
Modula-3 wrapper functions generated by SWIG
consist of the following parts:
</p>
<ul>
<li>Generate <tt>PROCEDURE</tt> signature.</li>
<li>Declare local variables.</li>
<li>Convert input values from Modula-3 to C.</li>
<li>Check for input value integrity.</li>
<li>Call the C function.</li>
<li>Check returned values, e.g. error codes.</li>
<li>Convert and write back values into Modula-3 records.</li>
<li>Free temporary storage.</li>
<li>Return values.</li>
</ul>
<table border summary="Modula-3 typemaps">
<tr>
<th>Typemap</th>
<th>Example</th>
<th>Description</th>
</tr>
<tr>
<td>m3wrapargvar</td>
<td><tt>$1: INTEGER := $1_name;</tt></td>
<td>
Declaration of some variables needed for temporary results.
</td>
</tr>
<tr>
<td>m3wrapargconst</td>
<td><tt>$1 = "$1_name";</tt></td>
<td>
Declaration of some constant, maybe for debug purposes.
</td>
</tr>
<tr>
<td>m3wrapargraw</td>
<td><tt>ORD($1_name)</tt></td>
<td>
The expression that should be passed as argument to the raw Modula-3 interface function.
</td>
</tr>
<tr>
<td>m3wrapargdir</td>
<td><tt>out</tt></td>
<td>
Referential arguments can be used for input, output, update.
???
</td>
</tr>
<tr>
<td>m3wrapinmode</td>
<td><tt>READONLY</tt></td>
<td>
One of Modula-3 parameter modes
<tt>VALUE</tt> (or empty),
<tt>VAR</tt>,
<tt>READONLY</tt>
</td>
</tr>
<tr>
<td>m3wrapinname</td>
<td></td>
<td>
New name of the input argument.
</td>
</tr>
<tr>
<td>m3wrapintype</td>
<td></td>
<td>
Modula-3 type of the input argument.
</td>
</tr>
<tr>
<td>m3wrapindefault</td>
<td></td>
<td>
Default value of the input argument
</td>
</tr>
<tr>
<td>m3wrapinconv</td>
<td><tt>$1 := M3toC.SharedTtoS($1_name);</tt></td>
<td>
Statement for converting the Modula-3 input value to C compliant value.
</td>
</tr>
<tr>
<td>m3wrapincheck</td>
<td><tt>IF Text.Length($1_name) &gt; 10 THEN RAISE E("str too long"); END;</tt></td>
<td>
Check the integrity of the input value.
</td>
</tr>
<tr>
<td>m3wrapoutname</td>
<td></td>
<td>
Name of the <tt>RECORD</tt> field to be used for returning multiple values.
This applies to referential output arguments that shall be turned
into return values.
</td>
</tr>
<tr>
<td>m3wrapouttype</td>
<td></td>
<td>
Type of the value that is returned instead of a referential output argument.
</td>
</tr>
<tr>
<td>m3wrapoutconv</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapoutcheck</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretraw</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretname</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wraprettype</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretvar</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretconv</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretcheck</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapfreearg</td>
<td><tt>M3toC.FreeSharedS(str, arg1);</tt></td>
<td>
Free resources that were temporarily used in the wrapper.
Since this step should never be skipped,
SWIG will put it in the <tt>FINALLY</tt> branch
of a <tt>TRY .. FINALLY</tt> structure.
</td>
</tr>
</table>
<H3><a name="Modula3_ordinals">31.4.2 Subranges, Enumerations, Sets</a></H3>
<p>
Subranges, enumerations, and sets are machine oriented types
that make Modula very strong and expressive compared
with the type systems of many other languages.
</p>
<ul>
<li>
Subranges are used for statically restricted choices of integers.
</li>
<li>
Enumerations are used for named choices.
</li>
<li>
Sets are commonly used for flag (option) sets.
</li>
</ul>
<p>
Using them extensively makes Modula code very safe and readable.
</p>
<p>
C supports enumerations, too, but they are not as safe as the ones of Modula.
Thus they are abused for many things:
For named choices, for integer constant definitions, for sets.
To make it complete every way of defining a value in C
(<tt>#define</tt>, <tt>const int</tt>, <tt>enum</tt>)
is somewhere used for defining something
that must be handled completely different in Modula-3
(<tt>INTEGER</tt>, enumeration, <tt>SET</tt>).
</p>
<p>
I played around with several <tt>%feature</tt>s and <tt>%pragma</tt>s
that split the task up into converting
the C bit patterns (integer or bit set)
into Modula-3 bit patterns (integer or bit set)
and change the type as requested.
See the corresponding example in the
Examples/modula3/enum/example.i file.
This is quite messy and not satisfying.
So the best what you can currently do is
to rewrite constant definitions manually.
Though this is a tedious work
that I'd like to automate.
</p>
<H3><a name="Modula3_class">31.4.3 Objects</a></H3>
<p>
Declarations of C++ classes are mapped to <tt>OBJECT</tt> types
while it is tried to retain the access hierarchy
"public - protected - private" using partial revelation.
Though the example in
Examples/modula3/class/example.i
is not really useful, yet.
</p>
<H3><a name="Modula3_imports">31.4.4 Imports</a></H3>
<p>
Pieces of Modula-3 code provided by typemaps
may contain identifiers from foreign modules.
If the typemap <tt>m3wrapinconv</tt> for <tt>blah *</tt>
contains code using the function <tt>M3toC.SharedTtoS</tt>
you may declare <tt>%typemap("m3wrapinconv:import") blah * %{M3toC%}</tt>.
Then the module <tt>M3toC</tt> is imported
if the <tt>m3wrapinconv</tt> typemap for <tt>blah *</tt>
is used at least once.
Use <tt>%typemap("m3wrapinconv:import") blah * %{MyConversions AS M3toC%}</tt>
if you need module renaming.
Unqualified import is not supported.
</p>
<p>
It is cumbersome to add this typemap to each piece of Modula-3 code.
It is especially useful when writing general typemaps
for the modula3.swg typemap library.
For a monolithic module you might be better off
if you add the imports directly:
</p>
<div class="code">
<pre>
%insert(m3rawintf) %{
IMPORT M3toC;
%}
</pre></div>
<H3><a name="Modula3_exceptions">31.4.5 Exceptions</a></H3>
<p>
Modula-3 provides another possibility
of an output of a function: exceptions.
</p>
<p>
Any piece of Modula-3 code that SWIG inserts
due to a typemap can raise an exception.
This way you can also convert an error code
from a C function into a Modula-3 exception.
</p>
<p>
The <tt>RAISES</tt> clause is controlled
by typemaps with the <tt>throws</tt> extension.
If the typemap <tt>m3wrapinconv</tt> for <tt>blah *</tt>
contains code that may raise the exceptions <tt>OSError.E</tt>
you should declare
<tt>%typemap("m3wrapinconv:throws") blah * %{OSError.E%}</tt>.
</p>
<H3><a name="Modula3_typemap_example">31.4.6 Example</a></H3>
<p>
The generation of wrappers in Modula-3 needs very fine control
to take advantage of the language features.
Here is an example of a generated wrapper
where almost everything is generated by a typemap:
</p>
<div class="code"><pre>
<I> (* %relabel m3wrapinmode m3wrapinname m3wrapintype m3wrapindefault *)</I>
PROCEDURE Name (READONLY str : TEXT := "" )
<I> (* m3wrapoutcheck:throws *)</I>
: NameResult RAISES {E} =
CONST
arg1name = "str"; <I>(* m3wrapargconst *)</I>
VAR
arg0 : C.char_star; <I>(* m3wrapretvar *)</I>
arg1 : C.char_star; <I>(* m3wrapargvar *)</I>
arg2 : C.int;
result : RECORD
<I> (*m3wrapretname m3wraprettype*)</I>
unixPath : TEXT;
<I> (*m3wrapoutname m3wrapouttype*)</I>
checksum : CARDINAL;
END;
BEGIN
TRY
arg1 := M3toC.SharedTtoS(str); <I>(* m3wrapinconv *)</I>
IF Text.Length(arg1) &gt; 10 THEN <I>(* m3wrapincheck *)</I>
RAISE E("str too long");
END;
<I> (* m3wrapretraw m3wrapargraw *)</I>
arg0 := MessyToUnix (arg1, arg2);
result.unixPath := M3toC.CopyStoT(arg0); <I>(* m3wrapretconv *)</I>
result.checksum := arg2; <I>(* m3wrapoutconv *)</I>
IF result.checksum = 0 THEN <I>(* m3wrapoutcheck *)</I>
RAISE E("invalid checksum");
END;
FINALLY
M3toC.FreeSharedS(str, arg1); <I>(* m3wrapfreearg *)</I>
END;
END Name;
</pre></div>
<H2><a name="Modula3_hints">31.5 More hints to the generator</a></H2>
<H3><a name="Modula3_features">31.5.1 Features</a></H3>
<table border summary="Modula-3 features">
<tr>
<th>Feature</th>
<th>Example</th>
<th>Description</th>
</tr>
<tr>
<td>multiretval</td>
<td><tt>%m3multiretval get_box;</tt> or
<tt>%feature("modula3:multiretval") get_box;</tt></td>
<td>Let the denoted function return a <tt>RECORD</tt>
rather than a plain value.
This <tt>RECORD</tt> contains all arguments with "out" direction
including the return value of the C function (if there is one).
If more than one argument is "out"
then the function <b>must</b> have the <tt>multiretval</tt> feature activated,
but it is explicitly requested from the user to prevent mistakes.</td>
</tr>
<tr>
<td>constnumeric</td>
<td><tt>%constnumeric(12) twelve;</tt> or
<tt>%feature("constnumeric", "12") twelve;</tt></td>
<td>This feature can be used to tell Modula-3's back-end of SWIG
the value of an identifier.
This is necessary in the cases
where it was defined by a non-trivial C expression.
This feature is used by the
<tt>-generateconst</tt> <a href="#Modula3_commandline">option</a>.
In future it may be generalized to other kind of values
such as strings.
</td>
</tr>
</table>
<H3><a name="Modula3_pragmas">31.5.2 Pragmas</a></H3>
<table border summary="Modula-3 pragmas">
<tr>
<th>Pragma</th>
<th>Example</th>
<th>Description</th>
</tr>
<tr>
<td>unsafe</td>
<td><tt>%pragma(modula3) unsafe="true";</tt></td>
<td>Mark the raw interface modules as <tt>UNSAFE</tt>.
This will be necessary in many cases.</td>
</tr>
<tr>
<td>library</td>
<td><tt>%pragma(modula3) library="m3fftw";</tt></td>
<td>Specifies the library name for the wrapper library to be created.
It should be distinct from the name of the library to be wrapped.</td>
</tr>
</table>
<H2><a name="Modula3_remarks">31.6 Remarks</a></H2>
<ul>
<li>
The Modula-3 part of SWIG doesn't try to generate nicely formatted code.
If you need to read the generated code, use <tt>m3pp</tt> to postprocess the
Modula files.
</li>
</ul>
</body>
</html>

352
Doc/Manual/Modules.html Normal file
View File

@ -0,0 +1,352 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Working with Modules</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Modules">19 Working with Modules</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Modules_introduction">Modules Introduction</a>
<li><a href="#Modules_nn1">Basics</a>
<li><a href="#Modules_nn2">The SWIG runtime code</a>
<li><a href="#Modules_external_run_time">External access to the runtime</a>
<li><a href="#Modules_nn4">A word of caution about static libraries</a>
<li><a href="#Modules_nn5">References</a>
<li><a href="#Modules_nn6">Reducing the wrapper file size</a>
</ul>
</div>
<!-- INDEX -->
<H2><a name="Modules_introduction">19.1 Modules Introduction</a></H2>
<p>
Each invocation of SWIG requires a module name to be specified.
The module name is used to name the resulting target language extension module.
Exactly what this means and what the name is used for
depends on the target language, for example the name can define
a target language namespace or merely be a useful name for naming files or helper classes.
Essentially, a module comprises target language wrappers for a chosen collection of global variables/functions, structs/classes and other C/C++ types.
</p>
<p>
The module name can be supplied in one of two ways.
The first is to specify it with the special <tt>%module</tt>
directive. This directive must appear at the beginning of the interface file.
The general form of this directive is:
</p>
<div class="code"><pre>
<tt>%module(option1="value1", option2="value2", ...) modulename</tt>
</pre></div>
<p>
where the modulename is mandatory and the options add one or more optional additional features.
Typically no options are specified, for example:
</p>
<div class="code"><pre>
<tt>%module mymodule</tt>
</pre></div>
<p>
The second way to specify the module name is with the <tt>-module</tt> command line option, for example <tt>-module mymodule</tt>.
If the module name is supplied on the command line, it overrides the name specified by the
<tt>%module</tt> directive.
</p>
<p>
When first working with SWIG, users commonly start by creating a
single module. That is, you might define a single SWIG interface that
wraps some set of C/C++ code. You then compile all of the generated
wrapper code together and use it. For large applications, however,
this approach is problematic---the size of the generated wrapper code
can be rather large. Moreover, it is probably easier to manage the
target language interface when it is broken up into smaller pieces.
</p>
<p>
This chapter describes the problem of using SWIG in programs
where you want to create a collection of modules.
Each module in the collection is created via separate invocations of SWIG.
</p>
<H2><a name="Modules_nn1">19.2 Basics</a></H2>
<p>
The basic usage case with multiple modules is when modules do not have
cross-references (ie. when wrapping multiple independent C APIs). In that case,
swig input files should just work out of the box - you simply create multiple
wrapper .cxx files, link them into your application, and insert/load each in the
scripting language runtime as you would do for the single module case.
</p>
<p>
A bit more complex is the case in which modules need to share information.
For example, when one module extends the class of another by deriving from
it:
</p>
<div class="code"><pre>
// File: base.h
class base {
public:
int foo();
};
</pre></div>
&nbsp;
<div class="code"><pre>
// File: base_module.i
%module base_module
%{
#include "base.h"
%}
%include "base.h"
</pre></div>
&nbsp;
<div class="code"><pre>
// File: derived_module.i
%module derived_module
%import "base_module.i"
%inline %{
class derived : public base {
public:
int bar();
};
%}
</pre></div>
<p>To create the wrapper properly, module <tt>derived_module</tt> needs to know about the
<tt>base</tt> class and that its interface is covered in another module. The
line <tt>%import "base_module.i"</tt> lets SWIG know exactly that. Often
the <tt>.h</tt> file is passed to <tt>%import</tt> instead of the <tt>.i</tt>,
which unfortunately doesn't work for all language modules. For example, Python requires the
name of module that the base class exists in so that the proxy classes can fully inherit the
base class's methods. Typically you will get a warning when the module name is missing, eg:
</p>
<div class="shell"> <pre>
derived_module.i:8: Warning 401: Base class 'base' ignored - unknown module name for base. Either
import
the appropriate module interface file or specify the name of the module in the %import directive.
</pre></div>
<p>
It is sometimes desirable to import the header file rather than the interface file and overcome
the above warning.
For example in the case of the imported interface being quite large, it may be desirable to
simplify matters and just import a small header file of dependent types.
This can be done by specifying the optional <tt>module</tt> attribute in the <tt>%import</tt> directive.
The <tt>derived_module.i</tt> file shown above could be replaced with the following:
<div class="code"><pre>
// File: derived_module.i
%module derived_module
%import(module="base_module") "base.h"
%inline %{
class derived : public base {
public:
int bar();
};
</pre></div>
<p>
Note that "base_module" is the module name and is the same as that specified in <tt>%module</tt>
in <tt>base_module.i</tt> as well as the <tt>%import</tt> in <tt>derived_module.i</tt>.
</p>
<p>
Another issue
to beware of is that multiple dependent wrappers should not be linked/loaded
in parallel from multiple threads as SWIG provides no locking - for more on that
issue, read on.
</p>
<H2><a name="Modules_nn2">19.3 The SWIG runtime code</a></H2>
<p>
Many of SWIG's target languages generate a set of functions commonly known as
the "SWIG runtime." These functions are primarily related to the runtime type
system which checks pointer types and performs other tasks such as proper
casting of pointer values in C++. As a general rule, the statically typed target
languages, such as Java, use the language's built in static type checking and
have no need for a SWIG runtime. All the dynamically typed / interpreted
languages rely on the SWIG runtime.
</p>
<p>
The runtime functions are private to each SWIG-generated module. That is, the
runtime functions are declared with "static" linkage and are visible only to the
wrapper functions defined in that module. The only problem with this approach is
that when more than one SWIG module is used in the same application, those
modules often need to share type information. This is especially true for C++
programs where SWIG must collect and share information about inheritance
relationships that cross module boundaries.
</p>
<p>
To solve the problem of sharing information across modules, a pointer to the
type information is stored in a global variable in the target language
namespace. During module initialization, type information is loaded into the
global data structure of type information from all modules.
</p>
<p>
There are a few trade offs with this approach. This type information is global
across all SWIG modules loaded, and can cause type conflicts between modules
that were not designed to work together. To solve this approach, the SWIG
runtime code uses a define SWIG_TYPE_TABLE to provide a unique type table. This
behavior can be enabled when compiling the generated _wrap.cxx or _wrap.c file
by adding -DSWIG_TYPE_TABLE=myprojectname to the command line argument.
</p>
<p>
Then, only modules compiled with SWIG_TYPE_TABLE set to myprojectname will share
type information. So if your project has three modules, all three should be
compiled with -DSWIG_TYPE_TABLE=myprojectname, and then these three modules will
share type information. But any other project's types will not interfere or
clash with the types in your module.
</p>
<p>
Another issue relating to the global type table is thread safety. If two modules
try and load at the same time, the type information can become corrupt. SWIG
currently does not provide any locking, and if you use threads, you must make
sure that modules are loaded serially. Be careful if you use threads and the
automatic module loading that some scripting languages provide. One solution is
to load all modules before spawning any threads, or use SWIG_TYPE_TABLE to
separate type tables so they do not clash with each other.
</p>
<p>
Lastly, SWIG uses a #define SWIG_RUNTIME_VERSION, located in Lib/swigrun.swg and
near the top of every generated module. This number gets incremented when the
data structures change, so that SWIG modules generated with different versions
can peacefully coexist. So the type structures are separated by the
(SWIG_TYPE_TABLE, SWIG_RUNTIME_VERSION) pair, where by default SWIG_TYPE_TABLE
is empty. Only modules compiled with the same pair will share type information.
</p>
<H2><a name="Modules_external_run_time">19.4 External access to the runtime</a></H2>
<p>As described in <a href="Typemaps.html#Typemaps_runtime_type_checker">The run-time type checker</a>,
the functions <tt>SWIG_TypeQuery</tt>, <tt>SWIG_NewPointerObj</tt>, and others sometimes need
to be called. Calling these functions from a typemap is supported, since the typemap code
is embedded into the <tt>_wrap.c</tt> file, which has those declarations available. If you need
to call the SWIG run-time functions from another C file, there is one header you need
to include. To generate the header that needs to be included, SWIG can be run in a different
mode via <tt>-external-runtime</tt> to generate the run-time instead of the normal mode of
processing an input interface file. For example:
<div class="shell"><pre>
$ swig -python -external-runtime &lt;filename&gt;
</pre></div>
<p>The filename argument is optional and if it is not passed, then the default filename will
be something like <tt>swigpyrun.h</tt>, depending on the language. This header file should
be treated like any of the other _wrap.c output files, and should be regenerated when the
_wrap files are. After including this header, your code will be able to call <tt>SWIG_TypeQuery</tt>,
<tt>SWIG_NewPointerObj</tt>, <tt>SWIG_ConvertPtr</tt> and others. The exact argument parameters
for these functions might differ between language modules; please check the language module chapters
for more information.</p>
<p>Inside this header the functions are declared static and are included inline into the file,
and thus the file does not need to be linked against any SWIG libraries or code (you might still
need to link against the language libraries like libpython-2.3). Data is shared between this
file and the _wrap.c files through a global variable in the scripting language. It is also
possible to copy this header file along with the generated wrapper files into your own package,
so that you can distribute a package that can be compiled without SWIG installed (this works
because the header file is self-contained, and does not need to link with anything).</p>
<p>
This header will also use the -DSWIG_TYPE_TABLE described above, so when
compiling any code which includes the generated header file should define the
SWIG_TYPE_TABLE to be the same as the module whose types you are trying to
access.
</p>
<H2><a name="Modules_nn4">19.5 A word of caution about static libraries</a></H2>
<p>
When working with multiple SWIG modules, you should take care not to use static
libraries. For example, if you have a static library <tt>libfoo.a</tt> and you link a collection
of SWIG modules with that library, each module will get its own private copy of the library code inserted
into it. This is very often <b>NOT</b> what you want and it can lead to unexpected or bizarre program
behavior. When working with dynamically loadable modules, you should try to work exclusively with shared libraries.
</p>
<H2><a name="Modules_nn5">19.6 References</a></H2>
<p>
Due to the complexity of working with shared libraries and multiple modules, it might be a good idea to consult
an outside reference. John Levine's "Linkers and Loaders" is highly recommended.
</p>
<H2><a name="Modules_nn6">19.7 Reducing the wrapper file size</a></H2>
<p>
Using multiple modules with the <tt>%import</tt> directive is the most common approach to modularising large projects.
In this way a number of different wrapper files can be generated, thereby avoiding the generation of a single large wrapper file.
There are a couple of alternative solutions for reducing the size of a wrapper file through the use of command line options and features.
</p>
<p>
<b>-fcompact</b><br>
This command line option will compact the size of the wrapper file without changing the code generated into the wrapper file.
It simply removes blank lines and joins lines of code together.
This is useful for compilers that have a maximum file size that can be handled.
</p>
<p>
<b>-fvirtual</b><br>
This command line option will remove the generation of superfluous virtual method wrappers.
Consider the following inheritance hierarchy:
</p>
<div class="code">
<pre>
struct Base {
virtual void method();
...
};
struct Derived : Base {
virtual void method();
...
};
</pre>
</div>
<p>
Normally wrappers are generated for both methods, whereas this command line option will suppress the generation of a wrapper for <tt>Derived::method</tt>.
Normal polymorphic behaviour remains as <tt>Derived::method</tt> will still be called should you have
a <tt>Derived</tt> instance and call the wrapper for <tt>Base::method</tt>.
</p>
<p>
<b>%feature("compactdefaultargs")</b><br>
This feature can reduce the number of wrapper methods when wrapping methods with default arguments. The section on <a href="SWIGPlus.html#SWIGPlus_default_args">default arguments</a> discusses the feature and its limitations.
</p>
</body>
</html>

181
Doc/Manual/Mzscheme.html Normal file
View File

@ -0,0 +1,181 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and MzScheme/Racket</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Mzscheme">37 SWIG and MzScheme/Racket</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#MzScheme_nn2">Creating native structures</a>
<li><a href="#MzScheme_simple">Simple example</a>
<li><a href="#MzScheme_external_docs">External documentation</a>
</ul>
</div>
<!-- INDEX -->
<p>
This section contains information on SWIG's support of Racket, formally known as MzScheme.
<H2><a name="MzScheme_nn2">37.1 Creating native structures</a></H2>
<p>
Example interface file:
</p>
<div class="code">
<pre>
/* define a macro for the struct creation */
%define handle_ptr(TYPE, NAME)
%typemap(argout) TYPE *NAME{
Scheme_Object *o = SWIG_NewStructFromPtr($1, $*1_mangle);
SWIG_APPEND_VALUE(o);
}
%typemap(in, numinputs=0) TYPE *NAME (TYPE temp) {
$1 = &amp;temp;
}
%enddef
/* setup the typemaps for the pointer to an output parameter cntrs */
handle_ptr(struct diag_cntrs, cntrs);
</pre>
</div>
<p>
Then in scheme, you can use regular struct access procedures like
</p>
<div class="code">
<pre>
; suppose a function created a struct foo as
; (define foo (make-diag-cntrs (#x1 #x2 #x3) (make-inspector))
; Then you can do
(format "0x~x" (diag-cntrs-field1 foo))
(format "0x~x" (diag-cntrs-field2 foo))
;etc...
</pre>
</div>
<H2><a name="MzScheme_simple">37.2 Simple example</a></H2>
<p>
A few examples are available in the Examples/mzscheme directory.
The code and log of a session using SWIG below should help getting started.
</p>
<p>
C header file:
</p>
<div class="code">
<pre>
// example.h
int fact(int n);
</pre>
</div>
<p>
C source code:
</p>
<div class="code">
<pre>
// File: example.c
#include "example.h"
int fact(int n) {
if (n &lt; 0) { /* This should probably return an error, but this is simpler */
return 0;
}
if (n == 0) {
return 1;
}
else {
/* testing for overflow would be a good idea here */
return n * fact(n-1);
}
}
</pre>
</div>
<p>
SWIG interface file:
</p>
<div class="code">
<pre>
/* File: example.i */
%module example
%{
#include "example.h"
%}
int fact(int n);
</pre>
</div>
<p>
The session below using the above files is on an OS X machine, but the points to be made are more general. On OS X, libtool is the tool which creates libraries, which are named .dylib, rather than .so on other unixes, or .dll on Windows.
</p>
<div class="shell">
<pre>
% swig -mzscheme -declaremodule example.i
% gcc -c -m32 -o example.o example.c # force 32-bit object file (mzscheme is 32-bit only)
% libtool -dynamic -o libexample.dylib example.o # make it into a library
% ls # what've we got so far?
example.c example.o
example.h example_wrap.c
example.i libexample.dylib*
% mzc --cgc --cc example_wrap.c # compile the wrapping code
% LDFLAGS="-L. -lexample" mzc --ld example_wrap.dylib example_wrap.o # ...and link it
% mzscheme -e '(path-&gt;string (build-path "compiled" "native" (system-library-subpath)))'
"compiled/native/i386-macosx/3m"
% mkdir -p compiled/native/i386-macosx/3m # move the extension library to a magic place
% mv example_wrap.dylib compiled/native/i386-macosx/3m/example_ss.dylib
% mzscheme
Welcome to MzScheme v4.2.4 [3m], Copyright (c) 2004-2010 PLT Scheme Inc.
&gt; (require "example.ss")
&gt; (fact 5)
120
&gt; ^D
% echo 'It works!'
</pre>
</div>
<p>
Some points of interest:
</p>
<ul>
<li> This is on a 64-bit machine, so we have to include the -m32 option when building the object file
<li> If you want to declare a scheme module (and you probably do), it's important that you include the -declaremodule option to swig (if you miss this out, it'll appear to work, but fail later).
<li> Use mzc to compile and then link the wrapped code. You'll probably need to adjust the link flags to refer to the library you're wrapping (you can either do this with an LDFLAGS declaration, as here, or with multiple ++ldf options to mzc).
<li> Create the directory with path (build-path "compiled" "native" (system-library-subpath)) and move the freshly-generated .dylib to there, changing its name to module-name_ss.dylib. After that, you can REQUIRE the new module with (require "module-name.ss").
<li> The above requests mzc to create an extension using the CGC garbage-collector. The alternative -- the 3m collector -- has generally better performance, but work is still required for SWIG to emit code which is compatible with it.
</ul>
<H2><a name="MzScheme_external_docs">37.3 External documentation</a></H2>
<p>
See the <a href="https://docs.racket-lang.org/inside/index.html">C API</a> for more description of using the mechanism for adding extensions. The main documentation is <a href="https://docs.racket-lang.org/">here</a>.
</p>
<p>
Tip: mzc's --vv option is very useful for debugging the inevitable library problems you'll encounter.
</p>
</body>
</html>

1120
Doc/Manual/Ocaml.html Normal file

File diff suppressed because it is too large Load Diff

909
Doc/Manual/Octave.html Normal file
View File

@ -0,0 +1,909 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Octave</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Octave">29 SWIG and Octave</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Octave_nn2">Preliminaries</a>
<li><a href="#Octave_nn3">Running SWIG</a>
<ul>
<li><a href="#Octave_nn4">Command-line options</a>
<li><a href="#Octave_nn5">Compiling a dynamic module</a>
<li><a href="#Octave_nn6">Using your module</a>
</ul>
<li><a href="#Octave_nn7">A tour of basic C/C++ wrapping</a>
<ul>
<li><a href="#Octave_nn8">Modules</a>
<li><a href="#Octave_nn9">Functions</a>
<li><a href="#Octave_nn10">Global variables</a>
<li><a href="#Octave_nn11">Constants and enums</a>
<li><a href="#Octave_nn12">Pointers</a>
<li><a href="#Octave_nn13">Structures and C++ classes</a>
<li><a href="#Octave_nn15">C++ inheritance</a>
<li><a href="#Octave_nn17">C++ overloaded functions</a>
<li><a href="#Octave_nn18">C++ operators</a>
<li><a href="#Octave_nn19">Class extension with %extend</a>
<li><a href="#Octave_nn20">C++ templates</a>
<li><a href="#Octave_nn21">C++ Smart Pointers</a>
<ul>
<li><a href="#Octave_smart_pointers_shared_ptr">The shared_ptr Smart Pointer</a>
<li><a href="#Octave_smart_pointers_generic">Generic Smart Pointers</a>
</ul>
<li><a href="#Octave_nn22">Directors (calling Octave from C++ code)</a>
<li><a href="#Octave_nn23">Threads</a>
<li><a href="#Octave_nn24">Memory management</a>
<li><a href="#Octave_nn25">STL support</a>
<li><a href="#Octave_nn26">Matrix typemaps</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
Octave is a high-level language intended for numerical programming that is mostly compatible with MATLAB.
More information can be found at <a href="http://www.gnu.org/software/octave/">Octave web site</a>.
</p>
<p>
This chapter is intended to give an introduction to using the module. You should also read the SWIG documentation that is not specific to Octave.
Also, there are a dozen or so examples in the Examples/octave directory, and hundreds in the test suite (Examples/test-suite and Examples/test-suite/octave).
</p>
<H2><a name="Octave_nn2">29.1 Preliminaries</a></H2>
<p>
SWIG is regularly tested against the following versions of Octave: 3.8, 4.0, 4.2.
</p>
<p>
Every effort is made to maintain backward compatibility with older versions of Octave.
This cannot be guaranteed however, as in recent times new Octave releases have required nontrivial updates to SWIG, which may break backward compatibility for older Octave versions against which SWIG is not regularly tested.
</p>
<p>
The SWIG runtime exports the function <tt>swig_octave_prereq()</tt> for checking the version of Octave.
</p>
<H2><a name="Octave_nn3">29.2 Running SWIG</a></H2>
<p>
Let's start with a very simple SWIG interface file, example.i:
</p>
<div class="code"><pre>
%module swigexample
%{
#include "example.h"
%}
int gcd(int x, int y);
extern double Foo; </pre></div>
<p>
To build an Octave module when wrapping C code, run SWIG using the <tt>-octave</tt> option:
</p>
<div class="shell"><pre>$ swig -octave -o example_wrap.cpp example.i </pre></div>
<p>
The <tt>-c++</tt> option is also required when wrapping C++ code:
</p>
<div class="shell"><pre>$ swig -octave -c++ -o example_wrap.cpp example.i </pre></div>
<p>
This creates a C++ source file "example_wrap.cpp". A C++ file is generated even when wrapping C code as Octave is itself written in C++ and requires wrapper code to be in the same language. The generated C++ source file contains the low-level wrappers that need to be compiled and linked with the rest of your C/C++ application (in this case, the gcd implementation) to create an extension module.
</p>
<H3><a name="Octave_nn4">29.2.1 Command-line options</a></H3>
<p>
The swig command line has a number of options you can use, like to redirect its output. Use <tt>swig -help</tt> to learn about these.
Options specific to the Octave module are:
</p>
<div class="shell">
<pre>$ swig -octave -help
...
Octave Options (available with -octave)
-globals <em>name</em> - Set <em>name</em> used to access C global variables [default: 'cvar']
Use '.' to load C global variables into module namespace
-opprefix <em>str</em> - Prefix <em>str</em> for global operator functions [default: 'op_']
</pre></div>
<p>
The <em>-globals</em> option sets the name of the variable which is the namespace for C global variables exported by the module.
The special name "." loads C global variables into the module namespace, i.e. alongside C functions and structs exported by the module.
The <em>-opprefix</em> options sets the prefix of the names of global/friend <a href="#Octave_nn18">operator</a> functions.
</p>
<H3><a name="Octave_nn5">29.2.2 Compiling a dynamic module</a></H3>
<p>
Octave modules are DLLs/shared objects having the ".oct" suffix.
Building an oct file is usually done with the mkoctfile command (either within Octave itself, or from the shell). For example,
</p>
<div class="shell"><pre>
$ swig -octave -c++ -o example_wrap.cpp example.i
$ mkoctfile example_wrap.cpp example.c
</pre></div>
<p>
where "example.c" is the file containing the gcd() implementation.
</p>
<p>
mkoctfile can also be used to extract the build parameters required to invoke the compiler and linker yourself. See the Octave manual and mkoctfile man page.
</p>
<p>
mkoctfile will produce "swigexample.oct", which contains the compiled extension module. Loading it into Octave is then a matter of invoking
</p>
<div class="targetlang"><pre>octave:1&gt; swigexample</pre></div>
<H3><a name="Octave_nn6">29.2.3 Using your module</a></H3>
<p>
Assuming all goes well, you will be able to do this:
<br>
</p>
<div class="targetlang"><pre>$ octave -q
octave:1&gt; swigexample
octave:2&gt; swigexample.gcd(4, 6)
ans = 2
octave:3&gt; swigexample.cvar.Foo
ans = 3
octave:4&gt; swigexample.cvar.Foo=4;
octave:5&gt; swigexample.cvar.Foo
ans = 4 </pre></div>
<H2><a name="Octave_nn7">29.3 A tour of basic C/C++ wrapping</a></H2>
<H3><a name="Octave_nn8">29.3.1 Modules</a></H3>
<p>
The SWIG module directive specifies the name of the Octave module. If you specify "module swigexample", then in Octave everything in the module will be accessible under "swigexample", as in the above example. When choosing a module name, make sure you don't use the same name as a built-in Octave command or standard module name.
</p>
<p>
When Octave is asked to invoke <tt>swigexample</tt>, it will try to find the ".m" or ".oct" file that defines the function "swigexample". You therefore need to make sure that "swigexample.oct" is in Octave's search path, which can be specified with the environment variable "OCTAVE_PATH".
</p>
<p>
To load an Octave module, simply type its name:
</p>
<div class="targetlang"><pre>
octave:1&gt; swigexample;
octave:2&gt; gcd(4, 6)
ans = 2
octave:3&gt; cvar.Foo
ans = 3
octave:4&gt; cvar.Foo=4;
octave:5&gt; cvar.Foo
ans = 4
</pre></div>
<p>
Modules can also be loaded from within functions, even before being loaded in the base context.
If the module is also used in the base context, however, it must first be loaded again:
</p>
<div class="targetlang"><pre>
octave:1&gt; function l = my_lcm(a, b)
&gt; swigexample
&gt; l = abs(a*b)/swigexample.gcd(a, b);
&gt; endfunction
octave:2&gt; my_lcm(4, 6)
ans = 12
octave:3&gt; swigexample.gcd(4, 6)
error: can't perform indexing operations for &lt;unknown type&gt; type
octave:3&gt; swigexample;
octave:4&gt; swigexample.gcd(4, 6)
ans = 2
</pre></div>
<H3><a name="Octave_nn9">29.3.2 Functions</a></H3>
<p>
Global functions are wrapped as new Octave built-in functions. For example,
</p>
<div class="code"><pre>&#037;module swigexample
int fact(int n); </pre></div>
<p>
creates a built-in function <tt>swigexample.fact(n)</tt> that works exactly like you think it does:
</p>
<div class="targetlang"><pre>octave:1&gt; swigexample.fact(4)
24 </pre></div>
<H3><a name="Octave_nn10">29.3.3 Global variables</a></H3>
<p>
Global variables are a little special in Octave. Given a global variable:
</p>
<div class="code"><pre>%module swigexample
extern double Foo;
</pre></div>
<p>
To expose variables, SWIG actually generates two functions, to get and set the value. In this case, Foo_set and Foo_set would be generated. SWIG then automatically calls these functions when you get and set the variable-- in the former case creating a local copy in the interpreter of the C variables, and in the latter case copying an interpreter variables onto the C variable.
</p>
<div class="targetlang"><pre>octave:1&gt; swigexample;
octave:2&gt; c=swigexample.cvar.Foo
c = 3
octave:3&gt; swigexample.cvar.Foo=4;
octave:4&gt; c
c = 3
octave:5&gt; swigexample.cvar.Foo
ans = 4</pre></div>
<p>
If a variable is marked with the %immutable directive then any attempts to set this variable will cause an Octave error. Given a global variable:
</p>
<div class="code"><pre>%module swigexample
%immutable;
extern double Foo;
%mutable;
</pre></div>
<p>
SWIG will allow the reading of <tt>Foo</tt> but when a set attempt is made, an error function will be called.
</p>
<div class="targetlang"><pre>octave:1&gt; swigexample
octave:2&gt; swigexample.Foo=4
error: attempt to set immutable member variable
error: assignment failed, or no method for `swig_type = scalar'
error: evaluating assignment expression near line 2, column 12 </pre></div>
<p>
It is possible to add new functions or variables to the module. This also allows the user to rename/remove existing functions and constants (but not linked variables, mutable or immutable). Therefore users are recommended to be careful when doing so.
</p>
<div class="targetlang"><pre>octave:1&gt; swigexample;
octave:2&gt; swigexample.PI=3.142;
octave:3&gt; swigexample.PI
ans = 3.1420 </pre></div>
<H3><a name="Octave_nn11">29.3.4 Constants and enums</a></H3>
<p>
Because Octave doesn't really have the concept of constants, C/C++ constants are not really constant in Octave. They are actually just a copy of the value into the Octave interpreter. Therefore they can be changed just as any other value. For example given some constants:
</p>
<div class="code"><pre>%module swigexample
%constant int ICONST=42;
#define SCONST "Hello World"
enum Days{SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
</pre></div>
<p>
This is 'effectively' converted into the following Octave code:
</p>
<div class="targetlang"><pre>swigexample.ICONST=42
swigexample.SCONST="Hello World"
swigexample.SUNDAY=0
.... </pre></div>
<H3><a name="Octave_nn12">29.3.5 Pointers</a></H3>
<p>
C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the &lt;file.h&gt; interface:
C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the &lt;file.h&gt; interface:
</p>
<div class="code"><pre>%module swigexample
FILE *fopen(const char *filename, const char *mode);
int fputs(const char *, FILE *);
int fclose(FILE *);
</pre></div>
<p>
When wrapped, you will be able to use the functions in a natural way from Octave. For example:
</p>
<div class="targetlang"><pre>
octave:1&gt; swigexample;
octave:2&gt; f=swigexample.fopen("w", "junk");
octave:3&gt; swigexample.fputs("Hello world", f);
octave:4&gt; swigexample.fclose(f);
</pre></div>
<p>
Simply printing the value of a wrapped C++ type will print its typename. E.g.,
</p>
<div class="targetlang"><pre>octave:1&gt; swigexample;
octave:2&gt; f=swigexample.fopen("junk", "w");
octave:3&gt; f
f =
{
_p_FILE, ptr = 0x9b0cd00
} </pre></div>
<p>
As the user of the pointer, you are responsible for freeing it, or closing any resources associated with it (just as you would in a C program). This does not apply so strictly to classes and structs (see below).
</p>
<div class="targetlang"><pre>octave:1&gt; swigexample;
octave:2&gt; f=swigexample.fopen("not there", "r");
error: value on right hand side of assignment is undefined
error: evaluating assignment expression near line 2, column 2 </pre></div>
<H3><a name="Octave_nn13">29.3.6 Structures and C++ classes</a></H3>
<p>
SWIG wraps C structures and C++ classes by using a special Octave type called a <tt>swig_ref</tt>. A <tt>swig_ref</tt> contains a reference to one or more instances of C/C++ objects, or just the type information for an object.
For each wrapped structure and class, a <tt>swig_ref</tt> will be exposed that has the name of the type. When invoked as a function, it creates a new object of its type and returns a <tt>swig_ref</tt> that points to that instance. This provides a very natural interface. For example,
</p>
<div class="code"><pre>struct Point{
int x, y;
};
</pre></div>
<p>
is used as follows:
</p>
<div class="targetlang">
<pre>octave:1&gt; swigexample;
octave:2&gt; p=swigexample.Point();
octave:3&gt; p.x=3;
octave:4&gt; p.y=5;
octave:5&gt; p.x, p.y
ans = 3
ans = 5
</pre></div>
<p>
In C++, invoking the type object in this way calls the object's constructor.
<tt>swig_ref</tt> objects can also be acquired by having a wrapped function return a pointer, reference, or value of a non-primitive type.
</p>
<p>
The swig_ref type handles indexing operations such that usage maps closely to what you would have in C/C++.
Structure members are accessed as in the above example, by calling set and get methods for C++ variables.
Methods also work as expected. For example, code wrapped in the following way
</p>
<div class="code"><pre>class Point{
public:
int x, y;
Point(int _x, int _y) : x(_x), y(_y) {}
double distance(const Point&amp; rhs) {
return sqrt(pow(x-rhs.x, 2)+pow(y-rhs.y, 2));
}
void set(int _x, int _y) {
x=_x; y=_y;
}
};
</pre></div>
<p>
can be used from Octave like this
</p>
<div class="targetlang">
<pre>octave:1&gt; swigexample;
octave:2&gt; p1=swigexample.Point(3, 5);
octave:3&gt; p2=swigexample.Point(1, 2);
octave:4&gt; p1.distance(p2)
ans = 3.6056
</pre></div>
<p>
By using the <tt>swig_this()</tt> and <tt>swig_type()</tt> functions, one can discover the pointers to and types of the underlying C/C++ object.
</p>
<div class="targetlang">
<pre>
octave:5> swig_this(p1)
ans = 162504808
octave:6> swig_type(p1)
ans = Point
</pre></div>
<p>
Note that <tt>swig_ref</tt> is a reference-counted pointer to a C/C++ object/type, and as such has pass-by-reference semantics. For example if one has a allocated a single object but has two <tt>swig_ref</tt>'s pointing to it, modifying the object through either of them will change the single allocated object.
This differs from the usual pass-by-value (copy-on-write) semantics that Octave maintains for built-in types. For example, in the following snippet, modifying <tt>b</tt> does not modify <tt>a</tt>,
</p>
<div class="targetlang">
<pre>
octave:7> a=struct('x', 4)
a =
{
x = 4
}
octave:8> b=a
b =
{
x = 4
}
octave:9> b.y=4
b =
{
x = 4
y = 4
}
octave:10> a
a =
{
x = 4
}
</pre></div>
<p>
However, when dealing with wrapped objects, one gets the behavior
</p>
<div class="targetlang">
<pre>
octave:2> a=Point(3, 5)
a =
{
Point, ptr = 0x9afbbb0
}
octave:3> b=a
b =
{
Point, ptr = 0x9afbbb0
}
octave:4> b.set(2, 1);
octave:5> b.x, b.y
ans = 2
ans = 1
octave:6> a.x, a.y
ans = 2
ans = 1
</pre></div>
<p>
Depending on the ownership setting of a <tt>swig_ref</tt>, it may call C++ destructors when its reference count goes to zero. See the section on memory management below for details.
</p>
<H3><a name="Octave_nn15">29.3.7 C++ inheritance</a></H3>
<p>
Single and multiple inheritance are fully supported. The <tt>swig_ref</tt> type carries type information along with any C++ object pointer it holds.
This information contains the full class hierarchy. When an indexing operation (such as a method invocation) occurs,
the tree is walked to find a match in the current class as well as any of its bases. The lookup is then cached in the <tt>swig_ref</tt>.
</p>
<H3><a name="Octave_nn17">29.3.8 C++ overloaded functions</a></H3>
<p>
Overloaded functions are supported, and handled as in other modules. That is,
each overload is wrapped separately (under internal names), and a dispatch function is also emitted under the external/visible name.
The dispatch function selects which overload to call (if any) based on the passed arguments.
<tt>typecheck</tt> typemaps are used to analyze each argument, as well as assign precedence. See the chapter on typemaps for details.
</p>
<H3><a name="Octave_nn18">29.3.9 C++ operators</a></H3>
<p>
C++ operator overloading is supported, in a way similar to other modules.
The <tt>swig_ref</tt> type supports all unary and binary operators between itself and all other types that exist in the system at module load time. When an operator is used (where one of the operands is a <tt>swig_ref</tt>), the runtime routes the call to either a member function of the given object, or to a global function whose named is derived from the types of the operands (either both or just the lhs or rhs).
</p>
<p>
For example, if <tt>a</tt> and <tt>b</tt> are SWIG variables in Octave, <tt>a+b</tt> becomes <tt>a.__add__(b)</tt>. The wrapper is then free to implement __add__ to do whatever it wants. A wrapper may define the <tt>__add__</tt> function manually, %rename some other function to it, or %rename a C++ operator to it.
</p>
<p>
By default the C++ operators are renamed to their corresponding Octave operators. So without doing any work, the following interface
</p>
<div class="code"><pre>
%inline {
struct A {
int value;
A(int _value) : value(_value) {}
A operator+ (const A&amp; x) {
return A(value+x.value);
}
};
}
</pre></div>
<p>
is usable from Octave like this:
</p>
<div class="targetlang"><pre>
a=A(2), b=A(3), c=a+b
assert(c.value==5);
</pre></div>
<p>
Octave operators are mapped in the following way:
</p>
<div class="code"><pre>
__brace__ a{args}
__brace_asgn__ a{args} = rhs
__paren__ a(args)
__paren_asgn__ a(args) = rhs
__str__ generates string rep
__not__ !a
__uplus__ +a
__uminus__ -a
__transpose__ a.'
__hermitian__ a'
__incr__ a++
__decr__ a--
__add__ a + b
__sub__ a - b
__mul__ a * b
__div__ a / b
__pow__ a ^ b
__ldiv__ a \ b
__lshift__ a << b
__rshift__ a >> b
__lt__ a < b
__le__ a <= b
__eq__ a == b
__ge__ a >= b
__gt__ a > b
__ne__ a != b
__el_mul__ a .* b
__el_div__ a ./ b
__el_pow__ a .^ b
__el_ldiv__ a .\ b
__el_and__ a &amp; b
__el_or__ a | b
</pre></div>
<p>
On the C++ side, the default mappings are as follows:
</p>
<div class="code"><pre>
%rename(__add__) *::operator+;
%rename(__add__) *::operator+();
%rename(__add__) *::operator+() const;
%rename(__sub__) *::operator-;
%rename(__uminus__) *::operator-();
%rename(__uminus__) *::operator-() const;
%rename(__mul__) *::operator*;
%rename(__div__) *::operator/;
%rename(__mod__) *::operator%;
%rename(__lshift__) *::operator<<;
%rename(__rshift__) *::operator>>;
%rename(__el_and__) *::operator&amp;&amp;;
%rename(__el_or__) *::operator||;
%rename(__xor__) *::operator^;
%rename(__invert__) *::operator~;
%rename(__lt__) *::operator<;
%rename(__le__) *::operator<=;
%rename(__gt__) *::operator>;
%rename(__ge__) *::operator>=;
%rename(__eq__) *::operator==;
%rename(__ne__) *::operator!=;
%rename(__not__) *::operator!;
%rename(__incr__) *::operator++;
%rename(__decr__) *::operator--;
%rename(__paren__) *::operator();
%rename(__brace__) *::operator[];
</pre></div>
<p>
Octave can also utilise friend (i.e. non-member) operators with a simple %rename: see the example in the Examples/octave/operator directory.
</p>
<H3><a name="Octave_nn19">29.3.10 Class extension with %extend</a></H3>
<p>
The %extend directive works the same as in other modules.
</p>
<p>
You can use it to define special behavior, like for example defining Octave operators not mapped to C++ operators, or defining certain Octave mechanisms such as how an object prints. For example, the <tt>octave_value::{is_string, string_value, print}</tt> functions are routed to a special method <tt>__str__</tt> that can be defined inside an %extend.
</p>
<div class="code"><pre>
%extend A {
string __str__() {
stringstream sout;
sout&lt;&lt;$self->value;
return sout.str();
}
}
</pre></div>
<p>
Then in Octave one gets,
</p>
<div class="targetlang"><pre>
octave:1&gt; a=A(4);
octave:2&gt; a
a = 4
octave:3&gt; printf("%s\n", a);
4
octave:4&gt; a.__str__()
4
</pre></div>
<p>
Similarly, Octave can use the <tt>__float__</tt> method to convert an object to a numeric value.
</p>
<p>
Octave 3.8.0 and later versions will also map unary functions X() to the corresponding <tt>__X__</tt> method, where X includes: abs(), acos(), acosh(), angle(), arg(), asin(), asinh(), atan(), atanh(), cbrt(), ceil(), conj(), cos(), cosh(), dawson(), erf(), erfc(), erfcinv(), erfcx(), erfi(), erfinv(), exp(), expm1(), finite(), fix(), floor(), gamma(), imag(), isalnum(), isalpha(), isascii(), iscntrl(), isdigit(), isgraph(), isinf(), islower(), isna(), isnan(), isprint(), ispunct(), isspace(), isupper(), isxdigit(), lgamma(), log(), log10(), log1p(), log2(), real(), round(), roundb(), signbit(), signum(), sin(), sinh(), sqrt(), tan(), tanh(), toascii(), tolower(), toupper()
</p>
<H3><a name="Octave_nn20">29.3.11 C++ templates</a></H3>
<p>
C++ class and function templates are fully supported as in other modules, in that the %template directive may used to create explicit instantiations of templated types.
For example, function templates can be instantiated as follows:
</p>
<div class="code"><pre>%module swigexample
%inline {
template&lt;class __scalar&gt;
__scalar mul(__scalar a, __scalar b) {
return a*b;
}
}
%include &lt;std_complex.i&gt;
%template(mul) mul&lt;std::complex&lt;double&gt; &gt;
%template(mul) mul&lt;double&gt;
</pre></div>
<p>
and then used from Octave
</p>
<div class="targetlang"><pre>
octave:1> mul(4, 3)
ans = 12
octave:2> mul(4.2, 3.6)
ans = 15.120
octave:3> mul(3+4i, 10+2i)
ans = 22 + 46i
</pre></div>
<p>
Similarly, class templates can be instantiated as in the following example,
</p>
<div class="code"><pre>%module swigexample
%include &lt;std_complex.i&gt;
%include &lt;std_string.i&gt;
%inline {
#include &lt;sstream&gt;
template&lt;class __scalar&gt; class sum {
__scalar s;
public:
sum(__scalar _s=0) : s(_s) {}
sum&amp; add(__scalar _s) {
s+=_s;
return *this;
}
std::string __str__() const {
std::stringstream sout;
sout&lt;&lt;s;
return sout.str();
}
};
}
%template(sum_complex) sum&lt;std::complex&lt;double&gt; &gt;;
%template(sum_double) sum&lt;double&gt;;
</pre></div>
<p>
and then used from Octave
</p>
<div class="targetlang"><pre>
octave:2> a=sum_complex(2+3i);
octave:3> a.add(2)
ans =
(4, 3)
octave:4> a.add(3+i)
ans =
(7, 4)
</pre></div>
<H3><a name="Octave_nn21">29.3.12 C++ Smart Pointers</a></H3>
<H4><a name="Octave_smart_pointers_shared_ptr">29.3.12.1 The shared_ptr Smart Pointer</a></H4>
<p>
The C++11 standard provides <tt>std::shared_ptr</tt> which was derived from the Boost
implementation, <tt>boost::shared_ptr</tt>.
Both of these are available for Octave in the SWIG library and usage is outlined
in the <a href="Library.html#Library_std_shared_ptr">shared_ptr smart pointer</a> library section.
</p>
<H4><a name="Octave_smart_pointers_generic">29.3.12.2 Generic Smart Pointers</a></H4>
<p>
C++ smart pointers are fully supported as in other modules.
</p>
<H3><a name="Octave_nn22">29.3.13 Directors (calling Octave from C++ code)</a></H3>
<p>
There is full support for SWIG Directors, which permits Octave code to subclass C++ classes, and implement their virtual methods.
</p>
<p>
Octave has no direct support for object oriented programming, however the <tt>swig_ref</tt> type provides some of this support. You can manufacture a <tt>swig_ref</tt> using the <tt>subclass</tt> function (provided by the SWIG/Octave runtime).
</p>
<p>
For example,
</p>
<div class="targetlang"><pre>
octave:1&gt; a=subclass();
octave:2&gt; a.my_var = 4;
octave:3&gt; a.my_method = @(self) printf("my_var = ", self.my_var);
octave:4&gt; a.my_method();
my_var = 4
</pre></div>
<p>
<tt>subclass()</tt> can also be used to subclass one or more C++ types. Suppose you have an interface defined by
</p>
<div class="code"><pre>
%inline {
class A {
public:
virtual my_method() {
printf("c-side routine called\n");
}
};
void call_your_method(A&amp; a) {
a.my_method();
}
}
</pre></div>
<p>
Then from Octave you can say:
</p>
<div class="targetlang"><pre>
octave:1&gt; B=@() subclass(A(), @my_method);
octave:2&gt; function my_method(self)
octave:3&gt; printf("octave-side routine called\n");
octave:4&gt; end
octave:5&gt; call_your_method(B());
octave-side routine called
</pre></div>
<p>
or more concisely,
</p>
<div class="targetlang"><pre>
octave:1&gt; B=@() subclass(A(), 'my_method', @(self) printf("octave-side routine called\n"));
octave:2&gt; call_your_method(B());
octave-side routine called
</pre></div>
<p>
Note that you have to enable directors via the %feature directive (see other modules for this).
</p>
<p>
<tt>subclass()</tt> will accept any number of C++ bases or other <tt>subclass()</tt>'ed objects, <tt>(string, octave_value)</tt> pairs, and <tt>function_handles</tt>. In the first case, these are taken as base classes; in the second case, as named members (either variables or functions, depending on whether the given value is a function handle); in the third case, as member functions whose name is taken from the given function handle. E.g.,
</p>
<div class="targetlang"><pre>
octave:1&gt; B=@(some_var=2) subclass(A(), 'some_var', some_var, @some_func, 'another_func',
@(self) do_stuff())
</pre></div>
<p>
You can also assign non-C++ member variables and functions after construct time. There is no support for non-C++ static members.
</p>
<p>
There is limited support for explicitly referencing C++ bases. So, in the example above, we could have
</p>
<div class="targetlang"><pre>
octave:1&gt; B=@() subclass(A(), @my_method);
octave:2&gt; function my_method(self)
octave:3&gt; self.A.my_method();
octave:4&gt; printf("octave-side routine called\n");
octave:5&gt; end
octave:6&gt; call_your_method(B());
c-side routine called
octave-side routine called
</pre></div>
<H3><a name="Octave_nn23">29.3.14 Threads</a></H3>
<p>
The use of threads in wrapped Director code is not supported; i.e., an Octave-side implementation of a C++ class must be called from the Octave interpreter's thread. Anything fancier (apartment/queue model, whatever) is left to the user. Without anything fancier, this amounts to the limitation that Octave must drive the module... like, for example, an optimization package that calls Octave to evaluate an objective function.
</p>
<H3><a name="Octave_nn24">29.3.15 Memory management</a></H3>
<p>
As noted above, <tt>swig_ref</tt> represents a reference counted pointer to a C/C++-side object. It also contains a flag indicating whether Octave or the C/C++ code owns the object. If Octave owns it, any destructors will be called when the reference count reaches zero. If the C/C++ side owns the object, then destructors will not be called when the reference count goes to zero.
</p>
<p>
For example,
<div class="code"><pre>
%inline {
class A {
public:
A() { printf("A constructing\n"); }
~A() { printf("A destructing\n"); }
};
}
</pre></div>
<p>
Would produce this behavior in Octave:
</p>
<div class="targetlang"><pre>
octave:1&gt; a=A();
A constructing
octave:2&gt; b=a;
octave:3&gt; clear a;
octave:4&gt; b=4;
A destructing
</pre></div>
<p>
The %newobject directive may be used to control this behavior for pointers returned from functions.
<p>
In the case where one wishes for the C++ side to own an object that was created in Octave (especially a Director object), one can use the __disown() method to invert this logic. Then letting the Octave reference count go to zero will not destroy the object, but destroying the object will invalidate the Octave-side object if it still exists (and call destructors of other C++ bases in the case of multiple inheritance/<tt>subclass()</tt>'ing).
</p>
<H3><a name="Octave_nn25">29.3.16 STL support</a></H3>
<p>
Various STL library files are provided for wrapping STL containers.
</p>
<H3><a name="Octave_nn26">29.3.17 Matrix typemaps</a></H3>
<p>
Octave provides a rich set of classes for dealing with matrices. Currently there are no built-in typemaps to deal with those. However, these are relatively straight forward for users to add themselves (see the docs on typemaps). Without much work (a single typemap decl-- say, 5 lines of code in the interface file), it would be possible to have a function
</p>
<div class="code"><pre>
double my_det(const double* mat, int m, int n);
</pre></div>
<p>
that is accessed from Octave as,
</p>
<div class="targetlang"><pre>
octave:1&gt; my_det(rand(4));
ans = -0.18388
</pre></div>
<tt><br></tt>
</body>
</html>

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