sleepyhead111 commited on
Commit
d3dc4c6
·
verified ·
1 Parent(s): ac8aa50

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. FacebookAI/xlm-roberta-large/onnx/sentencepiece.bpe.model +3 -0
  2. mosesdecoder/contrib/memscore/Makefile.am +24 -0
  3. mosesdecoder/contrib/memscore/aclocal.m4 +851 -0
  4. mosesdecoder/contrib/memscore/config.h.in +79 -0
  5. mosesdecoder/contrib/memscore/datastorage.h +52 -0
  6. mosesdecoder/contrib/memscore/depcomp +530 -0
  7. mosesdecoder/contrib/memscore/install-sh +323 -0
  8. mosesdecoder/contrib/memscore/lexdecom.cpp +183 -0
  9. mosesdecoder/contrib/memscore/phraselm.cpp +63 -0
  10. mosesdecoder/contrib/memscore/phrasetable.h +710 -0
  11. mosesdecoder/contrib/memscore/scorer-impl.h +124 -0
  12. mosesdecoder/contrib/promix/README.md +66 -0
  13. mosesdecoder/contrib/promix/bleu.py +27 -0
  14. mosesdecoder/contrib/promix/coll.py +260 -0
  15. mosesdecoder/contrib/promix/main.py +112 -0
  16. mosesdecoder/contrib/promix/nbest.py +230 -0
  17. mosesdecoder/contrib/promix/test.py +25 -0
  18. mosesdecoder/contrib/promix/test_sampler.py +53 -0
  19. mosesdecoder/contrib/promix/test_train.py +306 -0
  20. mosesdecoder/contrib/promix/util.py +12 -0
  21. mosesdecoder/jam-files/boost-build/build/ac.jam +198 -0
  22. mosesdecoder/jam-files/boost-build/build/project.jam +1121 -0
  23. mosesdecoder/jam-files/boost-build/build/property-set.jam +489 -0
  24. mosesdecoder/jam-files/boost-build/build/targets.jam +1659 -0
  25. mosesdecoder/jam-files/boost-build/build/version.jam +161 -0
  26. mosesdecoder/jam-files/boost-build/build/virtual-target.jam +1317 -0
  27. mosesdecoder/jam-files/boost-build/util/assert.jam +336 -0
  28. mosesdecoder/jam-files/boost-build/util/doc.jam +997 -0
  29. mosesdecoder/jam-files/boost-build/util/numbers.jam +218 -0
  30. mosesdecoder/jam-files/boost-build/util/regex.jam +193 -0
  31. mosesdecoder/jam-files/engine/build.bat +565 -0
  32. mosesdecoder/jam-files/engine/builtins.c +2354 -0
  33. mosesdecoder/jam-files/engine/builtins.h +70 -0
  34. mosesdecoder/jam-files/engine/bump_version.py +98 -0
  35. mosesdecoder/jam-files/engine/class.c +191 -0
  36. mosesdecoder/jam-files/engine/command.h +73 -0
  37. mosesdecoder/jam-files/engine/compile.h +59 -0
  38. mosesdecoder/jam-files/engine/cwd.c +83 -0
  39. mosesdecoder/jam-files/engine/filent.c +311 -0
  40. mosesdecoder/jam-files/engine/fileunix.c +180 -0
  41. mosesdecoder/jam-files/engine/frames.c +29 -0
  42. mosesdecoder/jam-files/engine/function.c +0 -0
  43. mosesdecoder/jam-files/engine/function.h +46 -0
  44. mosesdecoder/jam-files/engine/hash.h +79 -0
  45. mosesdecoder/jam-files/engine/hcache.c +519 -0
  46. mosesdecoder/jam-files/engine/hdrmacro.h +21 -0
  47. mosesdecoder/jam-files/engine/headers.c +197 -0
  48. mosesdecoder/jam-files/engine/jam.c +656 -0
  49. mosesdecoder/jam-files/engine/jam.h +475 -0
  50. mosesdecoder/jam-files/engine/jamgram.y +373 -0
FacebookAI/xlm-roberta-large/onnx/sentencepiece.bpe.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cfc8146abe2a0488e9e2a0c56de7952f7c11ab059eca145a0a727afce0db2865
3
+ size 5069051
mosesdecoder/contrib/memscore/Makefile.am ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # memscore - in-memory phrase scoring for Statistical Machine Translation
2
+ # Christian Hardmeier, FBK-irst, Trento, 2010
3
+ # $Id$
4
+
5
+ ## Process this file with automake to produce Makefile.in
6
+
7
+ ACLOCAL_AMFLAGS = -I m4
8
+
9
+ AUTOMAKE_OPTIONS = foreign
10
+ AM_CXXFLAGS = $(BOOST_CPPFLAGS) -Wall -ffast-math -ftrapping-math -fomit-frame-pointer
11
+
12
+ bin_PROGRAMS = memscore
13
+ memscore_SOURCES = datastorage.h memscore.h phrasetable.h scorer.h scorer-impl.h statistic.h timestamp.h \
14
+ phrasetable.cpp memscore.cpp scorer.cpp lexdecom.cpp lexdecom.h
15
+
16
+ if IRSTLM
17
+ memscore_SOURCES += phraselm.cpp phraselm.h
18
+ endif
19
+ if CHANNEL_SCORER
20
+ memscore_SOURCES += channel-scorer.cpp channel-scorer.h
21
+ endif
22
+
23
+
24
+ memscore_LDADD = $(IRSTLM_LIBS) $(GSL_LIBS)
mosesdecoder/contrib/memscore/aclocal.m4 ADDED
@@ -0,0 +1,851 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # generated automatically by aclocal 1.9.6 -*- Autoconf -*-
2
+
3
+ # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4
+ # 2005 Free Software Foundation, Inc.
5
+ # This file is free software; the Free Software Foundation
6
+ # gives unlimited permission to copy and/or distribute it,
7
+ # with or without modifications, as long as this notice is preserved.
8
+
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY, to the extent permitted by law; without
11
+ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12
+ # PARTICULAR PURPOSE.
13
+
14
+ # Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
15
+ #
16
+ # This file is free software; the Free Software Foundation
17
+ # gives unlimited permission to copy and/or distribute it,
18
+ # with or without modifications, as long as this notice is preserved.
19
+
20
+ # AM_AUTOMAKE_VERSION(VERSION)
21
+ # ----------------------------
22
+ # Automake X.Y traces this macro to ensure aclocal.m4 has been
23
+ # generated from the m4 files accompanying Automake X.Y.
24
+ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"])
25
+
26
+ # AM_SET_CURRENT_AUTOMAKE_VERSION
27
+ # -------------------------------
28
+ # Call AM_AUTOMAKE_VERSION so it can be traced.
29
+ # This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
30
+ AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
31
+ [AM_AUTOMAKE_VERSION([1.9.6])])
32
+
33
+ # AM_AUX_DIR_EXPAND -*- Autoconf -*-
34
+
35
+ # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
36
+ #
37
+ # This file is free software; the Free Software Foundation
38
+ # gives unlimited permission to copy and/or distribute it,
39
+ # with or without modifications, as long as this notice is preserved.
40
+
41
+ # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
42
+ # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
43
+ # `$srcdir', `$srcdir/..', or `$srcdir/../..'.
44
+ #
45
+ # Of course, Automake must honor this variable whenever it calls a
46
+ # tool from the auxiliary directory. The problem is that $srcdir (and
47
+ # therefore $ac_aux_dir as well) can be either absolute or relative,
48
+ # depending on how configure is run. This is pretty annoying, since
49
+ # it makes $ac_aux_dir quite unusable in subdirectories: in the top
50
+ # source directory, any form will work fine, but in subdirectories a
51
+ # relative path needs to be adjusted first.
52
+ #
53
+ # $ac_aux_dir/missing
54
+ # fails when called from a subdirectory if $ac_aux_dir is relative
55
+ # $top_srcdir/$ac_aux_dir/missing
56
+ # fails if $ac_aux_dir is absolute,
57
+ # fails when called from a subdirectory in a VPATH build with
58
+ # a relative $ac_aux_dir
59
+ #
60
+ # The reason of the latter failure is that $top_srcdir and $ac_aux_dir
61
+ # are both prefixed by $srcdir. In an in-source build this is usually
62
+ # harmless because $srcdir is `.', but things will broke when you
63
+ # start a VPATH build or use an absolute $srcdir.
64
+ #
65
+ # So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
66
+ # iff we strip the leading $srcdir from $ac_aux_dir. That would be:
67
+ # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
68
+ # and then we would define $MISSING as
69
+ # MISSING="\${SHELL} $am_aux_dir/missing"
70
+ # This will work as long as MISSING is not called from configure, because
71
+ # unfortunately $(top_srcdir) has no meaning in configure.
72
+ # However there are other variables, like CC, which are often used in
73
+ # configure, and could therefore not use this "fixed" $ac_aux_dir.
74
+ #
75
+ # Another solution, used here, is to always expand $ac_aux_dir to an
76
+ # absolute PATH. The drawback is that using absolute paths prevent a
77
+ # configured tree to be moved without reconfiguration.
78
+
79
+ AC_DEFUN([AM_AUX_DIR_EXPAND],
80
+ [dnl Rely on autoconf to set up CDPATH properly.
81
+ AC_PREREQ([2.50])dnl
82
+ # expand $ac_aux_dir to an absolute path
83
+ am_aux_dir=`cd $ac_aux_dir && pwd`
84
+ ])
85
+
86
+ # AM_CONDITIONAL -*- Autoconf -*-
87
+
88
+ # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005
89
+ # Free Software Foundation, Inc.
90
+ #
91
+ # This file is free software; the Free Software Foundation
92
+ # gives unlimited permission to copy and/or distribute it,
93
+ # with or without modifications, as long as this notice is preserved.
94
+
95
+ # serial 7
96
+
97
+ # AM_CONDITIONAL(NAME, SHELL-CONDITION)
98
+ # -------------------------------------
99
+ # Define a conditional.
100
+ AC_DEFUN([AM_CONDITIONAL],
101
+ [AC_PREREQ(2.52)dnl
102
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
103
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
104
+ AC_SUBST([$1_TRUE])
105
+ AC_SUBST([$1_FALSE])
106
+ if $2; then
107
+ $1_TRUE=
108
+ $1_FALSE='#'
109
+ else
110
+ $1_TRUE='#'
111
+ $1_FALSE=
112
+ fi
113
+ AC_CONFIG_COMMANDS_PRE(
114
+ [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
115
+ AC_MSG_ERROR([[conditional "$1" was never defined.
116
+ Usually this means the macro was only invoked conditionally.]])
117
+ fi])])
118
+
119
+
120
+ # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
121
+ # Free Software Foundation, Inc.
122
+ #
123
+ # This file is free software; the Free Software Foundation
124
+ # gives unlimited permission to copy and/or distribute it,
125
+ # with or without modifications, as long as this notice is preserved.
126
+
127
+ # serial 8
128
+
129
+ # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
130
+ # written in clear, in which case automake, when reading aclocal.m4,
131
+ # will think it sees a *use*, and therefore will trigger all it's
132
+ # C support machinery. Also note that it means that autoscan, seeing
133
+ # CC etc. in the Makefile, will ask for an AC_PROG_CC use...
134
+
135
+
136
+ # _AM_DEPENDENCIES(NAME)
137
+ # ----------------------
138
+ # See how the compiler implements dependency checking.
139
+ # NAME is "CC", "CXX", "GCJ", or "OBJC".
140
+ # We try a few techniques and use that to set a single cache variable.
141
+ #
142
+ # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
143
+ # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
144
+ # dependency, and given that the user is not expected to run this macro,
145
+ # just rely on AC_PROG_CC.
146
+ AC_DEFUN([_AM_DEPENDENCIES],
147
+ [AC_REQUIRE([AM_SET_DEPDIR])dnl
148
+ AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
149
+ AC_REQUIRE([AM_MAKE_INCLUDE])dnl
150
+ AC_REQUIRE([AM_DEP_TRACK])dnl
151
+
152
+ ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
153
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
154
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
155
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
156
+ [depcc="$$1" am_compiler_list=])
157
+
158
+ AC_CACHE_CHECK([dependency style of $depcc],
159
+ [am_cv_$1_dependencies_compiler_type],
160
+ [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
161
+ # We make a subdir and do the tests there. Otherwise we can end up
162
+ # making bogus files that we don't know about and never remove. For
163
+ # instance it was reported that on HP-UX the gcc test will end up
164
+ # making a dummy file named `D' -- because `-MD' means `put the output
165
+ # in D'.
166
+ mkdir conftest.dir
167
+ # Copy depcomp to subdir because otherwise we won't find it if we're
168
+ # using a relative directory.
169
+ cp "$am_depcomp" conftest.dir
170
+ cd conftest.dir
171
+ # We will build objects and dependencies in a subdirectory because
172
+ # it helps to detect inapplicable dependency modes. For instance
173
+ # both Tru64's cc and ICC support -MD to output dependencies as a
174
+ # side effect of compilation, but ICC will put the dependencies in
175
+ # the current directory while Tru64 will put them in the object
176
+ # directory.
177
+ mkdir sub
178
+
179
+ am_cv_$1_dependencies_compiler_type=none
180
+ if test "$am_compiler_list" = ""; then
181
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
182
+ fi
183
+ for depmode in $am_compiler_list; do
184
+ # Setup a source with many dependencies, because some compilers
185
+ # like to wrap large dependency lists on column 80 (with \), and
186
+ # we should not choose a depcomp mode which is confused by this.
187
+ #
188
+ # We need to recreate these files for each test, as the compiler may
189
+ # overwrite some of them when testing with obscure command lines.
190
+ # This happens at least with the AIX C compiler.
191
+ : > sub/conftest.c
192
+ for i in 1 2 3 4 5 6; do
193
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
194
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
195
+ # Solaris 8's {/usr,}/bin/sh.
196
+ touch sub/conftst$i.h
197
+ done
198
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
199
+
200
+ case $depmode in
201
+ nosideeffect)
202
+ # after this tag, mechanisms are not by side-effect, so they'll
203
+ # only be used when explicitly requested
204
+ if test "x$enable_dependency_tracking" = xyes; then
205
+ continue
206
+ else
207
+ break
208
+ fi
209
+ ;;
210
+ none) break ;;
211
+ esac
212
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
213
+ # mode. It turns out that the SunPro C++ compiler does not properly
214
+ # handle `-M -o', and we need to detect this.
215
+ if depmode=$depmode \
216
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
217
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
218
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
219
+ >/dev/null 2>conftest.err &&
220
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
221
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
222
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
223
+ # icc doesn't choke on unknown options, it will just issue warnings
224
+ # or remarks (even with -Werror). So we grep stderr for any message
225
+ # that says an option was ignored or not supported.
226
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
227
+ # icc: Command line warning: ignoring option '-M'; no argument required
228
+ # The diagnosis changed in icc 8.0:
229
+ # icc: Command line remark: option '-MP' not supported
230
+ if (grep 'ignoring option' conftest.err ||
231
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
232
+ am_cv_$1_dependencies_compiler_type=$depmode
233
+ break
234
+ fi
235
+ fi
236
+ done
237
+
238
+ cd ..
239
+ rm -rf conftest.dir
240
+ else
241
+ am_cv_$1_dependencies_compiler_type=none
242
+ fi
243
+ ])
244
+ AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
245
+ AM_CONDITIONAL([am__fastdep$1], [
246
+ test "x$enable_dependency_tracking" != xno \
247
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
248
+ ])
249
+
250
+
251
+ # AM_SET_DEPDIR
252
+ # -------------
253
+ # Choose a directory name for dependency files.
254
+ # This macro is AC_REQUIREd in _AM_DEPENDENCIES
255
+ AC_DEFUN([AM_SET_DEPDIR],
256
+ [AC_REQUIRE([AM_SET_LEADING_DOT])dnl
257
+ AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
258
+ ])
259
+
260
+
261
+ # AM_DEP_TRACK
262
+ # ------------
263
+ AC_DEFUN([AM_DEP_TRACK],
264
+ [AC_ARG_ENABLE(dependency-tracking,
265
+ [ --disable-dependency-tracking speeds up one-time build
266
+ --enable-dependency-tracking do not reject slow dependency extractors])
267
+ if test "x$enable_dependency_tracking" != xno; then
268
+ am_depcomp="$ac_aux_dir/depcomp"
269
+ AMDEPBACKSLASH='\'
270
+ fi
271
+ AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
272
+ AC_SUBST([AMDEPBACKSLASH])
273
+ ])
274
+
275
+ # Generate code to set up dependency tracking. -*- Autoconf -*-
276
+
277
+ # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
278
+ # Free Software Foundation, Inc.
279
+ #
280
+ # This file is free software; the Free Software Foundation
281
+ # gives unlimited permission to copy and/or distribute it,
282
+ # with or without modifications, as long as this notice is preserved.
283
+
284
+ #serial 3
285
+
286
+ # _AM_OUTPUT_DEPENDENCY_COMMANDS
287
+ # ------------------------------
288
+ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
289
+ [for mf in $CONFIG_FILES; do
290
+ # Strip MF so we end up with the name of the file.
291
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
292
+ # Check whether this is an Automake generated Makefile or not.
293
+ # We used to match only the files named `Makefile.in', but
294
+ # some people rename them; so instead we look at the file content.
295
+ # Grep'ing the first line is not enough: some people post-process
296
+ # each Makefile.in and add a new line on top of each file to say so.
297
+ # So let's grep whole file.
298
+ if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then
299
+ dirpart=`AS_DIRNAME("$mf")`
300
+ else
301
+ continue
302
+ fi
303
+ # Extract the definition of DEPDIR, am__include, and am__quote
304
+ # from the Makefile without running `make'.
305
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
306
+ test -z "$DEPDIR" && continue
307
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
308
+ test -z "am__include" && continue
309
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
310
+ # When using ansi2knr, U may be empty or an underscore; expand it
311
+ U=`sed -n 's/^U = //p' < "$mf"`
312
+ # Find all dependency output files, they are included files with
313
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
314
+ # simplest approach to changing $(DEPDIR) to its actual value in the
315
+ # expansion.
316
+ for file in `sed -n "
317
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
318
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
319
+ # Make sure the directory exists.
320
+ test -f "$dirpart/$file" && continue
321
+ fdir=`AS_DIRNAME(["$file"])`
322
+ AS_MKDIR_P([$dirpart/$fdir])
323
+ # echo "creating $dirpart/$file"
324
+ echo '# dummy' > "$dirpart/$file"
325
+ done
326
+ done
327
+ ])# _AM_OUTPUT_DEPENDENCY_COMMANDS
328
+
329
+
330
+ # AM_OUTPUT_DEPENDENCY_COMMANDS
331
+ # -----------------------------
332
+ # This macro should only be invoked once -- use via AC_REQUIRE.
333
+ #
334
+ # This code is only required when automatic dependency tracking
335
+ # is enabled. FIXME. This creates each `.P' file that we will
336
+ # need in order to bootstrap the dependency handling code.
337
+ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
338
+ [AC_CONFIG_COMMANDS([depfiles],
339
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
340
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
341
+ ])
342
+
343
+ # Do all the work for Automake. -*- Autoconf -*-
344
+
345
+ # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
346
+ # Free Software Foundation, Inc.
347
+ #
348
+ # This file is free software; the Free Software Foundation
349
+ # gives unlimited permission to copy and/or distribute it,
350
+ # with or without modifications, as long as this notice is preserved.
351
+
352
+ # serial 12
353
+
354
+ # This macro actually does too much. Some checks are only needed if
355
+ # your package does certain things. But this isn't really a big deal.
356
+
357
+ # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
358
+ # AM_INIT_AUTOMAKE([OPTIONS])
359
+ # -----------------------------------------------
360
+ # The call with PACKAGE and VERSION arguments is the old style
361
+ # call (pre autoconf-2.50), which is being phased out. PACKAGE
362
+ # and VERSION should now be passed to AC_INIT and removed from
363
+ # the call to AM_INIT_AUTOMAKE.
364
+ # We support both call styles for the transition. After
365
+ # the next Automake release, Autoconf can make the AC_INIT
366
+ # arguments mandatory, and then we can depend on a new Autoconf
367
+ # release and drop the old call support.
368
+ AC_DEFUN([AM_INIT_AUTOMAKE],
369
+ [AC_PREREQ([2.58])dnl
370
+ dnl Autoconf wants to disallow AM_ names. We explicitly allow
371
+ dnl the ones we care about.
372
+ m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
373
+ AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
374
+ AC_REQUIRE([AC_PROG_INSTALL])dnl
375
+ # test to see if srcdir already configured
376
+ if test "`cd $srcdir && pwd`" != "`pwd`" &&
377
+ test -f $srcdir/config.status; then
378
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
379
+ fi
380
+
381
+ # test whether we have cygpath
382
+ if test -z "$CYGPATH_W"; then
383
+ if (cygpath --version) >/dev/null 2>/dev/null; then
384
+ CYGPATH_W='cygpath -w'
385
+ else
386
+ CYGPATH_W=echo
387
+ fi
388
+ fi
389
+ AC_SUBST([CYGPATH_W])
390
+
391
+ # Define the identity of the package.
392
+ dnl Distinguish between old-style and new-style calls.
393
+ m4_ifval([$2],
394
+ [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
395
+ AC_SUBST([PACKAGE], [$1])dnl
396
+ AC_SUBST([VERSION], [$2])],
397
+ [_AM_SET_OPTIONS([$1])dnl
398
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
399
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
400
+
401
+ _AM_IF_OPTION([no-define],,
402
+ [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
403
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
404
+
405
+ # Some tools Automake needs.
406
+ AC_REQUIRE([AM_SANITY_CHECK])dnl
407
+ AC_REQUIRE([AC_ARG_PROGRAM])dnl
408
+ AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
409
+ AM_MISSING_PROG(AUTOCONF, autoconf)
410
+ AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
411
+ AM_MISSING_PROG(AUTOHEADER, autoheader)
412
+ AM_MISSING_PROG(MAKEINFO, makeinfo)
413
+ AM_PROG_INSTALL_SH
414
+ AM_PROG_INSTALL_STRIP
415
+ AC_REQUIRE([AM_PROG_MKDIR_P])dnl
416
+ # We need awk for the "check" target. The system "awk" is bad on
417
+ # some platforms.
418
+ AC_REQUIRE([AC_PROG_AWK])dnl
419
+ AC_REQUIRE([AC_PROG_MAKE_SET])dnl
420
+ AC_REQUIRE([AM_SET_LEADING_DOT])dnl
421
+ _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
422
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
423
+ [_AM_PROG_TAR([v7])])])
424
+ _AM_IF_OPTION([no-dependencies],,
425
+ [AC_PROVIDE_IFELSE([AC_PROG_CC],
426
+ [_AM_DEPENDENCIES(CC)],
427
+ [define([AC_PROG_CC],
428
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
429
+ AC_PROVIDE_IFELSE([AC_PROG_CXX],
430
+ [_AM_DEPENDENCIES(CXX)],
431
+ [define([AC_PROG_CXX],
432
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
433
+ ])
434
+ ])
435
+
436
+
437
+ # When config.status generates a header, we must update the stamp-h file.
438
+ # This file resides in the same directory as the config header
439
+ # that is generated. The stamp files are numbered to have different names.
440
+
441
+ # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
442
+ # loop where config.status creates the headers, so we can generate
443
+ # our stamp files there.
444
+ AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
445
+ [# Compute $1's index in $config_headers.
446
+ _am_stamp_count=1
447
+ for _am_header in $config_headers :; do
448
+ case $_am_header in
449
+ $1 | $1:* )
450
+ break ;;
451
+ * )
452
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
453
+ esac
454
+ done
455
+ echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
456
+
457
+ # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
458
+ #
459
+ # This file is free software; the Free Software Foundation
460
+ # gives unlimited permission to copy and/or distribute it,
461
+ # with or without modifications, as long as this notice is preserved.
462
+
463
+ # AM_PROG_INSTALL_SH
464
+ # ------------------
465
+ # Define $install_sh.
466
+ AC_DEFUN([AM_PROG_INSTALL_SH],
467
+ [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
468
+ install_sh=${install_sh-"$am_aux_dir/install-sh"}
469
+ AC_SUBST(install_sh)])
470
+
471
+ # Copyright (C) 2003, 2005 Free Software Foundation, Inc.
472
+ #
473
+ # This file is free software; the Free Software Foundation
474
+ # gives unlimited permission to copy and/or distribute it,
475
+ # with or without modifications, as long as this notice is preserved.
476
+
477
+ # serial 2
478
+
479
+ # Check whether the underlying file-system supports filenames
480
+ # with a leading dot. For instance MS-DOS doesn't.
481
+ AC_DEFUN([AM_SET_LEADING_DOT],
482
+ [rm -rf .tst 2>/dev/null
483
+ mkdir .tst 2>/dev/null
484
+ if test -d .tst; then
485
+ am__leading_dot=.
486
+ else
487
+ am__leading_dot=_
488
+ fi
489
+ rmdir .tst 2>/dev/null
490
+ AC_SUBST([am__leading_dot])])
491
+
492
+ # Check to see how 'make' treats includes. -*- Autoconf -*-
493
+
494
+ # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
495
+ #
496
+ # This file is free software; the Free Software Foundation
497
+ # gives unlimited permission to copy and/or distribute it,
498
+ # with or without modifications, as long as this notice is preserved.
499
+
500
+ # serial 3
501
+
502
+ # AM_MAKE_INCLUDE()
503
+ # -----------------
504
+ # Check to see how make treats includes.
505
+ AC_DEFUN([AM_MAKE_INCLUDE],
506
+ [am_make=${MAKE-make}
507
+ cat > confinc << 'END'
508
+ am__doit:
509
+ @echo done
510
+ .PHONY: am__doit
511
+ END
512
+ # If we don't find an include directive, just comment out the code.
513
+ AC_MSG_CHECKING([for style of include used by $am_make])
514
+ am__include="#"
515
+ am__quote=
516
+ _am_result=none
517
+ # First try GNU make style include.
518
+ echo "include confinc" > confmf
519
+ # We grep out `Entering directory' and `Leaving directory'
520
+ # messages which can occur if `w' ends up in MAKEFLAGS.
521
+ # In particular we don't look at `^make:' because GNU make might
522
+ # be invoked under some other name (usually "gmake"), in which
523
+ # case it prints its new name instead of `make'.
524
+ if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
525
+ am__include=include
526
+ am__quote=
527
+ _am_result=GNU
528
+ fi
529
+ # Now try BSD make style include.
530
+ if test "$am__include" = "#"; then
531
+ echo '.include "confinc"' > confmf
532
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
533
+ am__include=.include
534
+ am__quote="\""
535
+ _am_result=BSD
536
+ fi
537
+ fi
538
+ AC_SUBST([am__include])
539
+ AC_SUBST([am__quote])
540
+ AC_MSG_RESULT([$_am_result])
541
+ rm -f confinc confmf
542
+ ])
543
+
544
+ # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
545
+
546
+ # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
547
+ # Free Software Foundation, Inc.
548
+ #
549
+ # This file is free software; the Free Software Foundation
550
+ # gives unlimited permission to copy and/or distribute it,
551
+ # with or without modifications, as long as this notice is preserved.
552
+
553
+ # serial 4
554
+
555
+ # AM_MISSING_PROG(NAME, PROGRAM)
556
+ # ------------------------------
557
+ AC_DEFUN([AM_MISSING_PROG],
558
+ [AC_REQUIRE([AM_MISSING_HAS_RUN])
559
+ $1=${$1-"${am_missing_run}$2"}
560
+ AC_SUBST($1)])
561
+
562
+
563
+ # AM_MISSING_HAS_RUN
564
+ # ------------------
565
+ # Define MISSING if not defined so far and test if it supports --run.
566
+ # If it does, set am_missing_run to use it, otherwise, to nothing.
567
+ AC_DEFUN([AM_MISSING_HAS_RUN],
568
+ [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
569
+ test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
570
+ # Use eval to expand $SHELL
571
+ if eval "$MISSING --run true"; then
572
+ am_missing_run="$MISSING --run "
573
+ else
574
+ am_missing_run=
575
+ AC_MSG_WARN([`missing' script is too old or missing])
576
+ fi
577
+ ])
578
+
579
+ # Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
580
+ #
581
+ # This file is free software; the Free Software Foundation
582
+ # gives unlimited permission to copy and/or distribute it,
583
+ # with or without modifications, as long as this notice is preserved.
584
+
585
+ # AM_PROG_MKDIR_P
586
+ # ---------------
587
+ # Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
588
+ #
589
+ # Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
590
+ # created by `make install' are always world readable, even if the
591
+ # installer happens to have an overly restrictive umask (e.g. 077).
592
+ # This was a mistake. There are at least two reasons why we must not
593
+ # use `-m 0755':
594
+ # - it causes special bits like SGID to be ignored,
595
+ # - it may be too restrictive (some setups expect 775 directories).
596
+ #
597
+ # Do not use -m 0755 and let people choose whatever they expect by
598
+ # setting umask.
599
+ #
600
+ # We cannot accept any implementation of `mkdir' that recognizes `-p'.
601
+ # Some implementations (such as Solaris 8's) are not thread-safe: if a
602
+ # parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
603
+ # concurrently, both version can detect that a/ is missing, but only
604
+ # one can create it and the other will error out. Consequently we
605
+ # restrict ourselves to GNU make (using the --version option ensures
606
+ # this.)
607
+ AC_DEFUN([AM_PROG_MKDIR_P],
608
+ [if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
609
+ # We used to keeping the `.' as first argument, in order to
610
+ # allow $(mkdir_p) to be used without argument. As in
611
+ # $(mkdir_p) $(somedir)
612
+ # where $(somedir) is conditionally defined. However this is wrong
613
+ # for two reasons:
614
+ # 1. if the package is installed by a user who cannot write `.'
615
+ # make install will fail,
616
+ # 2. the above comment should most certainly read
617
+ # $(mkdir_p) $(DESTDIR)$(somedir)
618
+ # so it does not work when $(somedir) is undefined and
619
+ # $(DESTDIR) is not.
620
+ # To support the latter case, we have to write
621
+ # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir),
622
+ # so the `.' trick is pointless.
623
+ mkdir_p='mkdir -p --'
624
+ else
625
+ # On NextStep and OpenStep, the `mkdir' command does not
626
+ # recognize any option. It will interpret all options as
627
+ # directories to create, and then abort because `.' already
628
+ # exists.
629
+ for d in ./-p ./--version;
630
+ do
631
+ test -d $d && rmdir $d
632
+ done
633
+ # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
634
+ if test -f "$ac_aux_dir/mkinstalldirs"; then
635
+ mkdir_p='$(mkinstalldirs)'
636
+ else
637
+ mkdir_p='$(install_sh) -d'
638
+ fi
639
+ fi
640
+ AC_SUBST([mkdir_p])])
641
+
642
+ # Helper functions for option handling. -*- Autoconf -*-
643
+
644
+ # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
645
+ #
646
+ # This file is free software; the Free Software Foundation
647
+ # gives unlimited permission to copy and/or distribute it,
648
+ # with or without modifications, as long as this notice is preserved.
649
+
650
+ # serial 3
651
+
652
+ # _AM_MANGLE_OPTION(NAME)
653
+ # -----------------------
654
+ AC_DEFUN([_AM_MANGLE_OPTION],
655
+ [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
656
+
657
+ # _AM_SET_OPTION(NAME)
658
+ # ------------------------------
659
+ # Set option NAME. Presently that only means defining a flag for this option.
660
+ AC_DEFUN([_AM_SET_OPTION],
661
+ [m4_define(_AM_MANGLE_OPTION([$1]), 1)])
662
+
663
+ # _AM_SET_OPTIONS(OPTIONS)
664
+ # ----------------------------------
665
+ # OPTIONS is a space-separated list of Automake options.
666
+ AC_DEFUN([_AM_SET_OPTIONS],
667
+ [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
668
+
669
+ # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
670
+ # -------------------------------------------
671
+ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
672
+ AC_DEFUN([_AM_IF_OPTION],
673
+ [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
674
+
675
+ # Check to make sure that the build environment is sane. -*- Autoconf -*-
676
+
677
+ # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
678
+ # Free Software Foundation, Inc.
679
+ #
680
+ # This file is free software; the Free Software Foundation
681
+ # gives unlimited permission to copy and/or distribute it,
682
+ # with or without modifications, as long as this notice is preserved.
683
+
684
+ # serial 4
685
+
686
+ # AM_SANITY_CHECK
687
+ # ---------------
688
+ AC_DEFUN([AM_SANITY_CHECK],
689
+ [AC_MSG_CHECKING([whether build environment is sane])
690
+ # Just in case
691
+ sleep 1
692
+ echo timestamp > conftest.file
693
+ # Do `set' in a subshell so we don't clobber the current shell's
694
+ # arguments. Must try -L first in case configure is actually a
695
+ # symlink; some systems play weird games with the mod time of symlinks
696
+ # (eg FreeBSD returns the mod time of the symlink's containing
697
+ # directory).
698
+ if (
699
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
700
+ if test "$[*]" = "X"; then
701
+ # -L didn't work.
702
+ set X `ls -t $srcdir/configure conftest.file`
703
+ fi
704
+ rm -f conftest.file
705
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
706
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
707
+
708
+ # If neither matched, then we have a broken ls. This can happen
709
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
710
+ # broken ls alias from the environment. This has actually
711
+ # happened. Such a system could not be considered "sane".
712
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
713
+ alias in your environment])
714
+ fi
715
+
716
+ test "$[2]" = conftest.file
717
+ )
718
+ then
719
+ # Ok.
720
+ :
721
+ else
722
+ AC_MSG_ERROR([newly created file is older than distributed files!
723
+ Check your system clock])
724
+ fi
725
+ AC_MSG_RESULT(yes)])
726
+
727
+ # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
728
+ #
729
+ # This file is free software; the Free Software Foundation
730
+ # gives unlimited permission to copy and/or distribute it,
731
+ # with or without modifications, as long as this notice is preserved.
732
+
733
+ # AM_PROG_INSTALL_STRIP
734
+ # ---------------------
735
+ # One issue with vendor `install' (even GNU) is that you can't
736
+ # specify the program used to strip binaries. This is especially
737
+ # annoying in cross-compiling environments, where the build's strip
738
+ # is unlikely to handle the host's binaries.
739
+ # Fortunately install-sh will honor a STRIPPROG variable, so we
740
+ # always use install-sh in `make install-strip', and initialize
741
+ # STRIPPROG with the value of the STRIP variable (set by the user).
742
+ AC_DEFUN([AM_PROG_INSTALL_STRIP],
743
+ [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
744
+ # Installed binaries are usually stripped using `strip' when the user
745
+ # run `make install-strip'. However `strip' might not be the right
746
+ # tool to use in cross-compilation environments, therefore Automake
747
+ # will honor the `STRIP' environment variable to overrule this program.
748
+ dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
749
+ if test "$cross_compiling" != no; then
750
+ AC_CHECK_TOOL([STRIP], [strip], :)
751
+ fi
752
+ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
753
+ AC_SUBST([INSTALL_STRIP_PROGRAM])])
754
+
755
+ # Check how to create a tarball. -*- Autoconf -*-
756
+
757
+ # Copyright (C) 2004, 2005 Free Software Foundation, Inc.
758
+ #
759
+ # This file is free software; the Free Software Foundation
760
+ # gives unlimited permission to copy and/or distribute it,
761
+ # with or without modifications, as long as this notice is preserved.
762
+
763
+ # serial 2
764
+
765
+ # _AM_PROG_TAR(FORMAT)
766
+ # --------------------
767
+ # Check how to create a tarball in format FORMAT.
768
+ # FORMAT should be one of `v7', `ustar', or `pax'.
769
+ #
770
+ # Substitute a variable $(am__tar) that is a command
771
+ # writing to stdout a FORMAT-tarball containing the directory
772
+ # $tardir.
773
+ # tardir=directory && $(am__tar) > result.tar
774
+ #
775
+ # Substitute a variable $(am__untar) that extract such
776
+ # a tarball read from stdin.
777
+ # $(am__untar) < result.tar
778
+ AC_DEFUN([_AM_PROG_TAR],
779
+ [# Always define AMTAR for backward compatibility.
780
+ AM_MISSING_PROG([AMTAR], [tar])
781
+ m4_if([$1], [v7],
782
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
783
+ [m4_case([$1], [ustar],, [pax],,
784
+ [m4_fatal([Unknown tar format])])
785
+ AC_MSG_CHECKING([how to create a $1 tar archive])
786
+ # Loop over all known methods to create a tar archive until one works.
787
+ _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
788
+ _am_tools=${am_cv_prog_tar_$1-$_am_tools}
789
+ # Do not fold the above two line into one, because Tru64 sh and
790
+ # Solaris sh will not grok spaces in the rhs of `-'.
791
+ for _am_tool in $_am_tools
792
+ do
793
+ case $_am_tool in
794
+ gnutar)
795
+ for _am_tar in tar gnutar gtar;
796
+ do
797
+ AM_RUN_LOG([$_am_tar --version]) && break
798
+ done
799
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
800
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
801
+ am__untar="$_am_tar -xf -"
802
+ ;;
803
+ plaintar)
804
+ # Must skip GNU tar: if it does not support --format= it doesn't create
805
+ # ustar tarball either.
806
+ (tar --version) >/dev/null 2>&1 && continue
807
+ am__tar='tar chf - "$$tardir"'
808
+ am__tar_='tar chf - "$tardir"'
809
+ am__untar='tar xf -'
810
+ ;;
811
+ pax)
812
+ am__tar='pax -L -x $1 -w "$$tardir"'
813
+ am__tar_='pax -L -x $1 -w "$tardir"'
814
+ am__untar='pax -r'
815
+ ;;
816
+ cpio)
817
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
818
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
819
+ am__untar='cpio -i -H $1 -d'
820
+ ;;
821
+ none)
822
+ am__tar=false
823
+ am__tar_=false
824
+ am__untar=false
825
+ ;;
826
+ esac
827
+
828
+ # If the value was cached, stop now. We just wanted to have am__tar
829
+ # and am__untar set.
830
+ test -n "${am_cv_prog_tar_$1}" && break
831
+
832
+ # tar/untar a dummy directory, and stop if the command works
833
+ rm -rf conftest.dir
834
+ mkdir conftest.dir
835
+ echo GrepMe > conftest.dir/file
836
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
837
+ rm -rf conftest.dir
838
+ if test -s conftest.tar; then
839
+ AM_RUN_LOG([$am__untar <conftest.tar])
840
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
841
+ fi
842
+ done
843
+ rm -rf conftest.dir
844
+
845
+ AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
846
+ AC_MSG_RESULT([$am_cv_prog_tar_$1])])
847
+ AC_SUBST([am__tar])
848
+ AC_SUBST([am__untar])
849
+ ]) # _AM_PROG_TAR
850
+
851
+ m4_include([m4/ax_boost_base.m4])
mosesdecoder/contrib/memscore/config.h.in ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* config.h.in. Generated from configure.ac by autoheader. */
2
+
3
+ /* Define to enable channel scorer */
4
+ #undef ENABLE_CHANNEL_SCORER
5
+
6
+ /* define if the Boost library is available */
7
+ #undef HAVE_BOOST
8
+
9
+ /* Define to 1 if you have the <inttypes.h> header file. */
10
+ #undef HAVE_INTTYPES_H
11
+
12
+ /* flag for IRSTLM */
13
+ #undef HAVE_IRSTLM
14
+
15
+ /* Define to 1 if you have the `gsl' library (-lgsl). */
16
+ #undef HAVE_LIBGSL
17
+
18
+ /* Define to 1 if you have the `gslcblas' library (-lgslcblas). */
19
+ #undef HAVE_LIBGSLCBLAS
20
+
21
+ /* Define to 1 if you have the `m' library (-lm). */
22
+ #undef HAVE_LIBM
23
+
24
+ /* Define to 1 if you have the `z' library (-lz). */
25
+ #undef HAVE_LIBZ
26
+
27
+ /* Define to 1 if you have the <memory.h> header file. */
28
+ #undef HAVE_MEMORY_H
29
+
30
+ /* Define to 1 if the system has the type `ptrdiff_t'. */
31
+ #undef HAVE_PTRDIFF_T
32
+
33
+ /* Define to 1 if you have the <stdint.h> header file. */
34
+ #undef HAVE_STDINT_H
35
+
36
+ /* Define to 1 if you have the <stdlib.h> header file. */
37
+ #undef HAVE_STDLIB_H
38
+
39
+ /* Define to 1 if you have the <strings.h> header file. */
40
+ #undef HAVE_STRINGS_H
41
+
42
+ /* Define to 1 if you have the <string.h> header file. */
43
+ #undef HAVE_STRING_H
44
+
45
+ /* Define to 1 if you have the <sys/stat.h> header file. */
46
+ #undef HAVE_SYS_STAT_H
47
+
48
+ /* Define to 1 if you have the <sys/types.h> header file. */
49
+ #undef HAVE_SYS_TYPES_H
50
+
51
+ /* Define to 1 if you have the <unistd.h> header file. */
52
+ #undef HAVE_UNISTD_H
53
+
54
+ /* Name of package */
55
+ #undef PACKAGE
56
+
57
+ /* Define to the address where bug reports for this package should be sent. */
58
+ #undef PACKAGE_BUGREPORT
59
+
60
+ /* Define to the full name of this package. */
61
+ #undef PACKAGE_NAME
62
+
63
+ /* Define to the full name and version of this package. */
64
+ #undef PACKAGE_STRING
65
+
66
+ /* Define to the one symbol short name of this package. */
67
+ #undef PACKAGE_TARNAME
68
+
69
+ /* Define to the version of this package. */
70
+ #undef PACKAGE_VERSION
71
+
72
+ /* Define to 1 if you have the ANSI C header files. */
73
+ #undef STDC_HEADERS
74
+
75
+ /* Version number of package */
76
+ #undef VERSION
77
+
78
+ /* Define to `unsigned int' if <sys/types.h> does not define. */
79
+ #undef size_t
mosesdecoder/contrib/memscore/datastorage.h ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // memscore - in-memory phrase scoring for Statistical Machine Translation
2
+ // Christian Hardmeier, FBK-irst, Trento, 2010
3
+ // $Id$
4
+
5
+ #ifndef DATASTORAGE_H
6
+ #define DATASTORAGE_H
7
+
8
+ #include "memscore.h"
9
+
10
+ template<class T>
11
+ class DataStorage
12
+ {
13
+ private:
14
+ T *base_;
15
+ size_t pos_;
16
+ size_t chunk_size_;
17
+
18
+ DataStorage() : base_(NULL), pos_(0) {
19
+ int ps = getpagesize();
20
+ chunk_size_ = 10 * ps * sizeof(T);
21
+ base_ = new T[chunk_size_];
22
+ }
23
+
24
+ DataStorage(const DataStorage &cc) {
25
+ abort();
26
+ }
27
+
28
+ ~DataStorage() {}
29
+
30
+ public:
31
+ static DataStorage &get_instance() {
32
+ static DataStorage<T> instance;
33
+ return instance;
34
+ }
35
+
36
+ T *alloc(size_t count) {
37
+ if(count == 0)
38
+ return NULL;
39
+
40
+ // The memory leak is intended.
41
+ if(pos_ + count > chunk_size_) {
42
+ base_ = new T[chunk_size_];
43
+ pos_ = 0;
44
+ }
45
+
46
+ T *ret = base_ + pos_;
47
+ pos_ += count;
48
+ return ret;
49
+ }
50
+ };
51
+
52
+ #endif
mosesdecoder/contrib/memscore/depcomp ADDED
@@ -0,0 +1,530 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #! /bin/sh
2
+ # depcomp - compile a program generating dependencies as side-effects
3
+
4
+ scriptversion=2005-07-09.11
5
+
6
+ # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
7
+
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2, or (at your option)
11
+ # any later version.
12
+
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
+ # 02110-1301, USA.
22
+
23
+ # As a special exception to the GNU General Public License, if you
24
+ # distribute this file as part of a program that contains a
25
+ # configuration script generated by Autoconf, you may include it under
26
+ # the same distribution terms that you use for the rest of that program.
27
+
28
+ # Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
29
+
30
+ case $1 in
31
+ '')
32
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
33
+ exit 1;
34
+ ;;
35
+ -h | --h*)
36
+ cat <<\EOF
37
+ Usage: depcomp [--help] [--version] PROGRAM [ARGS]
38
+
39
+ Run PROGRAMS ARGS to compile a file, generating dependencies
40
+ as side-effects.
41
+
42
+ Environment variables:
43
+ depmode Dependency tracking mode.
44
+ source Source file read by `PROGRAMS ARGS'.
45
+ object Object file output by `PROGRAMS ARGS'.
46
+ DEPDIR directory where to store dependencies.
47
+ depfile Dependency file to output.
48
+ tmpdepfile Temporary file to use when outputing dependencies.
49
+ libtool Whether libtool is used (yes/no).
50
+
51
+ Report bugs to <bug-automake@gnu.org>.
52
+ EOF
53
+ exit $?
54
+ ;;
55
+ -v | --v*)
56
+ echo "depcomp $scriptversion"
57
+ exit $?
58
+ ;;
59
+ esac
60
+
61
+ if test -z "$depmode" || test -z "$source" || test -z "$object"; then
62
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
63
+ exit 1
64
+ fi
65
+
66
+ # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
67
+ depfile=${depfile-`echo "$object" |
68
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
69
+ tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
70
+
71
+ rm -f "$tmpdepfile"
72
+
73
+ # Some modes work just like other modes, but use different flags. We
74
+ # parameterize here, but still list the modes in the big case below,
75
+ # to make depend.m4 easier to write. Note that we *cannot* use a case
76
+ # here, because this file can only contain one case statement.
77
+ if test "$depmode" = hp; then
78
+ # HP compiler uses -M and no extra arg.
79
+ gccflag=-M
80
+ depmode=gcc
81
+ fi
82
+
83
+ if test "$depmode" = dashXmstdout; then
84
+ # This is just like dashmstdout with a different argument.
85
+ dashmflag=-xM
86
+ depmode=dashmstdout
87
+ fi
88
+
89
+ case "$depmode" in
90
+ gcc3)
91
+ ## gcc 3 implements dependency tracking that does exactly what
92
+ ## we want. Yay! Note: for some reason libtool 1.4 doesn't like
93
+ ## it if -MD -MP comes after the -MF stuff. Hmm.
94
+ "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
95
+ stat=$?
96
+ if test $stat -eq 0; then :
97
+ else
98
+ rm -f "$tmpdepfile"
99
+ exit $stat
100
+ fi
101
+ mv "$tmpdepfile" "$depfile"
102
+ ;;
103
+
104
+ gcc)
105
+ ## There are various ways to get dependency output from gcc. Here's
106
+ ## why we pick this rather obscure method:
107
+ ## - Don't want to use -MD because we'd like the dependencies to end
108
+ ## up in a subdir. Having to rename by hand is ugly.
109
+ ## (We might end up doing this anyway to support other compilers.)
110
+ ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
111
+ ## -MM, not -M (despite what the docs say).
112
+ ## - Using -M directly means running the compiler twice (even worse
113
+ ## than renaming).
114
+ if test -z "$gccflag"; then
115
+ gccflag=-MD,
116
+ fi
117
+ "$@" -Wp,"$gccflag$tmpdepfile"
118
+ stat=$?
119
+ if test $stat -eq 0; then :
120
+ else
121
+ rm -f "$tmpdepfile"
122
+ exit $stat
123
+ fi
124
+ rm -f "$depfile"
125
+ echo "$object : \\" > "$depfile"
126
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
127
+ ## The second -e expression handles DOS-style file names with drive letters.
128
+ sed -e 's/^[^:]*: / /' \
129
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
130
+ ## This next piece of magic avoids the `deleted header file' problem.
131
+ ## The problem is that when a header file which appears in a .P file
132
+ ## is deleted, the dependency causes make to die (because there is
133
+ ## typically no way to rebuild the header). We avoid this by adding
134
+ ## dummy dependencies for each header file. Too bad gcc doesn't do
135
+ ## this for us directly.
136
+ tr ' ' '
137
+ ' < "$tmpdepfile" |
138
+ ## Some versions of gcc put a space before the `:'. On the theory
139
+ ## that the space means something, we add a space to the output as
140
+ ## well.
141
+ ## Some versions of the HPUX 10.20 sed can't process this invocation
142
+ ## correctly. Breaking it into two sed invocations is a workaround.
143
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
144
+ rm -f "$tmpdepfile"
145
+ ;;
146
+
147
+ hp)
148
+ # This case exists only to let depend.m4 do its work. It works by
149
+ # looking at the text of this script. This case will never be run,
150
+ # since it is checked for above.
151
+ exit 1
152
+ ;;
153
+
154
+ sgi)
155
+ if test "$libtool" = yes; then
156
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
157
+ else
158
+ "$@" -MDupdate "$tmpdepfile"
159
+ fi
160
+ stat=$?
161
+ if test $stat -eq 0; then :
162
+ else
163
+ rm -f "$tmpdepfile"
164
+ exit $stat
165
+ fi
166
+ rm -f "$depfile"
167
+
168
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
169
+ echo "$object : \\" > "$depfile"
170
+
171
+ # Clip off the initial element (the dependent). Don't try to be
172
+ # clever and replace this with sed code, as IRIX sed won't handle
173
+ # lines with more than a fixed number of characters (4096 in
174
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
175
+ # the IRIX cc adds comments like `#:fec' to the end of the
176
+ # dependency line.
177
+ tr ' ' '
178
+ ' < "$tmpdepfile" \
179
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
180
+ tr '
181
+ ' ' ' >> $depfile
182
+ echo >> $depfile
183
+
184
+ # The second pass generates a dummy entry for each header file.
185
+ tr ' ' '
186
+ ' < "$tmpdepfile" \
187
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
188
+ >> $depfile
189
+ else
190
+ # The sourcefile does not contain any dependencies, so just
191
+ # store a dummy comment line, to avoid errors with the Makefile
192
+ # "include basename.Plo" scheme.
193
+ echo "#dummy" > "$depfile"
194
+ fi
195
+ rm -f "$tmpdepfile"
196
+ ;;
197
+
198
+ aix)
199
+ # The C for AIX Compiler uses -M and outputs the dependencies
200
+ # in a .u file. In older versions, this file always lives in the
201
+ # current directory. Also, the AIX compiler puts `$object:' at the
202
+ # start of each line; $object doesn't have directory information.
203
+ # Version 6 uses the directory in both cases.
204
+ stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
205
+ tmpdepfile="$stripped.u"
206
+ if test "$libtool" = yes; then
207
+ "$@" -Wc,-M
208
+ else
209
+ "$@" -M
210
+ fi
211
+ stat=$?
212
+
213
+ if test -f "$tmpdepfile"; then :
214
+ else
215
+ stripped=`echo "$stripped" | sed 's,^.*/,,'`
216
+ tmpdepfile="$stripped.u"
217
+ fi
218
+
219
+ if test $stat -eq 0; then :
220
+ else
221
+ rm -f "$tmpdepfile"
222
+ exit $stat
223
+ fi
224
+
225
+ if test -f "$tmpdepfile"; then
226
+ outname="$stripped.o"
227
+ # Each line is of the form `foo.o: dependent.h'.
228
+ # Do two passes, one to just change these to
229
+ # `$object: dependent.h' and one to simply `dependent.h:'.
230
+ sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
231
+ sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
232
+ else
233
+ # The sourcefile does not contain any dependencies, so just
234
+ # store a dummy comment line, to avoid errors with the Makefile
235
+ # "include basename.Plo" scheme.
236
+ echo "#dummy" > "$depfile"
237
+ fi
238
+ rm -f "$tmpdepfile"
239
+ ;;
240
+
241
+ icc)
242
+ # Intel's C compiler understands `-MD -MF file'. However on
243
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
244
+ # ICC 7.0 will fill foo.d with something like
245
+ # foo.o: sub/foo.c
246
+ # foo.o: sub/foo.h
247
+ # which is wrong. We want:
248
+ # sub/foo.o: sub/foo.c
249
+ # sub/foo.o: sub/foo.h
250
+ # sub/foo.c:
251
+ # sub/foo.h:
252
+ # ICC 7.1 will output
253
+ # foo.o: sub/foo.c sub/foo.h
254
+ # and will wrap long lines using \ :
255
+ # foo.o: sub/foo.c ... \
256
+ # sub/foo.h ... \
257
+ # ...
258
+
259
+ "$@" -MD -MF "$tmpdepfile"
260
+ stat=$?
261
+ if test $stat -eq 0; then :
262
+ else
263
+ rm -f "$tmpdepfile"
264
+ exit $stat
265
+ fi
266
+ rm -f "$depfile"
267
+ # Each line is of the form `foo.o: dependent.h',
268
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
269
+ # Do two passes, one to just change these to
270
+ # `$object: dependent.h' and one to simply `dependent.h:'.
271
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
272
+ # Some versions of the HPUX 10.20 sed can't process this invocation
273
+ # correctly. Breaking it into two sed invocations is a workaround.
274
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
275
+ sed -e 's/$/ :/' >> "$depfile"
276
+ rm -f "$tmpdepfile"
277
+ ;;
278
+
279
+ tru64)
280
+ # The Tru64 compiler uses -MD to generate dependencies as a side
281
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
282
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
283
+ # dependencies in `foo.d' instead, so we check for that too.
284
+ # Subdirectories are respected.
285
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
286
+ test "x$dir" = "x$object" && dir=
287
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
288
+
289
+ if test "$libtool" = yes; then
290
+ # With Tru64 cc, shared objects can also be used to make a
291
+ # static library. This mecanism is used in libtool 1.4 series to
292
+ # handle both shared and static libraries in a single compilation.
293
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
294
+ #
295
+ # With libtool 1.5 this exception was removed, and libtool now
296
+ # generates 2 separate objects for the 2 libraries. These two
297
+ # compilations output dependencies in in $dir.libs/$base.o.d and
298
+ # in $dir$base.o.d. We have to check for both files, because
299
+ # one of the two compilations can be disabled. We should prefer
300
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
301
+ # automatically cleaned when .libs/ is deleted, while ignoring
302
+ # the former would cause a distcleancheck panic.
303
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
304
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
305
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
306
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
307
+ "$@" -Wc,-MD
308
+ else
309
+ tmpdepfile1=$dir$base.o.d
310
+ tmpdepfile2=$dir$base.d
311
+ tmpdepfile3=$dir$base.d
312
+ tmpdepfile4=$dir$base.d
313
+ "$@" -MD
314
+ fi
315
+
316
+ stat=$?
317
+ if test $stat -eq 0; then :
318
+ else
319
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
320
+ exit $stat
321
+ fi
322
+
323
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
324
+ do
325
+ test -f "$tmpdepfile" && break
326
+ done
327
+ if test -f "$tmpdepfile"; then
328
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
329
+ # That's a tab and a space in the [].
330
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
331
+ else
332
+ echo "#dummy" > "$depfile"
333
+ fi
334
+ rm -f "$tmpdepfile"
335
+ ;;
336
+
337
+ #nosideeffect)
338
+ # This comment above is used by automake to tell side-effect
339
+ # dependency tracking mechanisms from slower ones.
340
+
341
+ dashmstdout)
342
+ # Important note: in order to support this mode, a compiler *must*
343
+ # always write the preprocessed file to stdout, regardless of -o.
344
+ "$@" || exit $?
345
+
346
+ # Remove the call to Libtool.
347
+ if test "$libtool" = yes; then
348
+ while test $1 != '--mode=compile'; do
349
+ shift
350
+ done
351
+ shift
352
+ fi
353
+
354
+ # Remove `-o $object'.
355
+ IFS=" "
356
+ for arg
357
+ do
358
+ case $arg in
359
+ -o)
360
+ shift
361
+ ;;
362
+ $object)
363
+ shift
364
+ ;;
365
+ *)
366
+ set fnord "$@" "$arg"
367
+ shift # fnord
368
+ shift # $arg
369
+ ;;
370
+ esac
371
+ done
372
+
373
+ test -z "$dashmflag" && dashmflag=-M
374
+ # Require at least two characters before searching for `:'
375
+ # in the target name. This is to cope with DOS-style filenames:
376
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
377
+ "$@" $dashmflag |
378
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
379
+ rm -f "$depfile"
380
+ cat < "$tmpdepfile" > "$depfile"
381
+ tr ' ' '
382
+ ' < "$tmpdepfile" | \
383
+ ## Some versions of the HPUX 10.20 sed can't process this invocation
384
+ ## correctly. Breaking it into two sed invocations is a workaround.
385
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
386
+ rm -f "$tmpdepfile"
387
+ ;;
388
+
389
+ dashXmstdout)
390
+ # This case only exists to satisfy depend.m4. It is never actually
391
+ # run, as this mode is specially recognized in the preamble.
392
+ exit 1
393
+ ;;
394
+
395
+ makedepend)
396
+ "$@" || exit $?
397
+ # Remove any Libtool call
398
+ if test "$libtool" = yes; then
399
+ while test $1 != '--mode=compile'; do
400
+ shift
401
+ done
402
+ shift
403
+ fi
404
+ # X makedepend
405
+ shift
406
+ cleared=no
407
+ for arg in "$@"; do
408
+ case $cleared in
409
+ no)
410
+ set ""; shift
411
+ cleared=yes ;;
412
+ esac
413
+ case "$arg" in
414
+ -D*|-I*)
415
+ set fnord "$@" "$arg"; shift ;;
416
+ # Strip any option that makedepend may not understand. Remove
417
+ # the object too, otherwise makedepend will parse it as a source file.
418
+ -*|$object)
419
+ ;;
420
+ *)
421
+ set fnord "$@" "$arg"; shift ;;
422
+ esac
423
+ done
424
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
425
+ touch "$tmpdepfile"
426
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
427
+ rm -f "$depfile"
428
+ cat < "$tmpdepfile" > "$depfile"
429
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
430
+ ' | \
431
+ ## Some versions of the HPUX 10.20 sed can't process this invocation
432
+ ## correctly. Breaking it into two sed invocations is a workaround.
433
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
434
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
435
+ ;;
436
+
437
+ cpp)
438
+ # Important note: in order to support this mode, a compiler *must*
439
+ # always write the preprocessed file to stdout.
440
+ "$@" || exit $?
441
+
442
+ # Remove the call to Libtool.
443
+ if test "$libtool" = yes; then
444
+ while test $1 != '--mode=compile'; do
445
+ shift
446
+ done
447
+ shift
448
+ fi
449
+
450
+ # Remove `-o $object'.
451
+ IFS=" "
452
+ for arg
453
+ do
454
+ case $arg in
455
+ -o)
456
+ shift
457
+ ;;
458
+ $object)
459
+ shift
460
+ ;;
461
+ *)
462
+ set fnord "$@" "$arg"
463
+ shift # fnord
464
+ shift # $arg
465
+ ;;
466
+ esac
467
+ done
468
+
469
+ "$@" -E |
470
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
471
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
472
+ sed '$ s: \\$::' > "$tmpdepfile"
473
+ rm -f "$depfile"
474
+ echo "$object : \\" > "$depfile"
475
+ cat < "$tmpdepfile" >> "$depfile"
476
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
477
+ rm -f "$tmpdepfile"
478
+ ;;
479
+
480
+ msvisualcpp)
481
+ # Important note: in order to support this mode, a compiler *must*
482
+ # always write the preprocessed file to stdout, regardless of -o,
483
+ # because we must use -o when running libtool.
484
+ "$@" || exit $?
485
+ IFS=" "
486
+ for arg
487
+ do
488
+ case "$arg" in
489
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
490
+ set fnord "$@"
491
+ shift
492
+ shift
493
+ ;;
494
+ *)
495
+ set fnord "$@" "$arg"
496
+ shift
497
+ shift
498
+ ;;
499
+ esac
500
+ done
501
+ "$@" -E |
502
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
503
+ rm -f "$depfile"
504
+ echo "$object : \\" > "$depfile"
505
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
506
+ echo " " >> "$depfile"
507
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
508
+ rm -f "$tmpdepfile"
509
+ ;;
510
+
511
+ none)
512
+ exec "$@"
513
+ ;;
514
+
515
+ *)
516
+ echo "Unknown depmode $depmode" 1>&2
517
+ exit 1
518
+ ;;
519
+ esac
520
+
521
+ exit 0
522
+
523
+ # Local Variables:
524
+ # mode: shell-script
525
+ # sh-indentation: 2
526
+ # eval: (add-hook 'write-file-hooks 'time-stamp)
527
+ # time-stamp-start: "scriptversion="
528
+ # time-stamp-format: "%:y-%02m-%02d.%02H"
529
+ # time-stamp-end: "$"
530
+ # End:
mosesdecoder/contrib/memscore/install-sh ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ # install - install a program, script, or datafile
3
+
4
+ scriptversion=2005-05-14.22
5
+
6
+ # This originates from X11R5 (mit/util/scripts/install.sh), which was
7
+ # later released in X11R6 (xc/config/util/install.sh) with the
8
+ # following copyright and license.
9
+ #
10
+ # Copyright (C) 1994 X Consortium
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ # of this software and associated documentation files (the "Software"), to
14
+ # deal in the Software without restriction, including without limitation the
15
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16
+ # sell copies of the Software, and to permit persons to whom the Software is
17
+ # furnished to do so, subject to the following conditions:
18
+ #
19
+ # The above copyright notice and this permission notice shall be included in
20
+ # all copies or substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26
+ # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27
+ # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ #
29
+ # Except as contained in this notice, the name of the X Consortium shall not
30
+ # be used in advertising or otherwise to promote the sale, use or other deal-
31
+ # ings in this Software without prior written authorization from the X Consor-
32
+ # tium.
33
+ #
34
+ #
35
+ # FSF changes to this file are in the public domain.
36
+ #
37
+ # Calling this script install-sh is preferred over install.sh, to prevent
38
+ # `make' implicit rules from creating a file called install from it
39
+ # when there is no Makefile.
40
+ #
41
+ # This script is compatible with the BSD install script, but was written
42
+ # from scratch. It can only install one file at a time, a restriction
43
+ # shared with many OS's install programs.
44
+
45
+ # set DOITPROG to echo to test this script
46
+
47
+ # Don't use :- since 4.3BSD and earlier shells don't like it.
48
+ doit="${DOITPROG-}"
49
+
50
+ # put in absolute paths if you don't have them in your path; or use env. vars.
51
+
52
+ mvprog="${MVPROG-mv}"
53
+ cpprog="${CPPROG-cp}"
54
+ chmodprog="${CHMODPROG-chmod}"
55
+ chownprog="${CHOWNPROG-chown}"
56
+ chgrpprog="${CHGRPPROG-chgrp}"
57
+ stripprog="${STRIPPROG-strip}"
58
+ rmprog="${RMPROG-rm}"
59
+ mkdirprog="${MKDIRPROG-mkdir}"
60
+
61
+ chmodcmd="$chmodprog 0755"
62
+ chowncmd=
63
+ chgrpcmd=
64
+ stripcmd=
65
+ rmcmd="$rmprog -f"
66
+ mvcmd="$mvprog"
67
+ src=
68
+ dst=
69
+ dir_arg=
70
+ dstarg=
71
+ no_target_directory=
72
+
73
+ usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
74
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
75
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
76
+ or: $0 [OPTION]... -d DIRECTORIES...
77
+
78
+ In the 1st form, copy SRCFILE to DSTFILE.
79
+ In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
80
+ In the 4th, create DIRECTORIES.
81
+
82
+ Options:
83
+ -c (ignored)
84
+ -d create directories instead of installing files.
85
+ -g GROUP $chgrpprog installed files to GROUP.
86
+ -m MODE $chmodprog installed files to MODE.
87
+ -o USER $chownprog installed files to USER.
88
+ -s $stripprog installed files.
89
+ -t DIRECTORY install into DIRECTORY.
90
+ -T report an error if DSTFILE is a directory.
91
+ --help display this help and exit.
92
+ --version display version info and exit.
93
+
94
+ Environment variables override the default commands:
95
+ CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
96
+ "
97
+
98
+ while test -n "$1"; do
99
+ case $1 in
100
+ -c) shift
101
+ continue;;
102
+
103
+ -d) dir_arg=true
104
+ shift
105
+ continue;;
106
+
107
+ -g) chgrpcmd="$chgrpprog $2"
108
+ shift
109
+ shift
110
+ continue;;
111
+
112
+ --help) echo "$usage"; exit $?;;
113
+
114
+ -m) chmodcmd="$chmodprog $2"
115
+ shift
116
+ shift
117
+ continue;;
118
+
119
+ -o) chowncmd="$chownprog $2"
120
+ shift
121
+ shift
122
+ continue;;
123
+
124
+ -s) stripcmd=$stripprog
125
+ shift
126
+ continue;;
127
+
128
+ -t) dstarg=$2
129
+ shift
130
+ shift
131
+ continue;;
132
+
133
+ -T) no_target_directory=true
134
+ shift
135
+ continue;;
136
+
137
+ --version) echo "$0 $scriptversion"; exit $?;;
138
+
139
+ *) # When -d is used, all remaining arguments are directories to create.
140
+ # When -t is used, the destination is already specified.
141
+ test -n "$dir_arg$dstarg" && break
142
+ # Otherwise, the last argument is the destination. Remove it from $@.
143
+ for arg
144
+ do
145
+ if test -n "$dstarg"; then
146
+ # $@ is not empty: it contains at least $arg.
147
+ set fnord "$@" "$dstarg"
148
+ shift # fnord
149
+ fi
150
+ shift # arg
151
+ dstarg=$arg
152
+ done
153
+ break;;
154
+ esac
155
+ done
156
+
157
+ if test -z "$1"; then
158
+ if test -z "$dir_arg"; then
159
+ echo "$0: no input file specified." >&2
160
+ exit 1
161
+ fi
162
+ # It's OK to call `install-sh -d' without argument.
163
+ # This can happen when creating conditional directories.
164
+ exit 0
165
+ fi
166
+
167
+ for src
168
+ do
169
+ # Protect names starting with `-'.
170
+ case $src in
171
+ -*) src=./$src ;;
172
+ esac
173
+
174
+ if test -n "$dir_arg"; then
175
+ dst=$src
176
+ src=
177
+
178
+ if test -d "$dst"; then
179
+ mkdircmd=:
180
+ chmodcmd=
181
+ else
182
+ mkdircmd=$mkdirprog
183
+ fi
184
+ else
185
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
186
+ # might cause directories to be created, which would be especially bad
187
+ # if $src (and thus $dsttmp) contains '*'.
188
+ if test ! -f "$src" && test ! -d "$src"; then
189
+ echo "$0: $src does not exist." >&2
190
+ exit 1
191
+ fi
192
+
193
+ if test -z "$dstarg"; then
194
+ echo "$0: no destination specified." >&2
195
+ exit 1
196
+ fi
197
+
198
+ dst=$dstarg
199
+ # Protect names starting with `-'.
200
+ case $dst in
201
+ -*) dst=./$dst ;;
202
+ esac
203
+
204
+ # If destination is a directory, append the input filename; won't work
205
+ # if double slashes aren't ignored.
206
+ if test -d "$dst"; then
207
+ if test -n "$no_target_directory"; then
208
+ echo "$0: $dstarg: Is a directory" >&2
209
+ exit 1
210
+ fi
211
+ dst=$dst/`basename "$src"`
212
+ fi
213
+ fi
214
+
215
+ # This sed command emulates the dirname command.
216
+ dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
217
+
218
+ # Make sure that the destination directory exists.
219
+
220
+ # Skip lots of stat calls in the usual case.
221
+ if test ! -d "$dstdir"; then
222
+ defaultIFS='
223
+ '
224
+ IFS="${IFS-$defaultIFS}"
225
+
226
+ oIFS=$IFS
227
+ # Some sh's can't handle IFS=/ for some reason.
228
+ IFS='%'
229
+ set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
230
+ shift
231
+ IFS=$oIFS
232
+
233
+ pathcomp=
234
+
235
+ while test $# -ne 0 ; do
236
+ pathcomp=$pathcomp$1
237
+ shift
238
+ if test ! -d "$pathcomp"; then
239
+ $mkdirprog "$pathcomp"
240
+ # mkdir can fail with a `File exist' error in case several
241
+ # install-sh are creating the directory concurrently. This
242
+ # is OK.
243
+ test -d "$pathcomp" || exit
244
+ fi
245
+ pathcomp=$pathcomp/
246
+ done
247
+ fi
248
+
249
+ if test -n "$dir_arg"; then
250
+ $doit $mkdircmd "$dst" \
251
+ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
252
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
253
+ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
254
+ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
255
+
256
+ else
257
+ dstfile=`basename "$dst"`
258
+
259
+ # Make a couple of temp file names in the proper directory.
260
+ dsttmp=$dstdir/_inst.$$_
261
+ rmtmp=$dstdir/_rm.$$_
262
+
263
+ # Trap to clean up those temp files at exit.
264
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
265
+ trap '(exit $?); exit' 1 2 13 15
266
+
267
+ # Copy the file name to the temp name.
268
+ $doit $cpprog "$src" "$dsttmp" &&
269
+
270
+ # and set any options; do chmod last to preserve setuid bits.
271
+ #
272
+ # If any of these fail, we abort the whole thing. If we want to
273
+ # ignore errors from any of these, just make sure not to ignore
274
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
275
+ #
276
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
277
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
278
+ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
279
+ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
280
+
281
+ # Now rename the file to the real destination.
282
+ { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
283
+ || {
284
+ # The rename failed, perhaps because mv can't rename something else
285
+ # to itself, or perhaps because mv is so ancient that it does not
286
+ # support -f.
287
+
288
+ # Now remove or move aside any old file at destination location.
289
+ # We try this two ways since rm can't unlink itself on some
290
+ # systems and the destination file might be busy for other
291
+ # reasons. In this case, the final cleanup might fail but the new
292
+ # file should still install successfully.
293
+ {
294
+ if test -f "$dstdir/$dstfile"; then
295
+ $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
296
+ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
297
+ || {
298
+ echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
299
+ (exit 1); exit 1
300
+ }
301
+ else
302
+ :
303
+ fi
304
+ } &&
305
+
306
+ # Now rename the file to the real destination.
307
+ $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
308
+ }
309
+ }
310
+ fi || { (exit 1); exit 1; }
311
+ done
312
+
313
+ # The final little trick to "correctly" pass the exit status to the exit trap.
314
+ {
315
+ (exit 0); exit 0
316
+ }
317
+
318
+ # Local variables:
319
+ # eval: (add-hook 'write-file-hooks 'time-stamp)
320
+ # time-stamp-start: "scriptversion="
321
+ # time-stamp-format: "%:y-%02m-%02d.%02H"
322
+ # time-stamp-end: "$"
323
+ # End:
mosesdecoder/contrib/memscore/lexdecom.cpp ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * File: lexdecom.cpp
3
+ * Author: Felipe Sánchez-Martínez, Universitat d'Alacant <fsanchez@dlsi.ua.es>
4
+ *
5
+ * Created on 2010/01/27
6
+ */
7
+
8
+ #include "lexdecom.h"
9
+ #include "scorer-impl.h"
10
+
11
+ #include <iostream>
12
+ #include <fstream>
13
+
14
+ PhraseScorer*
15
+ LexicalDecompositionPhraseScorer::create_scorer(const char *argv[], int &argp, bool reverse, const PhraseScorerFactory &ptf)
16
+ {
17
+
18
+ if(argv[argp] == NULL)
19
+ usage();
20
+
21
+ String lwfile(argv[argp++]);
22
+
23
+ return new LexicalDecompositionPhraseScorer(ptf.get_phrase_table(), reverse, lwfile, argv, argp, ptf);
24
+ }
25
+
26
+ LexicalDecompositionPhraseScorer::LexicalDecompositionPhraseScorer(PhraseTable &pd, bool reverse,
27
+ const String &weightfile, const char *argv[], int &argp,
28
+ const PhraseScorerFactory &ptf) :
29
+ PhraseScorer(pd, reverse)
30
+ {
31
+
32
+ black_box_scorer = AbsoluteDiscountPhraseScorer::create_scorer(argv, argp, reverse, ptf);
33
+
34
+ std::ifstream wfile(weightfile.c_str());
35
+
36
+ //Code copied from LexicalWeightPhraseScorer; it should be factored !! -- 2010/01/27
37
+
38
+ std::cerr<<"Reading lexical weights from '"<<weightfile<<"' ... ";
39
+
40
+ while(!wfile.eof()) {
41
+ if(wfile.fail()) {
42
+ std::cerr << "Problem reading file: " << weightfile << std::endl;
43
+ exit(1);
44
+ }
45
+ String src, tgt;
46
+ Score weight;
47
+
48
+ wfile >> src >> tgt >> weight;
49
+ Count src_id = PhraseText::index_word(src);
50
+ Count tgt_id = PhraseText::index_word(tgt);
51
+ weight_map_.insert(std::make_pair(std::make_pair(src_id, tgt_id), weight));
52
+ }
53
+
54
+ wfile.close();
55
+ std::cerr<<"done."<<std::endl;
56
+ }
57
+
58
+ Score
59
+ LexicalDecompositionPhraseScorer::get_weight(const String &s_src, const String &s_tgt) const
60
+ {
61
+ //Code copied from LexicalWeightPhraseScorer; it should be factored !! -- 2010/01/27
62
+
63
+ Count src = PhraseText::index_word(s_src);
64
+ Count tgt = PhraseText::index_word(s_tgt);
65
+ return get_weight(src, tgt);
66
+ }
67
+
68
+ inline Score
69
+ LexicalDecompositionPhraseScorer::get_weight(Count src, Count tgt) const
70
+ {
71
+ //Code copied from LexicalWeightPhraseScorer; it should be factored !! -- 2010/01/27
72
+
73
+ WeightMapType_::const_iterator it = weight_map_.find(std::make_pair(src, tgt));
74
+ if(it == weight_map_.end())
75
+ return 0.00001; // default value copied from Philipp Koehn's scorer
76
+ return it->second;
77
+ }
78
+
79
+ void
80
+ LexicalDecompositionPhraseScorer::do_score_phrases()
81
+ {
82
+
83
+ //Estimate p(J|I) = p(src_len|tgt_len)
84
+
85
+ black_box_scorer->score_phrases();
86
+
87
+ std::cerr<<"LexicalDecompositionPhraseScorer::do_score_phrases"<<std::endl;
88
+
89
+ std::map<unsigned, std::map<unsigned, Count> > count_srclen_tgtlen;
90
+ std::map<unsigned, Count> total_tgtlen;
91
+
92
+ for(PhraseTable::iterator it = phrase_table_.begin(); it != phrase_table_.end(); it++) {
93
+ const PhrasePairInfo &ppair = *it;
94
+ PhraseInfo &src = phrase_table_.get_src_phrase(ppair.get_src());
95
+ PhraseInfo &tgt = phrase_table_.get_tgt_phrase(ppair.get_tgt());
96
+ unsigned src_len = src.get_phrase().size();
97
+ unsigned tgt_len = tgt.get_phrase().size();
98
+
99
+ /*//Debug code
100
+ for (unsigned i=0; i<src_len; i++)
101
+ std::cerr<<src.get_phrase().word(i)<<" ";
102
+ std::cerr<<"-> "<<src_len<<" ||| ";
103
+ for (unsigned i=0; i<tgt_len; i++)
104
+ std::cerr<<tgt.get_phrase().word(i)<<" ";
105
+ std::cerr<<"-> "<<tgt_len<<std::endl;
106
+ */
107
+
108
+ count_srclen_tgtlen[src_len][tgt_len]+=ppair.get_count();
109
+ total_tgtlen[tgt_len]+=ppair.get_count();
110
+ }
111
+
112
+ std::map<unsigned, std::map<unsigned, Count> >::iterator its;
113
+ std::map<unsigned, Count>::iterator itt;
114
+
115
+ for (its=count_srclen_tgtlen.begin(); its!=count_srclen_tgtlen.end(); its++) {
116
+ unsigned src_len=its->first;
117
+
118
+ for(itt=its->second.begin(); itt!=its->second.end(); itt++) {
119
+ unsigned tgt_len=itt->first;
120
+ Count cnt=itt->second;
121
+ prob_srclen_tgtlen_[src_len][tgt_len] = static_cast<Score>(cnt)/static_cast<Score>(total_tgtlen[tgt_len]);
122
+ }
123
+ }
124
+ }
125
+
126
+ Score
127
+ LexicalDecompositionPhraseScorer::get_noisy_or_combination(Count src_word, PhraseInfo &tgt_phrase)
128
+ {
129
+
130
+ Score sc=1.0;
131
+
132
+ unsigned tgt_len=tgt_phrase.get_phrase().size();
133
+
134
+ for(unsigned i=0; i<tgt_len; i++) {
135
+ Count tgt_word=tgt_phrase.get_phrase()[i];
136
+ sc *= (1.0 - get_weight(src_word, tgt_word));
137
+ }
138
+
139
+ return (1.0 - sc);
140
+ }
141
+
142
+ Score
143
+ LexicalDecompositionPhraseScorer::do_get_score(const PhraseTable::const_iterator &it)
144
+ {
145
+
146
+ /*
147
+ The implementation of this method relies on the asumption that the
148
+ smoothed probabilities produced by AbsoluteDiscountPhraseScorer
149
+ are deficient.
150
+ */
151
+
152
+ PhraseInfo &src_phrase = phrase_table_.get_src_phrase(it->get_src());
153
+ PhraseInfo &tgt_phrase = phrase_table_.get_tgt_phrase(it->get_tgt());
154
+
155
+ unsigned src_len=src_phrase.get_phrase().size();
156
+ unsigned tgt_len=tgt_phrase.get_phrase().size();
157
+
158
+ Score prod=1.0;
159
+
160
+ for(unsigned j=0; j<src_len; j++)
161
+ prod *= get_noisy_or_combination(src_phrase.get_phrase()[j], tgt_phrase);
162
+
163
+ Score lambda= static_cast<Score>(black_box_scorer->get_discount()) *
164
+ tgt_phrase.get_distinct() / tgt_phrase.get_count();
165
+
166
+ Score ret_value = black_box_scorer->get_score(it) + (lambda * prod * prob_srclen_tgtlen_[src_len][tgt_len]);
167
+
168
+ /*
169
+ //Debug code
170
+ for (unsigned i=0; i<src_len; i++)
171
+ std::cerr<<src_phrase.get_phrase().word(i)<<" ";
172
+ std::cerr<<" ||| ";
173
+ for (unsigned i=0; i<tgt_len; i++)
174
+ std::cerr<<tgt_phrase.get_phrase().word(i)<<" ";
175
+ std::cerr<<"==> discount: "<<black_box_scorer->get_discount()<<"; black box score: "<<black_box_scorer->get_score(it)
176
+ <<"; lambda: "<<lambda<<"; prod: "
177
+ <<prod<<"; prob_srclen_tgtlen_["<<src_len<<"]["<<tgt_len<<"]: "<<prob_srclen_tgtlen_[src_len][tgt_len]
178
+ <<"; count: "<<it->get_count()<<"; score: "<<ret_value;
179
+ std::cerr<<std::endl;
180
+ */
181
+
182
+ return ret_value;
183
+ }
mosesdecoder/contrib/memscore/phraselm.cpp ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // memscore - in-memory phrase scoring for Statistical Machine Translation
2
+ // Christian Hardmeier, FBK-irst, Trento, 2010
3
+ // $Id$
4
+
5
+ #include <cmath>
6
+ #include <iostream>
7
+ #include <fstream>
8
+ #include <sstream>
9
+ #include <string>
10
+
11
+ #include <n_gram.h>
12
+ #include <lmtable.h>
13
+
14
+ #include "phrasetable.h"
15
+ #include "phraselm.h"
16
+
17
+ void PhraseLanguageModel::attach(PhraseInfoList &pilist)
18
+ {
19
+ phrase_info_list_ = &pilist;
20
+ score_idx_ = pilist.register_data(1);
21
+ }
22
+
23
+ void PhraseLanguageModel::compute_statistic()
24
+ {
25
+ compute_lmscores(*phrase_info_list_, false);
26
+ }
27
+
28
+ void PhraseLanguageModel::compute_lmscores(PhraseInfoList &phrase_info_list, bool closed_world)
29
+ {
30
+ lmtable lm;
31
+ std::ifstream lmstream(lmfile_.c_str());
32
+ lm.load(lmstream, lmfile_.c_str(), NULL, 0);
33
+ lm.setlogOOVpenalty(10000000);
34
+
35
+ assert(!computation_done_);
36
+
37
+ Score marginal_score = .0;
38
+ for(PhraseInfoList::iterator it = phrase_info_list.begin(); it != phrase_info_list.end(); ++it) {
39
+ PhraseInfo &pi = *it;
40
+ ngram ng(lm.getDict());
41
+ Score lmscore = 0;
42
+ for(PhraseText::const_string_iterator it = pi.get_phrase().string_begin(); it != pi.get_phrase().string_end(); it++) {
43
+ ng.pushw(it->c_str());
44
+ lmscore += lm.clprob(ng);
45
+ }
46
+
47
+ pi.data(score_idx_) = exp10(lmscore);
48
+ marginal_score += pi.data(score_idx_);
49
+ }
50
+
51
+ if(closed_world)
52
+ for(PhraseInfoList::iterator it = phrase_info_list.begin(); it != phrase_info_list.end(); ++it) {
53
+ PhraseInfo &pi = *it;
54
+ pi.data(score_idx_) /= marginal_score;
55
+ }
56
+
57
+ computation_done_ = true;
58
+ }
59
+
60
+ void ClosedPhraseLanguageModel::compute_statistic()
61
+ {
62
+ compute_lmscores(*phrase_info_list_, true);
63
+ }
mosesdecoder/contrib/memscore/phrasetable.h ADDED
@@ -0,0 +1,710 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // memscore - in-memory phrase scoring for Statistical Machine Translation
2
+ // Christian Hardmeier, FBK-irst, Trento, 2010
3
+ // $Id$
4
+
5
+ #ifndef PHRASETABLE_H
6
+ #define PHRASETABLE_H
7
+
8
+ #include <cassert>
9
+ #include <iostream>
10
+ #include <iterator>
11
+ #include <list>
12
+ #include <map>
13
+ #include <set>
14
+ #include <string>
15
+ #include <vector>
16
+
17
+ #include <boost/bimap.hpp>
18
+ #include <boost/dynamic_bitset.hpp>
19
+ #include <boost/iterator/transform_iterator.hpp>
20
+ #include <boost/pool/object_pool.hpp>
21
+ #include <boost/pool/pool_alloc.hpp>
22
+ #include <boost/ptr_container/ptr_vector.hpp>
23
+ #include <boost/tuple/tuple.hpp>
24
+ #include <boost/tuple/tuple_comparison.hpp>
25
+
26
+ #include "datastorage.h"
27
+ #include "memscore.h"
28
+
29
+ class PhraseText
30
+ {
31
+ friend std::ostream &operator<<(std::ostream &os, const PhraseText &pt);
32
+
33
+ private:
34
+ typedef boost::ptr_vector<Count,boost::view_clone_allocator> WordListType_;
35
+ typedef boost::bimap<String,Count> DictionaryType_;
36
+
37
+ WordListType_ word_list_;
38
+
39
+ static DictionaryType_ dictionary_;
40
+ static Count last_id_;
41
+
42
+ typedef const String &(*LookupFunction_)(Count id);
43
+
44
+ public:
45
+ typedef WordListType_::const_iterator const_iterator;
46
+ typedef boost::transform_iterator<LookupFunction_,WordListType_::const_iterator> const_string_iterator;
47
+ typedef WordListType_::size_type size_type;
48
+
49
+ PhraseText(const String &s);
50
+
51
+ const_iterator begin() const {
52
+ return word_list_.begin();
53
+ }
54
+
55
+ const_iterator end() const {
56
+ return word_list_.end();
57
+ }
58
+
59
+ const_string_iterator string_begin() const {
60
+ return boost::make_transform_iterator(word_list_.begin(), dictionary_lookup);
61
+ }
62
+
63
+ const_string_iterator string_end() const {
64
+ return boost::make_transform_iterator(word_list_.end(), dictionary_lookup);
65
+ }
66
+
67
+ Count operator[](size_type i) const {
68
+ return word_list_[i];
69
+ }
70
+
71
+ const String &word(size_type i) const {
72
+ return dictionary_lookup(operator[](i));
73
+ }
74
+
75
+ size_type size() const {
76
+ return word_list_.size();
77
+ }
78
+
79
+ static const String &dictionary_lookup(Count id) {
80
+ DictionaryType_::right_const_iterator it = dictionary_.right.find(id);
81
+ assert(it != dictionary_.right.end());
82
+ return it->second;
83
+ }
84
+
85
+ static Count index_word(const String &word) {
86
+ Count id;
87
+ DictionaryType_::left_const_iterator it = dictionary_.left.find(word);
88
+ if(it != dictionary_.left.end())
89
+ id = it->second;
90
+ else {
91
+ id = last_id_++;
92
+ dictionary_.insert(DictionaryType_::value_type(word, id));
93
+ }
94
+ return id;
95
+ }
96
+ };
97
+
98
+ class PhraseInfo
99
+ {
100
+ friend class boost::object_pool<PhraseInfo>;
101
+ friend std::ostream &operator<<(std::ostream &os, const PhraseInfo &pt);
102
+
103
+ protected:
104
+ Count data_size_;
105
+
106
+ Count count_;
107
+ Count distinct_;
108
+ PhraseText phrase_;
109
+ Score *data_;
110
+
111
+ Count n1_;
112
+ Count n2_;
113
+ Count n3plus_;
114
+
115
+ PhraseInfo(Count data_size, const String &phrase) :
116
+ data_size_(data_size), count_(0), distinct_(0), phrase_(phrase), n1_(0), n2_(0), n3plus_(0) {
117
+ data_ = DataStorage<Score>::get_instance().alloc(data_size_);
118
+ }
119
+
120
+ public:
121
+ Score &data(Count base, Count i = 0) {
122
+ assert(base + i < data_size_);
123
+ return *(data_ + base + i);
124
+ }
125
+
126
+ const Score &data(Count base, Count i = 0) const {
127
+ assert(base + i < data_size_);
128
+ return *(data_ + base + i);
129
+ }
130
+
131
+ Count get_count() const {
132
+ return count_;
133
+ }
134
+
135
+ void inc_count() {
136
+ count_++;
137
+ }
138
+
139
+ Count get_distinct() const {
140
+ return distinct_;
141
+ }
142
+
143
+ void inc_distinct() {
144
+ distinct_++;
145
+ }
146
+
147
+ const PhraseText &get_phrase() const {
148
+ return phrase_;
149
+ }
150
+
151
+ void inc_n1() {
152
+ n1_++;
153
+ }
154
+
155
+ Count get_n1() {
156
+ return n1_;
157
+ }
158
+
159
+ void inc_n2() {
160
+ n2_++;
161
+ }
162
+
163
+ Count get_n2() {
164
+ return n2_;
165
+ }
166
+
167
+ void inc_n3plus() {
168
+ n3plus_++;
169
+ }
170
+
171
+ Count get_n3plus() {
172
+ return n3plus_;
173
+ }
174
+
175
+ };
176
+
177
+ inline std::ostream &operator<<(std::ostream &os, const PhraseInfo &pt)
178
+ {
179
+ return os << pt.get_phrase();
180
+ }
181
+
182
+ class PhraseInfoList
183
+ {
184
+ protected:
185
+ typedef std::map<String,Phrase> IDMapType_;
186
+ typedef boost::ptr_vector<PhraseInfo,boost::view_clone_allocator> ListType_;
187
+ //typedef std::vector<PhraseInfo *,boost::pool_allocator<PhraseInfo *> > ListType_;
188
+ //typedef std::vector<PhraseInfo> ListType_;
189
+ typedef std::list<PhraseStatistic *> StatListType_;
190
+
191
+ IDMapType_ idmap_;
192
+ ListType_ list_;
193
+ StatListType_ statistics_;
194
+ boost::object_pool<PhraseInfo> phrase_info_pool_;
195
+
196
+ Count data_size_;
197
+ public:
198
+ typedef ListType_::iterator iterator;
199
+ typedef ListType_::const_iterator const_iterator;
200
+ typedef ListType_::size_type size_type;
201
+
202
+ PhraseInfoList() : data_size_(0) {}
203
+
204
+ Phrase index_phrase(const String &s_phr);
205
+ DataIndex register_data(Count size);
206
+ void attach_statistic(PhraseStatistic &s);
207
+ void compute_statistics();
208
+
209
+ PhraseInfo &operator[](Phrase phr) {
210
+ return list_[phr];
211
+ }
212
+
213
+ iterator begin() {
214
+ return list_.begin();
215
+ }
216
+
217
+ iterator end() {
218
+ return list_.end();
219
+ }
220
+
221
+ const_iterator begin() const {
222
+ return list_.begin();
223
+ }
224
+
225
+ const_iterator end() const {
226
+ return list_.end();
227
+ }
228
+
229
+ size_type size() const {
230
+ return list_.size();
231
+ }
232
+
233
+ };
234
+
235
+ class PhraseAlignment
236
+ {
237
+ friend std::ostream &operator<<(std::ostream &os, const PhraseAlignment &pa);
238
+
239
+ private:
240
+ class Alignment
241
+ {
242
+ friend std::ostream &operator<<(std::ostream &os, const Alignment &pa);
243
+
244
+ private:
245
+ typedef boost::tuple<Count,Count,String> AlignmentTuple_;
246
+ typedef std::map<AlignmentTuple_,Count> AlignmentMapType_;
247
+ typedef std::vector<const Alignment *> AlignmentVectorType_;
248
+
249
+ static AlignmentMapType_ alignment_map_;
250
+ static AlignmentVectorType_ alignment_vector_;
251
+
252
+ Count slen_, tlen_;
253
+ boost::dynamic_bitset<unsigned int> matrix_;
254
+
255
+ Alignment(Count slen, Count tlen, const String &alignment);
256
+
257
+ public:
258
+ bool is_aligned(Count s, Count t) const {
259
+ assert(t < tlen_);
260
+ assert(s < slen_);
261
+ return matrix_[t * slen_ + s];
262
+ }
263
+
264
+ Count get_source_length() const {
265
+ return slen_;
266
+ }
267
+
268
+ Count get_target_length() const {
269
+ return tlen_;
270
+ }
271
+
272
+ bool operator<(const Alignment &pa) const {
273
+ if(slen_ < pa.slen_) return true;
274
+ if(tlen_ < pa.tlen_) return true;
275
+ return (matrix_ < pa.matrix_);
276
+ }
277
+
278
+ static Count index_alignment(Count slen, Count tlen, const String &alignment);
279
+
280
+ static const Alignment *find(Count index) {
281
+ return alignment_vector_[index];
282
+ }
283
+ };
284
+ friend std::ostream &operator<<(std::ostream &os, const Alignment &pa);
285
+
286
+ const Alignment *alignment_;
287
+ bool reverse_;
288
+
289
+ public:
290
+ PhraseAlignment(Count index, bool reverse = false) :
291
+ alignment_(Alignment::find(index)), reverse_(reverse) {}
292
+
293
+ bool is_aligned(Count s, Count t) const {
294
+ if(!reverse_)
295
+ return alignment_->is_aligned(s, t);
296
+ else
297
+ return alignment_->is_aligned(t, s);
298
+ }
299
+
300
+ Count get_source_length() const {
301
+ if(!reverse_)
302
+ return alignment_->get_source_length();
303
+ else
304
+ return alignment_->get_target_length();
305
+ }
306
+
307
+ Count get_target_length() const {
308
+ if(!reverse_)
309
+ return alignment_->get_target_length();
310
+ else
311
+ return alignment_->get_source_length();
312
+ }
313
+
314
+ static Count index_alignment(Count slen, Count tlen, const String &alignment) {
315
+ return Alignment::index_alignment(slen, tlen, alignment);
316
+ }
317
+ };
318
+
319
+ typedef std::map<PhrasePair,PhrasePairData> PhrasePairCounts;
320
+
321
+ class PhrasePairInfo
322
+ {
323
+ protected:
324
+ static const Count CONTINUATION_BIT;
325
+
326
+ static bool init_phase_;
327
+ static Count data_nscores_;
328
+ static Count data_ncounts_;
329
+
330
+ enum { COUNT_COUNT_IDX = 0, COUNT_FREE_IDX }; // COUNT_FREE_IDX must remain last!
331
+ enum { SCORE_FREE_IDX = 0 }; // SCORE_FREE_IDX must remain last!
332
+
333
+ Phrase src_, tgt_;
334
+ PhrasePairData data_;
335
+ bool reverse_;
336
+
337
+ void realloc_data(Count nalignments);
338
+
339
+ public:
340
+ typedef std::vector<std::pair<PhraseAlignment,Count> > AlignmentVector;
341
+
342
+ static DataIndex register_score_data(Count size);
343
+ static DataIndex register_count_data(Count size);
344
+
345
+ PhrasePairInfo(Count src, Count tgt, Count alignment, Count count);
346
+
347
+ PhrasePairInfo(Count src, Count tgt, PhrasePairData data, bool reverse = false) : src_(src), tgt_(tgt), data_(data), reverse_(reverse) {
348
+ init_phase_ = false;
349
+ }
350
+
351
+ PhrasePairInfo(const PhrasePairCounts::const_iterator &in) :
352
+ src_(in->first.first), tgt_(in->first.second), data_(in->second), reverse_(false) {}
353
+
354
+ PhrasePairData get_phrase_pair_data() {
355
+ return data_;
356
+ }
357
+
358
+ Phrase get_src() const {
359
+ return !reverse_ ? src_ : tgt_;
360
+ }
361
+
362
+ Phrase get_tgt() const {
363
+ return !reverse_ ? tgt_ : src_;
364
+ }
365
+
366
+ Count get_count() const {
367
+ return count_data(COUNT_COUNT_IDX);
368
+ }
369
+
370
+ Score &score_data(DataIndex base, DataIndex index = 0) {
371
+ return score_data(data_, base, index);
372
+ }
373
+
374
+ const Score &score_data(DataIndex base, DataIndex index = 0) const {
375
+ return score_data(data_, base, index);
376
+ }
377
+
378
+ Count &count_data(DataIndex base, DataIndex index = 0) {
379
+ return count_data(data_, base, index);
380
+ }
381
+
382
+ const Count &count_data(DataIndex base, DataIndex index = 0) const {
383
+ return count_data(data_, base, index);
384
+ }
385
+
386
+ void inc_count() {
387
+ count_data(data_, COUNT_COUNT_IDX)++;
388
+ }
389
+
390
+ AlignmentVector get_alignments() const;
391
+ void add_alignment(Count alignment);
392
+
393
+ private:
394
+ static Score &score_data(PhrasePairData data, DataIndex base, DataIndex index = 0) {
395
+ return *reinterpret_cast<Score *>(data + (base + index) * sizeof(Score));
396
+ }
397
+
398
+ static Count &count_data(PhrasePairData data, DataIndex base, DataIndex index = 0) {
399
+ return *reinterpret_cast<Count *>(data + data_nscores_ * sizeof(Score) + (base + index) * sizeof(Count));
400
+ }
401
+
402
+ static const Count COUNTS_PER_ALIGNMENT = 2;
403
+
404
+ static Count *alignment_data(PhrasePairData data, Count index) {
405
+ return reinterpret_cast<Count *>(data + data_nscores_ * sizeof(Score) + data_ncounts_ * sizeof(Count) + COUNTS_PER_ALIGNMENT * index * sizeof(Count));
406
+ }
407
+
408
+ Count *alignment_data(Count index) {
409
+ return alignment_data(data_, index);
410
+ }
411
+
412
+ const Count *alignment_data(Count index) const {
413
+ return alignment_data(data_, index);
414
+ }
415
+ };
416
+
417
+ class PhraseTable
418
+ {
419
+ public:
420
+ typedef PhrasePairInfo value_type;
421
+
422
+ protected:
423
+ typedef std::iterator_traits<PhrasePairCounts::iterator>::value_type InputEntry_;
424
+ typedef value_type (*EntryTransformer_)(InputEntry_);
425
+
426
+ static value_type pass_entry(InputEntry_ in) {
427
+ return PhrasePairInfo(in.first.first, in.first.second, in.second, false);
428
+ }
429
+
430
+ static value_type swap_src_tgt(InputEntry_ in) {
431
+ return PhrasePairInfo(in.first.first, in.first.second, in.second, true);
432
+ }
433
+
434
+ public:
435
+ typedef boost::transform_iterator<EntryTransformer_,PhrasePairCounts::iterator> iterator;
436
+ typedef boost::transform_iterator<EntryTransformer_,PhrasePairCounts::const_iterator> const_iterator;
437
+
438
+ virtual ~PhraseTable() {}
439
+
440
+ virtual PhraseInfo &get_src_phrase(Phrase src) = 0;
441
+ virtual Count n_src_phrases() const = 0;
442
+ virtual PhraseInfo &get_tgt_phrase(Phrase tgt) = 0;
443
+ virtual Count n_tgt_phrases() const = 0;
444
+ virtual PhrasePairCounts &get_joint_counts() = 0;
445
+ virtual void attach_src_statistic(PhraseStatistic &s) = 0;
446
+ virtual void attach_tgt_statistic(PhraseStatistic &s) = 0;
447
+ virtual void compute_phrase_statistics() = 0;
448
+ virtual DataIndex register_src_data(Count n) = 0;
449
+ virtual DataIndex register_tgt_data(Count n) = 0;
450
+ virtual PhraseTable &reverse() = 0;
451
+
452
+ virtual iterator begin() = 0;
453
+ virtual iterator end() = 0;
454
+ virtual iterator find(PhrasePair p) = 0;
455
+ virtual iterator find(const PhrasePairCounts::iterator &it) = 0;
456
+
457
+ virtual const_iterator begin() const = 0;
458
+ virtual const_iterator end() const = 0;
459
+ virtual const_iterator find(PhrasePair p) const = 0;
460
+ virtual const_iterator find(const PhrasePairCounts::const_iterator &it) const = 0;
461
+
462
+ virtual PhrasePairCounts::iterator raw_begin() = 0;
463
+ virtual PhrasePairCounts::iterator raw_end() = 0;
464
+ virtual PhrasePairCounts::iterator raw_find(PhrasePair p) = 0;
465
+
466
+ virtual PhrasePairCounts::const_iterator raw_begin() const = 0;
467
+ virtual PhrasePairCounts::const_iterator raw_end() const = 0;
468
+ virtual PhrasePairCounts::const_iterator raw_find(PhrasePair p) const = 0;
469
+
470
+ /*
471
+ static iterator swap_iterator(const iterator &it) {
472
+ if(it.functor() == swap_src_tgt)
473
+ return boost::make_transform_iterator(it.base(), pass_entry);
474
+ else if(it.functor() == pass_entry)
475
+ return boost::make_transform_iterator(it.base(), swap_src_tgt);
476
+ else
477
+ abort();
478
+ }
479
+
480
+ static const_iterator swap_iterator(const const_iterator &it) {
481
+ if(it.functor() == swap_src_tgt)
482
+ return boost::make_transform_iterator(it.base(), pass_entry);
483
+ else if(it.functor() == pass_entry)
484
+ return boost::make_transform_iterator(it.base(), swap_src_tgt);
485
+ else
486
+ abort();
487
+ }
488
+ */
489
+ };
490
+
491
+ class ReversePhraseTable : public PhraseTable
492
+ {
493
+ protected:
494
+ PhraseTable &phrase_table_;
495
+
496
+ public:
497
+ ReversePhraseTable(PhraseTable &phrase_table) :
498
+ phrase_table_(phrase_table) {}
499
+
500
+ virtual PhraseInfo &get_src_phrase(Phrase src) {
501
+ return phrase_table_.get_tgt_phrase(src);
502
+ }
503
+
504
+ virtual Count n_src_phrases() const {
505
+ return phrase_table_.n_tgt_phrases();
506
+ }
507
+
508
+ virtual PhraseInfo &get_tgt_phrase(Phrase tgt) {
509
+ return phrase_table_.get_src_phrase(tgt);
510
+ }
511
+
512
+ virtual Count n_tgt_phrases() const {
513
+ return phrase_table_.n_src_phrases();
514
+ }
515
+
516
+ virtual PhrasePairCounts &get_joint_counts() {
517
+ return phrase_table_.get_joint_counts();
518
+ }
519
+
520
+ virtual void attach_src_statistic(PhraseStatistic &s) {
521
+ return phrase_table_.attach_tgt_statistic(s);
522
+ }
523
+
524
+ virtual void attach_tgt_statistic(PhraseStatistic &s) {
525
+ return phrase_table_.attach_src_statistic(s);
526
+ }
527
+
528
+ virtual void compute_phrase_statistics() {
529
+ phrase_table_.compute_phrase_statistics();
530
+ }
531
+
532
+ virtual DataIndex register_src_data(Count n) {
533
+ return phrase_table_.register_tgt_data(n);
534
+ }
535
+
536
+ virtual DataIndex register_tgt_data(Count n) {
537
+ return phrase_table_.register_src_data(n);
538
+ }
539
+
540
+ virtual PhraseTable &reverse() {
541
+ return phrase_table_;
542
+ }
543
+
544
+ virtual iterator begin() {
545
+ return boost::make_transform_iterator(phrase_table_.raw_begin(), swap_src_tgt);
546
+ }
547
+
548
+ virtual iterator end() {
549
+ return boost::make_transform_iterator(raw_end(), swap_src_tgt);
550
+ }
551
+
552
+ virtual iterator find(PhrasePair p) {
553
+ return boost::make_transform_iterator(raw_find(p), swap_src_tgt);
554
+ }
555
+
556
+ virtual iterator find(const PhrasePairCounts::iterator &it) {
557
+ return boost::make_transform_iterator(it, swap_src_tgt);
558
+ }
559
+
560
+ virtual const_iterator begin() const {
561
+ return boost::make_transform_iterator(phrase_table_.raw_begin(), swap_src_tgt);
562
+ }
563
+
564
+ virtual const_iterator end() const {
565
+ return boost::make_transform_iterator(raw_end(), swap_src_tgt);
566
+ }
567
+
568
+ virtual const_iterator find(PhrasePair p) const {
569
+ return boost::make_transform_iterator(raw_find(p), swap_src_tgt);
570
+ }
571
+
572
+ virtual const_iterator find(const PhrasePairCounts::const_iterator &it) const {
573
+ return boost::make_transform_iterator(it, swap_src_tgt);
574
+ }
575
+
576
+ virtual PhrasePairCounts::iterator raw_begin() {
577
+ return phrase_table_.raw_begin();
578
+ }
579
+
580
+ virtual PhrasePairCounts::iterator raw_end() {
581
+ return phrase_table_.raw_end();
582
+ }
583
+
584
+ virtual PhrasePairCounts::iterator raw_find(PhrasePair p) {
585
+ return phrase_table_.raw_find(std::make_pair(p.second, p.first));
586
+ }
587
+
588
+ virtual PhrasePairCounts::const_iterator raw_begin() const {
589
+ return phrase_table_.raw_begin();
590
+ }
591
+
592
+ virtual PhrasePairCounts::const_iterator raw_end() const {
593
+ return phrase_table_.raw_end();
594
+ }
595
+
596
+ virtual PhrasePairCounts::const_iterator raw_find(PhrasePair p) const {
597
+ return phrase_table_.raw_find(std::make_pair(p.second, p.first));
598
+ }
599
+ };
600
+
601
+ class MemoryPhraseTable : public PhraseTable
602
+ {
603
+ protected:
604
+ PhraseInfoList src_info_;
605
+ PhraseInfoList tgt_info_;
606
+ PhrasePairCounts joint_counts_;
607
+
608
+ ReversePhraseTable reverse_;
609
+
610
+ public:
611
+ MemoryPhraseTable() : reverse_(*this) {}
612
+
613
+ void load_data(std::istream &instream);
614
+
615
+ virtual PhraseInfo &get_src_phrase(Phrase src) {
616
+ assert(src < src_info_.size());
617
+ return src_info_[src];
618
+ }
619
+
620
+ virtual Count n_src_phrases() const {
621
+ return src_info_.size();
622
+ }
623
+
624
+ virtual PhraseInfo &get_tgt_phrase(Phrase tgt) {
625
+ assert(tgt < tgt_info_.size());
626
+ return tgt_info_[tgt];
627
+ }
628
+
629
+ virtual Count n_tgt_phrases() const {
630
+ return tgt_info_.size();
631
+ }
632
+
633
+ virtual PhrasePairCounts &get_joint_counts() {
634
+ return joint_counts_;
635
+ }
636
+
637
+ virtual void attach_src_statistic(PhraseStatistic &s);
638
+ virtual void attach_tgt_statistic(PhraseStatistic &s);
639
+ virtual void compute_phrase_statistics();
640
+
641
+ virtual DataIndex register_src_data(Count n) {
642
+ return src_info_.register_data(n);
643
+ }
644
+
645
+ virtual DataIndex register_tgt_data(Count n) {
646
+ return tgt_info_.register_data(n);
647
+ }
648
+
649
+ virtual PhraseTable &reverse() {
650
+ return reverse_;
651
+ }
652
+
653
+ virtual iterator begin() {
654
+ return boost::make_transform_iterator(raw_begin(), pass_entry);
655
+ }
656
+
657
+ virtual iterator end() {
658
+ return boost::make_transform_iterator(raw_end(), pass_entry);
659
+ }
660
+
661
+ virtual iterator find(PhrasePair p) {
662
+ return boost::make_transform_iterator(raw_find(p), pass_entry);
663
+ }
664
+
665
+ virtual iterator find(const PhrasePairCounts::iterator &it) {
666
+ return boost::make_transform_iterator(it, pass_entry);
667
+ }
668
+
669
+ virtual const_iterator begin() const {
670
+ return boost::make_transform_iterator(raw_begin(), pass_entry);
671
+ }
672
+
673
+ virtual const_iterator end() const {
674
+ return boost::make_transform_iterator(raw_end(), pass_entry);
675
+ }
676
+
677
+ virtual const_iterator find(PhrasePair p) const {
678
+ return boost::make_transform_iterator(raw_find(p), pass_entry);
679
+ }
680
+
681
+ virtual const_iterator find(const PhrasePairCounts::const_iterator &it) const {
682
+ return boost::make_transform_iterator(it, pass_entry);
683
+ }
684
+
685
+ virtual PhrasePairCounts::iterator raw_begin() {
686
+ return joint_counts_.begin();
687
+ }
688
+
689
+ virtual PhrasePairCounts::iterator raw_end() {
690
+ return joint_counts_.end();
691
+ }
692
+
693
+ virtual PhrasePairCounts::iterator raw_find(PhrasePair p) {
694
+ return joint_counts_.find(p);
695
+ }
696
+
697
+ virtual PhrasePairCounts::const_iterator raw_begin() const {
698
+ return joint_counts_.begin();
699
+ }
700
+
701
+ virtual PhrasePairCounts::const_iterator raw_end() const {
702
+ return joint_counts_.end();
703
+ }
704
+
705
+ virtual PhrasePairCounts::const_iterator raw_find(PhrasePair p) const {
706
+ return joint_counts_.find(p);
707
+ }
708
+ };
709
+
710
+ #endif
mosesdecoder/contrib/memscore/scorer-impl.h ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // memscore - in-memory phrase scoring for Statistical Machine Translation
2
+ // Christian Hardmeier, FBK-irst, Trento, 2010
3
+ // $Id$
4
+
5
+ #ifndef SCORER_IMPL_H
6
+ #define SCORER_IMPL_H
7
+
8
+ #include "phrasetable.h"
9
+ #include "scorer.h"
10
+
11
+ class MLPhraseScorer : public PhraseScorer
12
+ {
13
+ private:
14
+ explicit MLPhraseScorer(PhraseTable &pd, bool reverse) :
15
+ PhraseScorer(pd, reverse) {}
16
+
17
+ virtual void do_score_phrases();
18
+ virtual Score do_get_score(const PhraseTable::const_iterator &it);
19
+
20
+ public:
21
+ static PhraseScorer *create_scorer(const char *argv[], int &argp, bool reverse, const PhraseScorerFactory &ptf);
22
+ };
23
+
24
+ class WittenBellPhraseScorer : public PhraseScorer
25
+ {
26
+ private:
27
+ explicit WittenBellPhraseScorer(PhraseTable &pd, bool reverse) :
28
+ PhraseScorer(pd, reverse) {}
29
+
30
+ virtual Score do_get_score(const PhraseTable::const_iterator &it);
31
+
32
+ public:
33
+ static PhraseScorer *create_scorer(const char *argv[], int &argp, bool reverse, const PhraseScorerFactory &ptf);
34
+ };
35
+
36
+ class AbsoluteDiscountPhraseScorer : public PhraseScorer
37
+ {
38
+ private:
39
+ Score discount_;
40
+
41
+ explicit AbsoluteDiscountPhraseScorer(PhraseTable &pd, bool reverse) :
42
+ PhraseScorer(pd, reverse) {}
43
+
44
+ virtual void do_score_phrases();
45
+ virtual Score do_get_score(const PhraseTable::const_iterator &it);
46
+
47
+ public:
48
+ Score get_discount();
49
+ static PhraseScorer *create_scorer(const char *argv[], int &argp, bool reverse, const PhraseScorerFactory &ptf);
50
+ };
51
+
52
+ class KNDiscount1PhraseScorer : public PhraseScorer
53
+ {
54
+ private:
55
+ Count total_distinct_;
56
+ Score discount_;
57
+ Count total_count_;
58
+
59
+ explicit KNDiscount1PhraseScorer(PhraseTable &pd, bool reverse) :
60
+ PhraseScorer(pd, reverse) {}
61
+
62
+ virtual void do_score_phrases();
63
+ virtual Score do_get_score(const PhraseTable::const_iterator &it);
64
+
65
+ public:
66
+ static PhraseScorer *create_scorer(const char *argv[], int &argp, bool reverse, const PhraseScorerFactory &ptf);
67
+ };
68
+
69
+ class KNDiscount3PhraseScorer : public PhraseScorer
70
+ {
71
+ private:
72
+ Score discount1_;
73
+ Score discount2_;
74
+ Score discount3plus_;
75
+
76
+ Count total_distinct_n1_;
77
+ Count total_distinct_n2_;
78
+ Count total_distinct_n3plus_;
79
+
80
+ explicit KNDiscount3PhraseScorer(PhraseTable &pd, bool reverse) :
81
+ PhraseScorer(pd, reverse) {}
82
+
83
+ virtual void do_score_phrases();
84
+ virtual Score do_get_score(const PhraseTable::const_iterator &it);
85
+
86
+ public:
87
+ static PhraseScorer *create_scorer(const char *argv[], int &argp, bool reverse, const PhraseScorerFactory &ptf);
88
+ };
89
+
90
+ class LexicalWeightPhraseScorer : public PhraseScorer
91
+ {
92
+ private:
93
+ typedef std::map<std::pair<Count,Count>,Score> WeightMapType_;
94
+
95
+ WeightMapType_ weight_map_;
96
+ bool overall_max_score_;
97
+ const Count null_word_;
98
+
99
+ LexicalWeightPhraseScorer(PhraseTable &pd, bool reverse, const String &weights, bool overall_max = true);
100
+
101
+ Score get_weight(const String &s_src, const String &s_tgt) const;
102
+ Score get_weight(Count src, Count tgt) const;
103
+
104
+ virtual void do_score_phrases();
105
+ virtual Score do_get_score(const PhraseTable::const_iterator &it);
106
+
107
+ public:
108
+ static PhraseScorer *create_scorer(const char *argv[], int &argp, bool reverse, const PhraseScorerFactory &ptf);
109
+ };
110
+
111
+ class ConstantPhraseScorer : public PhraseScorer
112
+ {
113
+ private:
114
+ Score constant_;
115
+
116
+ ConstantPhraseScorer(PhraseTable &pt, bool reverse, Score constant) : PhraseScorer(pt, reverse), constant_(constant) {}
117
+
118
+ virtual Score do_get_score(const PhraseTable::const_iterator &it);
119
+
120
+ public:
121
+ static PhraseScorer *create_scorer(const char *argv[], int &argp, bool reverse, const PhraseScorerFactory &ptf);
122
+ };
123
+
124
+ #endif
mosesdecoder/contrib/promix/README.md ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ promix - for training translation model interpolation weights using PRO
2
+
3
+ Author: Barry Haddow <bhaddow [AT] inf.ed.ac.uk>
4
+
5
+ ABOUT
6
+ -----
7
+
8
+ The code here provides the "inner loop" for a batch tuning algorithm (like MERT) which
9
+ optimises phrase table interpolation weights at the same time as the standard linear
10
+ model weights. Interpolation of the phrase tables uses the "naive" method of tmcombine.
11
+
12
+ Currently the interpolation only works for two phrase tables, but will soon
13
+ be extended to work for more than two.
14
+
15
+
16
+ REQUIREMENTS
17
+ ------------
18
+ The scripts require the Moses Python interface (in contrib/python). It should be built
19
+ first, following the instructions in that directory.
20
+
21
+ The scripts also require scipy and numpy. They have been tested with the following versions:
22
+
23
+ * Python 2.7
24
+ * Scipy 0.11.0
25
+ * Numpy 1.6.2
26
+
27
+ Run the test.py script to check that everything is functioning correctly.
28
+
29
+
30
+ USAGE
31
+ -----
32
+ Since the code in this directory provides the inner loop for a batch tuning algorithm,
33
+ it is run from the increasingly inaccurately named mert-moses.pl. If you want to run
34
+ the optimiser directly, run `main.py -h` for usage.
35
+
36
+ A sample command for mert-moses.pl is as follows:
37
+
38
+ MOSES/scripts/training/mert-moses.pl \
39
+ input-file ref-file \
40
+ decoder \
41
+ ini-file \
42
+ --promix-training MOSES/contrib/promix/main.py \
43
+ --maximum-iterations 15 \
44
+ --promix-table phrase-table-1 \
45
+ --promix-table phrase-table-2 \
46
+ --filtercmd "MOSES/scripts/training/filter-model-given-input.pl --Binarizer MOSES/bin/processPhraseTable" \
47
+ --nbest 100 --working-dir ./tmp --decoder-flags "-threads 4 -v 0 " \
48
+ --rootdir MOSES/scripts -mertdir MOSES/bin \
49
+ --return-best-dev
50
+
51
+ Note that promix training requires a filter and binarise script, and that the phrase table
52
+ referenced in the ini file is not used. The argument `--return-best-dev` is not essential,
53
+ but recommended.
54
+
55
+
56
+ REFERENCES
57
+ ----------
58
+
59
+ The code here was created for:
60
+
61
+ Haddow, Barry (2013) Applying Pairwise Ranked Optimisation to
62
+ Improve the Interpolation of Translation Models. In: Proceedings of NAACL 2013
63
+
64
+ See also:
65
+
66
+ Sennrich, Rico (2012). Perplexity Minimization for Translation Model Domain Adaptation in Statistical Machine Translation. In: Proceedings of EACL 2012.
mosesdecoder/contrib/promix/bleu.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ from math import exp,log
4
+
5
+ class BleuScoreException(Exception):
6
+ pass
7
+
8
+ class BleuScorer:
9
+ def __init__(self):
10
+ """References should be a list. If each element is a string, assume
11
+ they are filenames, if a list, assume tokenised strings"""
12
+ self.smooth = 1.0
13
+ self.order = 4
14
+
15
+ def score(self,scores):
16
+ if len(scores) != self.order*2+1:
17
+ raise BleuScoreException("Wrong number of scores. Expected %d, but found %d" %
18
+ (self.order*2+1, len(scores)))
19
+ logbleu = 0.0
20
+ for j in range(self.order):
21
+ logbleu += log(scores[2*j] + self.smooth) - log(scores[2*j+1] + self.smooth)
22
+ logbleu /= self.order
23
+ brevity = 1.0 - float(scores[-1]) / scores[1]
24
+ if brevity < 0:
25
+ logbleu += brevity
26
+ return exp(logbleu)
27
+
mosesdecoder/contrib/promix/coll.py ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
2
+ # Passes Python2.7's test suite and incorporates all the latest updates.
3
+
4
+ # From http://code.activestate.com/recipes/576693/
5
+
6
+ try:
7
+ from thread import get_ident as _get_ident
8
+ except ImportError:
9
+ from dummy_thread import get_ident as _get_ident
10
+
11
+ try:
12
+ from _abcoll import KeysView, ValuesView, ItemsView
13
+ except ImportError:
14
+ pass
15
+
16
+
17
+ class OrderedDict(dict):
18
+ 'Dictionary that remembers insertion order'
19
+ # An inherited dict maps keys to values.
20
+ # The inherited dict provides __getitem__, __len__, __contains__, and get.
21
+ # The remaining methods are order-aware.
22
+ # Big-O running times for all methods are the same as for regular dictionaries.
23
+
24
+ # The internal self.__map dictionary maps keys to links in a doubly linked list.
25
+ # The circular doubly linked list starts and ends with a sentinel element.
26
+ # The sentinel element never gets deleted (this simplifies the algorithm).
27
+ # Each link is stored as a list of length three: [PREV, NEXT, KEY].
28
+
29
+ def __init__(self, *args, **kwds):
30
+ '''Initialize an ordered dictionary. Signature is the same as for
31
+ regular dictionaries, but keyword arguments are not recommended
32
+ because their insertion order is arbitrary.
33
+
34
+ '''
35
+ if len(args) > 1:
36
+ raise TypeError('expected at most 1 arguments, got %d' % len(args))
37
+ try:
38
+ self.__root
39
+ except AttributeError:
40
+ self.__root = root = [] # sentinel node
41
+ root[:] = [root, root, None]
42
+ self.__map = {}
43
+ self.__update(*args, **kwds)
44
+
45
+ def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
46
+ 'od.__setitem__(i, y) <==> od[i]=y'
47
+ # Setting a new item creates a new link which goes at the end of the linked
48
+ # list, and the inherited dictionary is updated with the new key/value pair.
49
+ if key not in self:
50
+ root = self.__root
51
+ last = root[0]
52
+ last[1] = root[0] = self.__map[key] = [last, root, key]
53
+ dict_setitem(self, key, value)
54
+
55
+ def __delitem__(self, key, dict_delitem=dict.__delitem__):
56
+ 'od.__delitem__(y) <==> del od[y]'
57
+ # Deleting an existing item uses self.__map to find the link which is
58
+ # then removed by updating the links in the predecessor and successor nodes.
59
+ dict_delitem(self, key)
60
+ link_prev, link_next, key = self.__map.pop(key)
61
+ link_prev[1] = link_next
62
+ link_next[0] = link_prev
63
+
64
+ def __iter__(self):
65
+ 'od.__iter__() <==> iter(od)'
66
+ root = self.__root
67
+ curr = root[1]
68
+ while curr is not root:
69
+ yield curr[2]
70
+ curr = curr[1]
71
+
72
+ def __reversed__(self):
73
+ 'od.__reversed__() <==> reversed(od)'
74
+ root = self.__root
75
+ curr = root[0]
76
+ while curr is not root:
77
+ yield curr[2]
78
+ curr = curr[0]
79
+
80
+ def clear(self):
81
+ 'od.clear() -> None. Remove all items from od.'
82
+ try:
83
+ for node in self.__map.itervalues():
84
+ del node[:]
85
+ root = self.__root
86
+ root[:] = [root, root, None]
87
+ self.__map.clear()
88
+ except AttributeError:
89
+ pass
90
+ dict.clear(self)
91
+
92
+ def popitem(self, last=True):
93
+ '''od.popitem() -> (k, v), return and remove a (key, value) pair.
94
+ Pairs are returned in LIFO order if last is true or FIFO order if false.
95
+
96
+ '''
97
+ if not self:
98
+ raise KeyError('dictionary is empty')
99
+ root = self.__root
100
+ if last:
101
+ link = root[0]
102
+ link_prev = link[0]
103
+ link_prev[1] = root
104
+ root[0] = link_prev
105
+ else:
106
+ link = root[1]
107
+ link_next = link[1]
108
+ root[1] = link_next
109
+ link_next[0] = root
110
+ key = link[2]
111
+ del self.__map[key]
112
+ value = dict.pop(self, key)
113
+ return key, value
114
+
115
+ # -- the following methods do not depend on the internal structure --
116
+
117
+ def keys(self):
118
+ 'od.keys() -> list of keys in od'
119
+ return list(self)
120
+
121
+ def values(self):
122
+ 'od.values() -> list of values in od'
123
+ return [self[key] for key in self]
124
+
125
+ def items(self):
126
+ 'od.items() -> list of (key, value) pairs in od'
127
+ return [(key, self[key]) for key in self]
128
+
129
+ def iterkeys(self):
130
+ 'od.iterkeys() -> an iterator over the keys in od'
131
+ return iter(self)
132
+
133
+ def itervalues(self):
134
+ 'od.itervalues -> an iterator over the values in od'
135
+ for k in self:
136
+ yield self[k]
137
+
138
+ def iteritems(self):
139
+ 'od.iteritems -> an iterator over the (key, value) items in od'
140
+ for k in self:
141
+ yield (k, self[k])
142
+
143
+ def update(*args, **kwds):
144
+ '''od.update(E, **F) -> None. Update od from dict/iterable E and F.
145
+
146
+ If E is a dict instance, does: for k in E: od[k] = E[k]
147
+ If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
148
+ Or if E is an iterable of items, does: for k, v in E: od[k] = v
149
+ In either case, this is followed by: for k, v in F.items(): od[k] = v
150
+
151
+ '''
152
+ if len(args) > 2:
153
+ raise TypeError('update() takes at most 2 positional '
154
+ 'arguments (%d given)' % (len(args),))
155
+ elif not args:
156
+ raise TypeError('update() takes at least 1 argument (0 given)')
157
+ self = args[0]
158
+ # Make progressively weaker assumptions about "other"
159
+ other = ()
160
+ if len(args) == 2:
161
+ other = args[1]
162
+ if isinstance(other, dict):
163
+ for key in other:
164
+ self[key] = other[key]
165
+ elif hasattr(other, 'keys'):
166
+ for key in other.keys():
167
+ self[key] = other[key]
168
+ else:
169
+ for key, value in other:
170
+ self[key] = value
171
+ for key, value in kwds.items():
172
+ self[key] = value
173
+
174
+ __update = update # let subclasses override update without breaking __init__
175
+
176
+ __marker = object()
177
+
178
+ def pop(self, key, default=__marker):
179
+ '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
180
+ If key is not found, d is returned if given, otherwise KeyError is raised.
181
+
182
+ '''
183
+ if key in self:
184
+ result = self[key]
185
+ del self[key]
186
+ return result
187
+ if default is self.__marker:
188
+ raise KeyError(key)
189
+ return default
190
+
191
+ def setdefault(self, key, default=None):
192
+ 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
193
+ if key in self:
194
+ return self[key]
195
+ self[key] = default
196
+ return default
197
+
198
+ def __repr__(self, _repr_running={}):
199
+ 'od.__repr__() <==> repr(od)'
200
+ call_key = id(self), _get_ident()
201
+ if call_key in _repr_running:
202
+ return '...'
203
+ _repr_running[call_key] = 1
204
+ try:
205
+ if not self:
206
+ return '%s()' % (self.__class__.__name__,)
207
+ return '%s(%r)' % (self.__class__.__name__, self.items())
208
+ finally:
209
+ del _repr_running[call_key]
210
+
211
+ def __reduce__(self):
212
+ 'Return state information for pickling'
213
+ items = [[k, self[k]] for k in self]
214
+ inst_dict = vars(self).copy()
215
+ for k in vars(OrderedDict()):
216
+ inst_dict.pop(k, None)
217
+ if inst_dict:
218
+ return (self.__class__, (items,), inst_dict)
219
+ return self.__class__, (items,)
220
+
221
+ def copy(self):
222
+ 'od.copy() -> a shallow copy of od'
223
+ return self.__class__(self)
224
+
225
+ @classmethod
226
+ def fromkeys(cls, iterable, value=None):
227
+ '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
228
+ and values equal to v (which defaults to None).
229
+
230
+ '''
231
+ d = cls()
232
+ for key in iterable:
233
+ d[key] = value
234
+ return d
235
+
236
+ def __eq__(self, other):
237
+ '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
238
+ while comparison to a regular mapping is order-insensitive.
239
+
240
+ '''
241
+ if isinstance(other, OrderedDict):
242
+ return len(self)==len(other) and self.items() == other.items()
243
+ return dict.__eq__(self, other)
244
+
245
+ def __ne__(self, other):
246
+ return not self == other
247
+
248
+ # -- the following methods are only used in Python 2.7 --
249
+
250
+ def viewkeys(self):
251
+ "od.viewkeys() -> a set-like object providing a view on od's keys"
252
+ return KeysView(self)
253
+
254
+ def viewvalues(self):
255
+ "od.viewvalues() -> an object providing a view on od's values"
256
+ return ValuesView(self)
257
+
258
+ def viewitems(self):
259
+ "od.viewitems() -> a set-like object providing a view on od's items"
260
+ return ItemsView(self)
mosesdecoder/contrib/promix/main.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ #
4
+ # Implementation of PRO training and extensions to train phrase weights
5
+ #
6
+
7
+ import gzip
8
+ import logging
9
+ from numpy import array
10
+ import optparse
11
+ import os.path
12
+ import sys
13
+
14
+ from nbest import *
15
+ from sampler import *
16
+ from train import *
17
+
18
+
19
+ logging.basicConfig(format = "%(asctime)-15s %(message)s")
20
+ log = logging.getLogger('main')
21
+ log.setLevel(logging.DEBUG)
22
+
23
+ class Config:
24
+ def __init__(self):
25
+ self.parser = optparse.OptionParser(usage="%prog [options] ")
26
+ self.parser.add_option("-t", "--trainer", action="store",\
27
+ dest="trainer", metavar="TYPE", type="choice", choices=("pro","mix"),\
28
+ default="pro",\
29
+ help="type of trainer to run (pro,mix)")
30
+ self.parser.add_option("-n", "--nbest", action="append", \
31
+ dest="nbest", metavar="NBEST-FILE",\
32
+ help="nbest output file(s) from decoder")
33
+ self.parser.add_option("-S", "--scfile", action="append",\
34
+ dest="score", metavar="SCORE-FILE",\
35
+ help="score file(s) from extractor (in same order as nbests)")
36
+ self.parser.add_option("-p", "--phrase-table" , action="append",\
37
+ dest="ttable", metavar="TTABLE",\
38
+ help="ttable to be used in mixture model training")
39
+ self.parser.add_option("-i", "--input-file", action="store",\
40
+ dest="input_file", metavar="INPUT-FILE",
41
+ help="source text file")
42
+ self.parser.add_option("-m", "--moses-bin-dir", action="store",\
43
+ dest="moses_bin_dir", metavar="DIR",
44
+ help="directory containing Moses binaries",
45
+ default=os.path.expanduser("~/moses/bin"))
46
+ self.nbest_files = []
47
+ self.score_files = []
48
+ self.ttables = []
49
+
50
+ def parse(self,args=sys.argv[1:]):
51
+ (options,args) = self.parser.parse_args(args)
52
+ self.nbest_files = options.nbest
53
+ self.score_files = options.score
54
+ self.ttables = options.ttable
55
+ self.input_file = options.input_file
56
+ self.trainer = options.trainer
57
+ self.moses_bin_dir = options.moses_bin_dir
58
+ if not self.nbest_files:
59
+ self.nbest_files = ["data/esen.nc.nbest.segment"]
60
+ if not self.score_files:
61
+ self.score_files = ["data/esen.nc.scores"]
62
+ if len(self.nbest_files) != len(self.score_files):
63
+ self.parser.error("Must have equal numbers of score files and nbest files")
64
+ if self.trainer == "mix":
65
+ if not self.input_file or not self.ttables:
66
+ self.parser.error("Need to specify input file and ttables for mix training")
67
+ #if len(self.ttables) != 2:
68
+ # self.parser.error("Can only train mix model with 2 ttables at the moment")
69
+
70
+ def main():
71
+ config = Config()
72
+ config.parse()
73
+
74
+ samples = []
75
+ sampler = HopkinsMaySampler()
76
+ nbests = 0
77
+ for nbest_file,score_data_file in zip(config.nbest_files,config.score_files):
78
+ log.debug("nbest: " + nbest_file + "; score:" + score_data_file)
79
+ segments = False
80
+ if config.trainer == "mix": segments = True
81
+ for nbest in get_scored_nbests(nbest_file, score_data_file, config.input_file, segments=segments):
82
+ samples += sampler.sample(nbest)
83
+ nbests += 1
84
+ log.debug("Samples loaded")
85
+ trainer = None
86
+ if config.trainer == "mix":
87
+ # Add the phrase table scores
88
+ scorer = MosesPhraseScorer(config.ttables)
89
+ log.debug("Scoring samples...")
90
+ for sample in samples:
91
+ scorer.add_scores(sample.hyp1)
92
+ scorer.add_scores(sample.hyp2)
93
+ log.debug("...samples scored")
94
+ trainer = MixtureModelTrainer(samples)
95
+ elif config.trainer == "pro":
96
+ trainer = ProTrainer(samples)
97
+ else: assert(0)
98
+ log.debug("Starting training...")
99
+ weights,mix_weights = trainer.train(debug=False)
100
+ log.debug("...training complete")
101
+ for i,w in enumerate(weights):
102
+ print "F%d %10.8f" % (i,w)
103
+ for i,f in enumerate(mix_weights):
104
+ for j,w in enumerate(f):
105
+ print "M%d_%d %10.8f" % (i,j,w)
106
+
107
+
108
+
109
+
110
+
111
+ if __name__ == "__main__":
112
+ main()
mosesdecoder/contrib/promix/nbest.py ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ import gzip
4
+ import os
5
+ import re
6
+ import numpy as np
7
+ import sys
8
+
9
+ from bleu import BleuScorer
10
+ from coll import OrderedDict
11
+ # Edit to set moses python path
12
+ sys.path.append(os.path.dirname(__file__) + "/../python")
13
+ import moses.dictree as binpt
14
+
15
+ class DataFormatException(Exception):
16
+ pass
17
+
18
+ class Hypothesis:
19
+ def __init__(self,text,fv,segments=False):
20
+ self.alignment = [] #only stored for segmented hypos
21
+ self.tokens = [] #only stored for segmented hypos
22
+ if not segments:
23
+ self.text = text
24
+ # Triples of (source-start, source-end, target-end) where segments end positions
25
+ # are 1 beyond the last token
26
+ else:
27
+ # recover segmentation
28
+ self.tokens = []
29
+ align_re = re.compile("\|(\d+)-(\d+)\|")
30
+ for token in text.split():
31
+ match = align_re.match(token)
32
+ if match:
33
+ self.alignment.append\
34
+ ((int(match.group(1)), 1+int(match.group(2)), len(self.tokens)))
35
+ else:
36
+ self.tokens.append(token)
37
+ self.text = " ".join(self.tokens)
38
+ if not self.alignment:
39
+ raise DataFormatException("Expected segmentation information not found in nbest")
40
+
41
+
42
+ self.fv = np.array(fv)
43
+ self.score = 0
44
+
45
+ def __str__(self):
46
+ return "{text=%s fv=%s score=%5.4f}" % (self.text, str(self.fv), self.score)
47
+
48
+ class NBestList:
49
+ def __init__(self,id):
50
+ self.id = id
51
+ self.hyps = []
52
+
53
+ # Maps feature ids (short feature names) to their values
54
+ _feature_index = {}
55
+ def set_feature_start(name,index):
56
+ indexes = _feature_index.get(name, [index,0])
57
+ indexes[0] = index
58
+ _feature_index[name] = indexes
59
+
60
+ def set_feature_end(name,index):
61
+ indexes = _feature_index.get(name, [0,index])
62
+ indexes[1] = index
63
+ _feature_index[name] = indexes
64
+
65
+ def get_feature_index(name):
66
+ return _feature_index.get(name, [0,0])
67
+
68
+ def get_nbests(nbest_file, segments=False):
69
+ """Iterate through nbest lists"""
70
+ if nbest_file.endswith("gz"):
71
+ fh = gzip.GzipFile(nbest_file)
72
+ else:
73
+ fh = open(nbest_file)
74
+ lineno = 0
75
+ nbest = None
76
+ for line in fh:
77
+ fields = line.split(" ||| ")
78
+ if len(fields) != 4:
79
+ raise DataFormatException("nbest(%d): %s" % (lineno,line))
80
+ (id, text, scores, total) = fields
81
+ if nbest and nbest.id != id:
82
+ yield nbest
83
+ nbest = None
84
+ if not nbest:
85
+ nbest = NBestList(id)
86
+ fv = []
87
+ score_name = None
88
+ for score in scores.split():
89
+ if score.endswith(":"):
90
+ score = score[:-1]
91
+ if score_name:
92
+ set_feature_end(score_name,len(fv))
93
+ score_name = score
94
+ set_feature_start(score_name,len(fv))
95
+ else:
96
+ fv.append(float(score))
97
+ if score_name: set_feature_end(score_name,len(fv))
98
+ hyp = Hypothesis(text[:-1],fv,segments)
99
+ nbest.hyps.append(hyp)
100
+ if nbest:
101
+ yield nbest
102
+
103
+ def get_scores(score_data_file):
104
+ """Iterate through the score data, returning a set of scores for each sentence"""
105
+ scorer = BleuScorer()
106
+ fh = open(score_data_file)
107
+ lineno = 0
108
+ score_vectors = None
109
+ for line in fh:
110
+ if line.startswith("SCORES_TXT_BEGIN"):
111
+ score_vectors = []
112
+ elif line.startswith("SCORES_TXT_END"):
113
+ scores = [scorer.score(score_vector) for score_vector in score_vectors]
114
+ yield scores
115
+ else:
116
+ score_vectors.append([float(i) for i in line[:-1].split()])
117
+
118
+
119
+ def get_scored_nbests(nbest_file, score_data_file, input_file, segments=False):
120
+ score_gen = get_scores(score_data_file)
121
+ input_gen = None
122
+ if input_file: input_gen = open(input_file)
123
+ try:
124
+ for nbest in get_nbests(nbest_file, segments=segments):
125
+ scores = score_gen.next()
126
+ if len(scores) != len(nbest.hyps):
127
+ raise DataFormatException("Length of nbest %s does not match score list (%d != %d)" %
128
+ (nbest.id,len(nbest.hyps), len(scores)))
129
+ input_line = None
130
+ if input_gen:
131
+ input_line = input_gen.next()[:-1]
132
+ for hyp,score in zip(nbest.hyps, scores):
133
+ hyp.score = score
134
+ hyp.input_line = input_line
135
+ yield nbest
136
+
137
+ except StopIteration:
138
+ raise DataFormatException("Score file shorter than nbest list file")
139
+
140
+ class PhraseCache:
141
+ """An LRU cache for ttable lookups"""
142
+ def __init__(self, max_size):
143
+ self.max_size = max_size
144
+ self.pairs_to_scores = OrderedDict()
145
+
146
+ def get(self, source, target):
147
+ key = (source,target)
148
+ scores = self.pairs_to_scores.get(key,None)
149
+ if scores:
150
+ # cache hit - update access time
151
+ del self.pairs_to_scores[key]
152
+ self.pairs_to_scores[key] = scores
153
+ return scores
154
+
155
+ def add(self,source,target,scores):
156
+ key = (source,target)
157
+ self.pairs_to_scores[key] = scores
158
+ while len(self.pairs_to_scores) > self.max_size:
159
+ self.pairs_to_scores.popitem(last=False)
160
+
161
+ #
162
+ # Should I store full lists of options, or just phrase pairs?
163
+ # Should probably store phrase-pairs, but may want to add
164
+ # high scoring pairs (say, 20?) when I load the translations
165
+ # of a given phrase
166
+ #
167
+
168
+ class CachedPhraseTable:
169
+ def __init__(self,ttable_file,nscores=5,cache_size=20000):
170
+ wa = False
171
+ if binpt.PhraseDictionaryTree.canLoad(ttable_file,True):
172
+ # assume word alignment is included
173
+ wa = True
174
+ self.ttable = binpt.PhraseDictionaryTree(ttable_file,nscores = nscores,wa = wa, tableLimit=0)
175
+ self.cache = PhraseCache(cache_size)
176
+ self.nscores = nscores
177
+
178
+ def get_scores(self,phrase):
179
+ source = " ".join(phrase[0])
180
+ target_tuple = tuple(phrase[1])
181
+ target = " ".join(target_tuple)
182
+ scores = self.cache.get(source,target)
183
+ if not scores:
184
+ # cache miss
185
+ scores = [0] * (self.nscores-1) # ignore penalty
186
+ entries = self.ttable.query(source, converter=None)
187
+ # find correct target
188
+ for entry in entries:
189
+ if entry.rhs == target_tuple:
190
+ scores = entry.scores[:-1]
191
+ break
192
+ #print "QUERY",source,"|||",target,"|||",scores
193
+ self.cache.add(source,target,scores)
194
+ #else:
195
+ # print "CACHE",source,"|||",target,"|||",scores
196
+ return scores
197
+
198
+
199
+ class MosesPhraseScorer:
200
+ def __init__(self,ttable_files, cache_size=20000):
201
+ self.ttables = []
202
+ for ttable_file in ttable_files:
203
+ self.ttables.append(CachedPhraseTable(ttable_file, cache_size=cache_size))
204
+
205
+ def add_scores(self, hyp):
206
+ """Add the phrase scores to a hypothesis"""
207
+ # Collect up the phrase pairs
208
+ phrases = []
209
+ source_tokens = hyp.input_line.split()
210
+ tgt_st = 0
211
+ if not hyp.alignment:
212
+ raise DataFormatException("Alignments missing from: " + str(hyp))
213
+ for src_st,src_end,tgt_end in hyp.alignment:
214
+ phrases.append((source_tokens[src_st:src_end], hyp.tokens[tgt_st:tgt_end]))
215
+ tgt_st = tgt_end
216
+ # Look up the scores
217
+ phrase_scores = []
218
+ for ttable in self.ttables:
219
+ phrase_scores.append([])
220
+ for phrase in phrases:
221
+ phrase_scores[-1].append(ttable.get_scores(phrase))
222
+ # phrase_scores = np.array(phrase_scores)
223
+ # eps = np.exp(-100)
224
+ # phrase_scores[phrase_scores<eps]=eps
225
+ floor = np.exp(-100)
226
+ phrase_scores = np.clip(np.array(phrase_scores), floor, np.inf)
227
+ hyp.phrase_scores = phrase_scores
228
+
229
+
230
+
mosesdecoder/contrib/promix/test.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ import unittest
4
+
5
+ import test_bleu
6
+ import test_main
7
+ import test_moses
8
+ import test_nbest
9
+ import test_sampler
10
+ import test_train
11
+
12
+ def main():
13
+ test_list = []
14
+ test_list.append(test_bleu.suite)
15
+ test_list.append(test_main.suite)
16
+ # test_list.append(test_moses.suite)
17
+ test_list.append(test_nbest.suite)
18
+ test_list.append(test_sampler.suite)
19
+ test_list.append(test_train.suite)
20
+
21
+ suite = unittest.TestSuite(test_list)
22
+ unittest.TextTestRunner().run(suite)
23
+
24
+ if __name__ == "__main__":
25
+ main()
mosesdecoder/contrib/promix/test_sampler.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ import random
4
+ import unittest
5
+
6
+ from nbest import *
7
+ from sampler import *
8
+
9
+
10
+ class TestNBestSampler(unittest.TestCase):
11
+
12
+ def setUp(self):
13
+ self.h1 = Hypothesis("a",[])
14
+ self.h2 = Hypothesis("b",[])
15
+ self.h3 = Hypothesis("c",[])
16
+ self.nbest = NBestList(1)
17
+ self.nbest.hyps.append(self.h1)
18
+ self.nbest.hyps.append(self.h2)
19
+ self.nbest.hyps.append(self.h3)
20
+ self.sampler = HopkinsMaySampler()
21
+
22
+ def test_nsamples(self):
23
+ self.h1.score = 0.1
24
+ self.h2.score = 0.2
25
+ self.h3.score = 0.3
26
+ samples = self.sampler.sample(self.nbest)
27
+ self.assertEqual(len(samples), self.sampler.nsamples)
28
+
29
+ def test_biggest(self):
30
+ random.seed(0)
31
+ self.h1.score = 0.1
32
+ self.h2.score = 0.2
33
+ self.h3.score = 0.3
34
+ samples = self.sampler.sample(self.nbest)
35
+ for sample in samples:
36
+ self.assertAlmostEqual(sample.diff,0.2)
37
+
38
+ def test_score_diff(self):
39
+ self.h1.score = 0.1
40
+ self.h2.score = 0.1 + (0.9*self.sampler.min_diff)
41
+ self.h3.score = 0.1 + (1.8*self.sampler.min_diff)
42
+
43
+ # Should only see pairs with h1,h3
44
+ samples = self.sampler.sample(self.nbest)
45
+ for sample in samples:
46
+ self.assertTrue((sample.hyp1 == self.h1 and sample.hyp2 == self.h3) or \
47
+ (sample.hyp2 == self.h1 and sample.hyp1 == self.h3))
48
+
49
+
50
+ if __name__ == "__main__":
51
+ unittest.main()
52
+
53
+ suite = unittest.TestLoader().loadTestsFromTestCase(TestNBestSampler)
mosesdecoder/contrib/promix/test_train.py ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ import unittest
4
+
5
+ from math import log,exp
6
+
7
+ import nbest
8
+ import numpy.testing as nptest
9
+ import sampler
10
+ from train import *
11
+ import util
12
+
13
+ class TestParabaloidOptimiser(unittest.TestCase):
14
+ def setUp(self):
15
+ self.o = ParabaloidOptimiser(np.array([1,2,3,4]))
16
+
17
+ def test_parabaloid_bfgs(self):
18
+ start = np.array([2,2,2,2])
19
+ minimum = self.o.optimise_bfgs(start)
20
+ for m in minimum:
21
+ self.assertAlmostEqual(m,0)
22
+
23
+
24
+ def test_parabaloid_lbfgs(self):
25
+ start = np.array([2,2,2,2])
26
+ minimum = self.o.optimise_lbfgs(start)
27
+ for m in minimum:
28
+ self.assertAlmostEqual(m,0)
29
+
30
+ class TestLogisticRegressionOptimiser(unittest.TestCase):
31
+
32
+ def test_objective(self):
33
+ x = np.array([[1], [0]])
34
+ y = np.array([1,-1])
35
+ lro = LogisticRegressionOptimiser(x,y)
36
+ w = np.array([2])
37
+ expected = -log(1 / (1 + exp(-2))) - log(0.5)
38
+ self.assertAlmostEqual(lro.objective(w), expected)
39
+
40
+ def test_reg_objective(self):
41
+ x = np.array([[1], [0]])
42
+ y = np.array([1,-1])
43
+ alpha = 0.1
44
+ lro = LogisticRegressionOptimiser(x,y,alpha)
45
+ w = np.array([2])
46
+ expected = -log(1 / (1 + exp(-2))) - log(0.5) + 0.5*2*2 * alpha
47
+ self.assertAlmostEqual(lro.objective(w), expected)
48
+
49
+ def test_gradient_j(self):
50
+ x = np.array([[1], [0]])
51
+ y = np.array([1,-1])
52
+ lro = LogisticRegressionOptimiser(x,y)
53
+ w = np.array([2])
54
+ expected = -1 / (1 + exp(2))
55
+ self.assertAlmostEqual(lro.grad_j(w,0), expected)
56
+
57
+ def test_gradient(self):
58
+ x = np.array([[1,1], [0,1]])
59
+ y = np.array([1,-1])
60
+ w = np.array([2,1])
61
+ lro = LogisticRegressionOptimiser(x,y)
62
+ e0 = -1 / (1 + exp(3))
63
+ e1 = -1 / (1 + exp(3)) + 1/ (1 + exp(-1))
64
+ actual = lro.grad(w)
65
+ #print "expected: ",e0,e1
66
+ self.assertAlmostEqual(actual[0], e0)
67
+ self.assertAlmostEqual(actual[1], e1)
68
+
69
+ def test_reg_gradient(self):
70
+ x = np.array([[1,1], [0,1]])
71
+ y = np.array([1,-1])
72
+ alpha = 0.2
73
+ w = np.array([2,1])
74
+ lro = LogisticRegressionOptimiser(x,y, alpha)
75
+ e0 = -1 / (1 + exp(3)) + w[0]*alpha
76
+ e1 = -1 / (1 + exp(3)) + 1/ (1 + exp(-1)) +w[1]*alpha
77
+ actual = lro.grad(w)
78
+ self.assertAlmostEqual(actual[0], e0)
79
+ self.assertAlmostEqual(actual[1], e1)
80
+
81
+
82
+ def test_train(self):
83
+ x = np.array([[1,1],[-1,-2]])
84
+ y = np.array([1,-1])
85
+ w0 = np.array([1,-1])
86
+ lro = LogisticRegressionOptimiser(x,y)
87
+ actual = lro.train(w0, debug=False)
88
+ self.assertAlmostEqual(actual[0], 12.03882542)
89
+ self.assertAlmostEqual(actual[1], 8.02317419)
90
+
91
+ def test_train_reg(self):
92
+ x = np.array([[1,1],[-1,1]])
93
+ y = np.array([1,-1])
94
+ alpha = 0.1
95
+ w0 = np.array([1,-1])
96
+ lro = LogisticRegressionOptimiser(x,y,alpha)
97
+ actual = lro.train(w0, debug=False)
98
+ self.assertAlmostEqual(actual[1],0) # 2nd input should be ignored
99
+ # classify first example as negative, second as positive
100
+ self.assertTrue(1 / (1+exp(-np.dot(actual,np.array([1,1])))) > 0.5)
101
+ self.assertTrue(1 / (1+exp(-np.dot(actual,np.array([-1,-2])))) < 0.5)
102
+
103
+ def test_xy(self):
104
+ """Test pre-calculation of the y_i*x_ij vectors"""
105
+ x = np.array([[1,3], [2,8], [1,3]])
106
+ y = np.array([1,1,-1])
107
+ lro = LogisticRegressionOptimiser(x,y)
108
+ expected = np.array([[1,3], [2,8], [-1,-3]])
109
+ for i in 0,1,2:
110
+ for j in 0,1:
111
+ self.assertEqual(lro.xy[i][j], expected[i][j])
112
+ #
113
+ class TestMixtureModelTrainer(unittest.TestCase):
114
+
115
+ def setUp(self):
116
+ # 3 phrase table features, but last one is ignored for interpolation
117
+ nbest._feature_index = {"tm" : [0,3], "lm" : [3,4]}
118
+ log05 = np.log(0.5)
119
+ log03 = np.log(0.3)
120
+ log02 = np.log(0.2)
121
+ log01 = np.log(0.1)
122
+ hyp0 = nbest.Hypothesis("a |0-0| b c |1-2|", [log05, log05, log02, log03], True)
123
+ hyp0.input_line = "A B C"
124
+ hyp0.score = 3
125
+ # Two ttables, columns correspond to features, rows to phrase pairs
126
+ hyp0.phrase_scores = np.array([\
127
+ [[0.2, 0.3],\
128
+ [0.4, 0.3]],\
129
+ [[0, 0.2],\
130
+ [0.4,0.2]]])
131
+
132
+ hyp1 = nbest.Hypothesis("x |0-2|", [log02, log03, log03, log01], True)
133
+ hyp1.input_line = "X Y Z"
134
+ hyp1.score = 2
135
+ hyp1.phrase_scores = np.array([\
136
+ [[0.1, 0.1]],\
137
+ [[0.8,0.1]]])
138
+
139
+ hyp2 = nbest.Hypothesis("z |0-1| w |2-2| p |3-3|", [log02, log02, log05, log05], True)
140
+ hyp2.score = 1
141
+ hyp2.input_line = "M N O"
142
+ # phrase_table x phrase_pair x feature
143
+ hyp2.phrase_scores = np.array([\
144
+ [[0.1, 0.2],\
145
+ [0.3,0.5],\
146
+ [0.4,0.6]],\
147
+ [[0.1,0.5],\
148
+ [0.6,0.1],\
149
+ [0.2,0.2]]])
150
+ self.samples = [sampler.Sample(hyp0,hyp1), sampler.Sample(hyp1,hyp2)]
151
+ self.trainer = MixtureModelTrainer(self.samples)
152
+
153
+ def get_phrase_scores(self, hypothesis, iw):
154
+ nptest.assert_almost_equal(np.sum(iw, axis=0), np.array([1.0,1.0]))
155
+ phrase_probs = hypothesis.phrase_scores
156
+ interpolated_probs = np.sum(np.expand_dims(iw,1)*phrase_probs, axis = 0)
157
+
158
+ total_probs = np.prod(interpolated_probs, axis = 0)
159
+ return util.safelog(total_probs)
160
+
161
+ def model_score(self, hypothesis, weights):
162
+ # interpolation weights
163
+ # ttable x feature
164
+ iw = np.array([[weights[-2], weights[-1]],
165
+ [1-weights[-2],1-weights[-1]]])
166
+ #print "iw:",iw
167
+ phrase_scores = self.get_phrase_scores(hypothesis,iw)
168
+ weighted_phrase_scores = weights[:2] * phrase_scores
169
+ score = np.sum(weighted_phrase_scores)
170
+
171
+ other_score = np.sum(weights[2:4]*hypothesis.fv[2:4])
172
+ return score + other_score
173
+
174
+
175
+ def test_objective(self):
176
+ # 2 phrase weights, 2 other feature weights,
177
+ # 2 interpolation weights (1 per model x 2 phrase features)
178
+ weights = np.array([0.2,0.1,0.4,0.5,0.3,0.6])
179
+ actual = self.trainer.objective(weights)
180
+ # Expected objective is the sum of the logs of sigmoids of the score differences
181
+ # Weighted by 1 if hyp1 > hyp2, -1 otherwise
182
+ expected = 0
183
+ for sample in self.samples:
184
+ hyp1_model_score = self.model_score(sample.hyp1, weights)
185
+ hyp2_model_score = self.model_score(sample.hyp2, weights)
186
+ y = 1
187
+ if sample.hyp2.score > sample.hyp1.score: y = -1
188
+ expected -= log(sigmoid(y * (hyp1_model_score - hyp2_model_score)))
189
+ # regularisation
190
+ expected += 0.5 * self.trainer.alpha * np.dot(weights[:-2], weights[:-2])
191
+ self.assertAlmostEquals(actual,expected)
192
+
193
+ def test_gradient_other(self):
194
+ # Gradients are just differences in feature vectors
195
+ # fv(hypo0)-fv(hyp1), fv(hyp1)-fv(hyp2)
196
+ delta_s = np.vstack((self.samples[0].hyp1.fv-self.samples[0].hyp2.fv,\
197
+ self.samples[1].hyp1.fv-self.samples[1].hyp2.fv))
198
+ # feature functions across rows, samples down columns
199
+ # choose other features
200
+ other_delta_s = delta_s[:,2:]
201
+ actual = self.trainer.gradient_other()
202
+ nptest.assert_almost_equal(actual,other_delta_s)
203
+
204
+ def test_gradient_phrase(self):
205
+ iw = np.array([[0.3, 0.4],[0.7,0.6]])
206
+ sample_deltaf_list = []
207
+ for sample in self.samples:
208
+ f_A = self.get_phrase_scores(sample.hyp1, iw)
209
+ f_B = self.get_phrase_scores(sample.hyp2, iw)
210
+ sample_deltaf_list.append(f_A - f_B)
211
+ expected = np.vstack(sample_deltaf_list) # samples down, features along
212
+ actual = self.trainer.gradient_phrase(iw)
213
+ nptest.assert_almost_equal(actual,expected)
214
+
215
+ def test_gradient_interp(self):
216
+ # The interpolation weights - ttable x feature
217
+ iw = np.array([[0.3, 0.4],[0.7,0.6]])
218
+ phrasew = np.array([1,2]) # The phrase weights
219
+ num_ttables = iw.shape[0]
220
+ num_phrase_features = iw.shape[1]
221
+ bysample_list = []
222
+ # Stack up gradients for each sample
223
+ for sample in self.samples:
224
+ # Get the gradient of the interpolation weights for each
225
+ # hypothesis (A and B) in the sample
226
+ byhyp = []
227
+ for hyp in [sample.hyp1,sample.hyp2]:
228
+ # the weights are flattened. rows of iw joined together, last row omitted
229
+ grad_k = np.array([0.0] * ((num_ttables - 1) * num_phrase_features))
230
+ # Iterate through the phrase features
231
+ for j,probs in enumerate(np.transpose(hyp.phrase_scores)):
232
+ # j is phrase feature index
233
+ # probs is phrase-pair, ttable
234
+ grad_jk = np.array([0.0] * (len(iw)-1))
235
+ for l,phi in enumerate(probs):
236
+ # For each phrase-pair the gradient term for the lambda
237
+ # is the probability for this ttable - probability for last ttable
238
+ # divided by overall phrase probability
239
+ num = phi[:-1] - phi[-1]
240
+ denom = np.sum(iw[:,j]*phi) # use interpolation weights for this feature
241
+ grad_jk = grad_jk + (num/denom)
242
+ self.assertEquals(len(grad_jk), num_ttables-1)
243
+ #print "num",num,"denom",denom,"grad_jk",grad_jk
244
+ # add gradient in correct place
245
+ #print "\n",j,grad_k,phrasew[j]*grad_jk
246
+ grad_k[j*(num_ttables-1):(j+1)*(num_ttables-1)] =\
247
+ grad_k[j*(num_ttables-1):(j+1)*(num_ttables-1)] + phrasew[j]*grad_jk
248
+ #print "\ngrad_k",grad_k
249
+ byhyp.append(grad_k)
250
+ bysample_list.append(byhyp[0]-byhyp[1])
251
+ #print "diff: ", bysample_list[-1]
252
+ expected = np.vstack(bysample_list)
253
+ actual = self.trainer.gradient_interp(iw,phrasew)
254
+ nptest.assert_almost_equal(actual,expected, decimal=5)
255
+
256
+ def test_gradient(self):
257
+ # 2 phrase weights, 2 other feature weights,
258
+ # 2 interpolation weights (2 models and 2 tables)
259
+ weights = np.array([0.2,0.1,0.4,0.5,0.6,0.3])
260
+ expected = np.array([0.0] * len(weights))
261
+ # Get the gradients
262
+ iw = np.array([[weights[-2], weights[-1]],
263
+ [1-weights[-2],1-weights[-1]]])
264
+ phrase_g = self.trainer.gradient_phrase(iw)
265
+ other_g = self.trainer.gradient_other()
266
+ interp_g = self.trainer.gradient_interp(iw,weights[:2])
267
+ for k,sample in enumerate(self.samples):
268
+ hyp1_model_score = self.model_score(sample.hyp1, weights)
269
+ hyp2_model_score = self.model_score(sample.hyp2, weights)
270
+ y = 1
271
+ if sample.hyp2.score > sample.hyp1.score: y = -1
272
+ delta_score = hyp1_model_score - hyp2_model_score
273
+ sig_delta_score = sigmoid(-y * delta_score)
274
+ # phrase derivative term
275
+ expected[:2] -= (phrase_g[k]*sig_delta_score*y)
276
+ # other derivative term
277
+ expected[2:4] -= (other_g[k]*sig_delta_score*y)
278
+ # inter derivative term
279
+ expected[-2:] -= (interp_g[k]*sig_delta_score*y)
280
+ expected += self.trainer.alpha*np.append(weights[:-2], np.array([0.0,0.0]))
281
+ actual = self.trainer.gradient(weights)
282
+ nptest.assert_almost_equal(actual,expected)
283
+
284
+ def test_split_weights(self):
285
+ w = np.array([1,2,3,4,0.2,0.3])
286
+ sw = self.trainer.get_split_weights(w)
287
+ self.assertEquals(len(sw),3)
288
+ nptest.assert_almost_equal(sw['phrase'], np.array([1,2]))
289
+ nptest.assert_almost_equal(sw['other'], np.array([3,4]))
290
+ nptest.assert_almost_equal(sw['interp'], \
291
+ np.array([[0.2,0.3], [0.8,0.7]]))
292
+
293
+
294
+ def test_train(self):
295
+ """Simple test that it runs without errors"""
296
+ print "x=",self.trainer.train()
297
+
298
+ if __name__ == "__main__":
299
+ unittest.main()
300
+
301
+ suite = unittest.TestSuite([
302
+ unittest.TestLoader().loadTestsFromTestCase(TestParabaloidOptimiser),
303
+ unittest.TestLoader().loadTestsFromTestCase(TestLogisticRegressionOptimiser),
304
+ unittest.TestLoader().loadTestsFromTestCase(TestMixtureModelTrainer)])
305
+
306
+
mosesdecoder/contrib/promix/util.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/python
2
+
3
+ import numpy as np
4
+
5
+
6
+ floor = np.exp(-100)
7
+ def safelog(x):
8
+ """Wraps np.log to give it a floor"""
9
+ #return np.log(x)
10
+ return np.log(np.clip(x,floor,np.inf))
11
+
12
+
mosesdecoder/jam-files/boost-build/build/ac.jam ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2010 Vladimir Prus.
2
+ #
3
+ # Use, modification and distribution is subject to the Boost Software
4
+ # License Version 1.0. (See accompanying file LICENSE_1_0.txt or
5
+ # http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ import property-set ;
8
+ import path ;
9
+ import modules ;
10
+ import "class" ;
11
+ import errors ;
12
+ import configure ;
13
+
14
+ rule find-include-path ( variable : properties : header
15
+ : provided-path ? )
16
+ {
17
+ # FIXME: document which properties affect this function by
18
+ # default.
19
+ local target-os = [ $(properties).get <target-os> ] ;
20
+ properties = [ property-set.create <target-os>$(toolset) ] ;
21
+ if $($(variable)-$(properties))
22
+ {
23
+ return $($(variable)-$(properties)) ;
24
+ }
25
+ else
26
+ {
27
+ provided-path ?= [ modules.peek : $(variable) ] ;
28
+ includes = $(provided-path) ;
29
+ includes += [ $(properties).get <include> ] ;
30
+ if [ $(properties).get <target-os> ] != windows
31
+ {
32
+ # FIXME: use sysroot
33
+ includes += /usr/include ;
34
+ }
35
+
36
+ local result ;
37
+ while ! $(result) && $(includes)
38
+ {
39
+ local f = [ path.root $(header) $(includes[1]) ] ;
40
+ ECHO "Checking " $(f) ;
41
+ if [ path.exists $(f) ]
42
+ {
43
+ result = $(includes[1]) ;
44
+ }
45
+ else if $(provided-path)
46
+ {
47
+ errors.user-error "Could not find header" $(header)
48
+ : "in the user-specified directory" $(provided-path) ;
49
+ }
50
+ includes = $(includes[2-]) ;
51
+ }
52
+ $(variable)-$(properties) = $(result) ;
53
+ return $(result) ;
54
+ }
55
+ }
56
+
57
+ rule find-library ( variable : properties : names + : provided-path ? )
58
+ {
59
+ local target-os = [ $(properties).get <target-os> ] ;
60
+ properties = [ property-set.create <target-os>$(toolset) ] ;
61
+ if $($(variable)-$(properties))
62
+ {
63
+ return $($(variable)-$(properties)) ;
64
+ }
65
+ else
66
+ {
67
+ provided-path ?= [ modules.peek : $(variable) ] ;
68
+ paths = $(provided-path) ;
69
+ paths += [ $(properties).get <library-path> ] ;
70
+ if [ $(properties).get <target-os> ] != windows
71
+ {
72
+ paths += /usr/lib /usr/lib32 /usr/lib64 ;
73
+ }
74
+
75
+ local result ;
76
+ while ! $(result) && $(paths)
77
+ {
78
+ while ! $(result) && $(names)
79
+ {
80
+ local f ;
81
+ if $(target-os) = windows
82
+ {
83
+ f = $(paths[1])/$(names[1]).lib ;
84
+ if [ path.exists $(f) ]
85
+ {
86
+ result = $(f) ;
87
+ }
88
+ }
89
+ else
90
+ {
91
+ # FIXME: check for .a as well, depending on
92
+ # the 'link' feature.
93
+ f = $(paths[1])/lib$(names[1]).so ;
94
+ ECHO "CHECKING $(f) " ;
95
+ if [ path.exists $(f) ]
96
+ {
97
+ result = $(f) ;
98
+ }
99
+ }
100
+ if ! $(result) && $(provided-path)
101
+ {
102
+ errors.user-error "Could not find either of: " $(names)
103
+ : "in the user-specified directory" $(provided-path) ;
104
+
105
+ }
106
+ names = $(names[2-]) ;
107
+ }
108
+ paths = $(paths[2-]) ;
109
+ }
110
+ $(variable)-$(properties) = $(result) ;
111
+ return $(result) ;
112
+ }
113
+ }
114
+
115
+ class ac-library : basic-target
116
+ {
117
+ import errors ;
118
+ import indirect ;
119
+ import virtual-target ;
120
+ import ac ;
121
+ import configure ;
122
+
123
+ rule __init__ ( name : project : * : * )
124
+ {
125
+ basic-target.__init__ $(name) : $(project) : $(sources)
126
+ : $(requirements) ;
127
+
128
+ reconfigure $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
129
+ }
130
+
131
+ rule set-header ( header )
132
+ {
133
+ self.header = $(header) ;
134
+ }
135
+
136
+ rule set-default-names ( names + )
137
+ {
138
+ self.default-names = $(names) ;
139
+ }
140
+
141
+ rule reconfigure ( * : * )
142
+ {
143
+ ECHO "XXX" $(1) ;
144
+ if ! $(1)
145
+ {
146
+ # This is 'using xxx ;'. Nothing to configure, really.
147
+ }
148
+ else
149
+ {
150
+ for i in 1 2 3 4 5 6 7 8 9
151
+ {
152
+ # FIXME: this naming is inconsistent with XXX_INCLUDE/XXX_LIBRARY
153
+ if ! ( $($(i)[1]) in root include-path library-path library-name condition )
154
+ {
155
+ errors.user-error "Invalid named parameter" $($(i)[1]) ;
156
+ }
157
+ local name = $($(i)[1]) ;
158
+ local value = $($(i)[2-]) ;
159
+ if $($(name)) && $($(name)) != $(value)
160
+ {
161
+ errors.user-error "Attempt to change value of '$(name)'" ;
162
+ }
163
+ $(name) = $(value) ;
164
+ }
165
+
166
+ include-path ?= $(root)/include ;
167
+ library-path ?= $(root)/lib ;
168
+ }
169
+ }
170
+
171
+ rule construct ( name : sources * : property-set )
172
+ {
173
+ # FIXME: log results.
174
+ local libnames = $(library-name) ;
175
+ if ! $(libnames) && ! $(include-path) && ! $(library-path)
176
+ {
177
+ libnames = [ modules.peek : $(name:U)_NAME ] ;
178
+ # Backward compatibility only.
179
+ libnames ?= [ modules.peek : $(name:U)_BINARY ] ;
180
+ }
181
+ libnames ?= $(self.default-names) ;
182
+
183
+ local includes = [
184
+ ac.find-include-path $(name:U)_INCLUDE : $(property-set) : $(self.header) : $(include-path) ] ;
185
+ local library = [ ac.find-library $(name:U)_LIBRARY : $(property-set) : $(libnames) : $(library-path) ] ;
186
+ if $(includes) && $(library)
187
+ {
188
+ library = [ virtual-target.from-file $(library) : . : $(self.project) ] ;
189
+ configure.log-library-search-result $(name) : "found" ;
190
+ return [ property-set.create <include>$(includes) <source>$(library) ] ;
191
+ }
192
+ else
193
+ {
194
+ configure.log-library-search-result $(name) : "no found" ;
195
+ }
196
+ }
197
+ }
198
+
mosesdecoder/jam-files/boost-build/build/project.jam ADDED
@@ -0,0 +1,1121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2002, 2003 Dave Abrahams
2
+ # Copyright 2002, 2005, 2006 Rene Rivera
3
+ # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ # Implements project representation and loading. Each project is represented by:
8
+ # - a module where all the Jamfile content live.
9
+ # - an instance of 'project-attributes' class.
10
+ # (given a module name, can be obtained using the 'attributes' rule)
11
+ # - an instance of 'project-target' class (from targets.jam)
12
+ # (given a module name, can be obtained using the 'target' rule)
13
+ #
14
+ # Typically, projects are created as result of loading a Jamfile, which is done
15
+ # by rules 'load' and 'initialize', below. First, module for Jamfile is loaded
16
+ # and new project-attributes instance is created. Some rules necessary for
17
+ # project are added to the module (see 'project-rules' module) at the bottom of
18
+ # this file. Default project attributes are set (inheriting attributes of parent
19
+ # project, if it exists). After that the Jamfile is read. It can declare its own
20
+ # attributes using the 'project' rule which will be combined with any already
21
+ # set attributes.
22
+ #
23
+ # The 'project' rule can also declare a project id which will be associated with
24
+ # the project module.
25
+ #
26
+ # There can also be 'standalone' projects. They are created by calling
27
+ # 'initialize' on an arbitrary module and not specifying their location. After
28
+ # the call, the module can call the 'project' rule, declare main targets and
29
+ # behave as a regular project except that, since it is not associated with any
30
+ # location, it should not declare targets that are not prebuilt.
31
+ #
32
+ # The list of all loaded Jamfile is stored in the .project-locations variable.
33
+ # It is possible to obtain a module name for a location using the 'module-name'
34
+ # rule. Standalone projects are not recorded and can only be referenced using
35
+ # their project id.
36
+
37
+ import "class" : new ;
38
+ import errors ;
39
+ import modules ;
40
+ import path ;
41
+ import print ;
42
+ import property-set ;
43
+ import sequence ;
44
+
45
+
46
+ # Loads the Jamfile at the given location. After loading, project global file
47
+ # and Jamfiles needed by the requested one will be loaded recursively. If the
48
+ # Jamfile at that location is loaded already, does nothing. Returns the project
49
+ # module for the Jamfile.
50
+ #
51
+ rule load ( jamfile-location )
52
+ {
53
+ if --debug-loading in [ modules.peek : ARGV ]
54
+ {
55
+ ECHO "Loading Jamfile at" '$(jamfile-location)' ;
56
+ }
57
+
58
+ local module-name = [ module-name $(jamfile-location) ] ;
59
+ # If Jamfile is already loaded, don't try again.
60
+ if ! $(module-name) in $(.jamfile-modules)
61
+ {
62
+ load-jamfile $(jamfile-location) : $(module-name) ;
63
+
64
+ # We want to make sure that child project are loaded only after parent
65
+ # projects. In particular, because parent projects define attributes
66
+ # which are inherited by children, and we don't want children to be
67
+ # loaded before parent has defined everything.
68
+ #
69
+ # While "build-project" and "use-project" can potentially refer to child
70
+ # projects from parent projects, we don't immediately load child
71
+ # projects when seeing those attributes. Instead, we record the minimal
72
+ # information to be used only later.
73
+ load-used-projects $(module-name) ;
74
+ }
75
+ return $(module-name) ;
76
+ }
77
+
78
+
79
+ rule load-used-projects ( module-name )
80
+ {
81
+ local used = [ modules.peek $(module-name) : .used-projects ] ;
82
+ local location = [ attribute $(module-name) location ] ;
83
+ import project ;
84
+ while $(used)
85
+ {
86
+ local id = $(used[1]) ;
87
+ local where = $(used[2]) ;
88
+
89
+ project.use $(id) : [ path.root [ path.make $(where) ] $(location) ] ;
90
+ used = $(used[3-]) ;
91
+ }
92
+ }
93
+
94
+
95
+ # Note the use of character groups, as opposed to listing 'Jamroot' and
96
+ # 'jamroot'. With the latter, we would get duplicate matches on Windows and
97
+ # would have to eliminate duplicates.
98
+ JAMROOT ?= [ modules.peek : JAMROOT ] ;
99
+ JAMROOT ?= project-root.jam [Jj]amroot [Jj]amroot.jam ;
100
+
101
+
102
+ # Loads parent of Jamfile at 'location'. Issues an error if nothing is found.
103
+ #
104
+ rule load-parent ( location )
105
+ {
106
+ local found = [ path.glob-in-parents $(location) : $(JAMROOT) $(JAMFILE) ] ;
107
+
108
+ if ! $(found)
109
+ {
110
+ ECHO error: Could not find parent for project at '$(location)' ;
111
+ EXIT error: Did not find Jamfile.jam or Jamroot.jam in any parent
112
+ directory. ;
113
+ }
114
+
115
+ return [ load $(found[1]:D) ] ;
116
+ }
117
+
118
+
119
+ # Makes the specified 'module' act as if it were a regularly loaded Jamfile at
120
+ # 'location'. Reports an error if a Jamfile has already been loaded for that
121
+ # location.
122
+ #
123
+ rule act-as-jamfile ( module : location )
124
+ {
125
+ if [ module-name $(location) ] in $(.jamfile-modules)
126
+ {
127
+ errors.error "Jamfile was already loaded for '$(location)'" ;
128
+ }
129
+ # Set up non-default mapping from location to module.
130
+ .module.$(location) = $(module) ;
131
+
132
+ # Add the location to the list of project locations so that we don't try to
133
+ # reload the same Jamfile in the future.
134
+ .jamfile-modules += [ module-name $(location) ] ;
135
+
136
+ initialize $(module) : $(location) ;
137
+ }
138
+
139
+
140
+ # Returns the project module corresponding to the given project-id or plain
141
+ # directory name. Returns nothing if such a project can not be found.
142
+ #
143
+ rule find ( name : current-location )
144
+ {
145
+ local project-module ;
146
+
147
+ # Try interpreting name as project id.
148
+ if [ path.is-rooted $(name) ]
149
+ {
150
+ project-module = $($(name).jamfile-module) ;
151
+ }
152
+
153
+ if ! $(project-module)
154
+ {
155
+ local location = [ path.root [ path.make $(name) ] $(current-location) ]
156
+ ;
157
+
158
+ # If no project is registered for the given location, try to load it.
159
+ # First see if we have a Jamfile. If not, then see if we might have a
160
+ # project root willing to act as a Jamfile. In that case, project root
161
+ # must be placed in the directory referred by id.
162
+
163
+ project-module = [ module-name $(location) ] ;
164
+ if ! $(project-module) in $(.jamfile-modules)
165
+ {
166
+ if [ path.glob $(location) : $(JAMROOT) $(JAMFILE) ]
167
+ {
168
+ project-module = [ load $(location) ] ;
169
+ }
170
+ else
171
+ {
172
+ project-module = ;
173
+ }
174
+ }
175
+ }
176
+
177
+ return $(project-module) ;
178
+ }
179
+
180
+
181
+ # Returns the name of the module corresponding to 'jamfile-location'. If no
182
+ # module corresponds to that location yet, associates the default module name
183
+ # with that location.
184
+ #
185
+ rule module-name ( jamfile-location )
186
+ {
187
+ if ! $(.module.$(jamfile-location))
188
+ {
189
+ # Root the path, so that locations are always unambiguous. Without this,
190
+ # we can't decide if '../../exe/program1' and '.' are the same paths.
191
+ jamfile-location = [ path.root $(jamfile-location) [ path.pwd ] ] ;
192
+ .module.$(jamfile-location) = Jamfile<$(jamfile-location)> ;
193
+ }
194
+ return $(.module.$(jamfile-location)) ;
195
+ }
196
+
197
+
198
+ # Default patterns to search for the Jamfiles to use for build declarations.
199
+ #
200
+ JAMFILE = [ modules.peek : JAMFILE ] ;
201
+ JAMFILE ?= [Bb]uild.jam [Jj]amfile.v2 [Jj]amfile [Jj]amfile.jam ;
202
+
203
+
204
+ # Find the Jamfile at the given location. This returns the exact names of all
205
+ # the Jamfiles in the given directory. The optional parent-root argument causes
206
+ # this to search not the given directory but the ones above it up to the
207
+ # directory given in it.
208
+ #
209
+ rule find-jamfile (
210
+ dir # The directory(s) to look for a Jamfile.
211
+ parent-root ? # Optional flag indicating to search for the parent Jamfile.
212
+ : no-errors ?
213
+ )
214
+ {
215
+ # Glob for all the possible Jamfiles according to the match pattern.
216
+ #
217
+ local jamfile-glob = ;
218
+ if $(parent-root)
219
+ {
220
+ if ! $(.parent-jamfile.$(dir))
221
+ {
222
+ .parent-jamfile.$(dir) = [ path.glob-in-parents $(dir) : $(JAMFILE)
223
+ ] ;
224
+ }
225
+ jamfile-glob = $(.parent-jamfile.$(dir)) ;
226
+ }
227
+ else
228
+ {
229
+ if ! $(.jamfile.$(dir))
230
+ {
231
+ .jamfile.$(dir) = [ path.glob $(dir) : $(JAMFILE) ] ;
232
+ }
233
+ jamfile-glob = $(.jamfile.$(dir)) ;
234
+
235
+ }
236
+
237
+ local jamfile-to-load = $(jamfile-glob) ;
238
+ # Multiple Jamfiles found in the same place. Warn about this and ensure we
239
+ # use only one of them. As a temporary convenience measure, if there is
240
+ # Jamfile.v2 among found files, suppress the warning and use it.
241
+ #
242
+ if $(jamfile-to-load[2-])
243
+ {
244
+ local v2-jamfiles = [ MATCH (.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam) : $(jamfile-to-load) ] ;
245
+
246
+ if $(v2-jamfiles) && ! $(v2-jamfiles[2])
247
+ {
248
+ jamfile-to-load = $(v2-jamfiles) ;
249
+ }
250
+ else
251
+ {
252
+ local jamfile = [ path.basename $(jamfile-to-load[1]) ] ;
253
+ ECHO "warning: Found multiple Jamfiles at '"$(dir)"'!"
254
+ "Loading the first one: '$(jamfile)'." ;
255
+ }
256
+
257
+ jamfile-to-load = $(jamfile-to-load[1]) ;
258
+ }
259
+
260
+ # Could not find it, error.
261
+ #
262
+ if ! $(no-errors) && ! $(jamfile-to-load)
263
+ {
264
+ errors.error Unable to load Jamfile.
265
+ : Could not find a Jamfile in directory '$(dir)'.
266
+ : Attempted to find it with pattern '"$(JAMFILE:J= )"'.
267
+ : Please consult the documentation at 'http://www.boost.org'. ;
268
+ }
269
+
270
+ return $(jamfile-to-load) ;
271
+ }
272
+
273
+
274
+ # Load a Jamfile at the given directory. Returns nothing. Will attempt to load
275
+ # the file as indicated by the JAMFILE patterns. Effect of calling this rule
276
+ # twice with the same 'dir' is undefined.
277
+ #
278
+ local rule load-jamfile (
279
+ dir # The directory of the project Jamfile.
280
+ : jamfile-module
281
+ )
282
+ {
283
+ # See if the Jamfile is where it should be.
284
+ #
285
+ local jamfile-to-load = [ path.glob $(dir) : $(JAMROOT) ] ;
286
+ if ! $(jamfile-to-load)
287
+ {
288
+ jamfile-to-load = [ find-jamfile $(dir) ] ;
289
+ }
290
+
291
+ if $(jamfile-to-load[2])
292
+ {
293
+ errors.error "Multiple Jamfiles found at '$(dir)'"
294
+ : "Filenames are: " $(jamfile-to-load:D=) ;
295
+ }
296
+
297
+ # Now load the Jamfile in it's own context.
298
+ # The call to 'initialize' may load parent Jamfile, which might have
299
+ # 'use-project' statement that causes a second attempt to load the
300
+ # same project we're loading now. Checking inside .jamfile-modules
301
+ # prevents that second attempt from messing up.
302
+ if ! $(jamfile-module) in $(.jamfile-modules)
303
+ {
304
+
305
+ # Initialize the Jamfile module before loading.
306
+ #
307
+ initialize $(jamfile-module) : [ path.parent $(jamfile-to-load) ]
308
+ : $(jamfile-to-load:BS) ;
309
+
310
+ if ! $(jamfile-module) in $(.jamfile-modules)
311
+ {
312
+ .jamfile-modules += $(jamfile-module) ;
313
+
314
+ local saved-project = $(.current-project) ;
315
+
316
+ mark-as-user $(jamfile-module) ;
317
+ modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ;
318
+ if [ MATCH ($(JAMROOT)) : $(jamfile-to-load:BS) ]
319
+ {
320
+ jamfile = [ find-jamfile $(dir) : no-errors ] ;
321
+ if $(jamfile)
322
+ {
323
+ load-aux $(jamfile-module) : [ path.native $(jamfile) ] ;
324
+ }
325
+ }
326
+
327
+ # Now do some checks.
328
+ if $(.current-project) != $(saved-project)
329
+ {
330
+ errors.error "The value of the .current-project variable has magically"
331
+ : "changed after loading a Jamfile. This means some of the targets"
332
+ : "might be defined in the wrong project."
333
+ : "after loading" $(jamfile-module)
334
+ : "expected value" $(saved-project)
335
+ : "actual value" $(.current-project) ;
336
+ }
337
+
338
+ if $(.global-build-dir)
339
+ {
340
+ local id = [ attribute $(jamfile-module) id ] ;
341
+ local project-root = [ attribute $(jamfile-module) project-root ] ;
342
+ local location = [ attribute $(jamfile-module) location ] ;
343
+
344
+ if $(location) && $(project-root) = $(dir)
345
+ {
346
+ # This is Jamroot.
347
+ if ! $(id)
348
+ {
349
+ ECHO "warning: the --build-dir option was specified" ;
350
+ ECHO "warning: but Jamroot at '$(dir)'" ;
351
+ ECHO "warning: specified no project id" ;
352
+ ECHO "warning: the --build-dir option will be ignored" ;
353
+ }
354
+ }
355
+ }
356
+ }
357
+ }
358
+ }
359
+
360
+
361
+ rule mark-as-user ( module-name )
362
+ {
363
+ if USER_MODULE in [ RULENAMES ]
364
+ {
365
+ USER_MODULE $(module-name) ;
366
+ }
367
+ }
368
+
369
+
370
+ rule load-aux ( module-name : file )
371
+ {
372
+ mark-as-user $(module-name) ;
373
+
374
+ module $(module-name)
375
+ {
376
+ include $(2) ;
377
+ local rules = [ RULENAMES $(1) ] ;
378
+ IMPORT $(1) : $(rules) : $(1) : $(1).$(rules) ;
379
+ }
380
+ }
381
+
382
+
383
+ .global-build-dir = [ MATCH --build-dir=(.*) : [ modules.peek : ARGV ] ] ;
384
+ if $(.global-build-dir)
385
+ {
386
+ # If the option is specified several times, take the last value.
387
+ .global-build-dir = [ path.make $(.global-build-dir[-1]) ] ;
388
+ }
389
+
390
+
391
+ # Initialize the module for a project.
392
+ #
393
+ rule initialize (
394
+ module-name # The name of the project module.
395
+ : location ? # The location (directory) of the project to initialize. If
396
+ # not specified, a standalone project will be initialized.
397
+ : basename ?
398
+ )
399
+ {
400
+ if --debug-loading in [ modules.peek : ARGV ]
401
+ {
402
+ ECHO "Initializing project '$(module-name)'" ;
403
+ }
404
+
405
+ local jamroot ;
406
+
407
+ local parent-module ;
408
+ if $(module-name) = test-config
409
+ {
410
+ # No parent.
411
+ }
412
+ else if $(module-name) = site-config
413
+ {
414
+ parent-module = test-config ;
415
+ }
416
+ else if $(module-name) = user-config
417
+ {
418
+ parent-module = site-config ;
419
+ }
420
+ else if $(module-name) = project-config
421
+ {
422
+ parent-module = user-config ;
423
+ }
424
+ else
425
+ {
426
+ # We search for parent/project-root only if Jamfile was specified, i.e.
427
+ # if the project is not standalone.
428
+ if $(location) && ! [ MATCH ($(JAMROOT)) : $(basename) ]
429
+ {
430
+ parent-module = [ load-parent $(location) ] ;
431
+ }
432
+ else
433
+ {
434
+ # It's either jamroot or standalone project. If it's jamroot,
435
+ # inherit from user-config.
436
+ if $(location)
437
+ {
438
+ # If project-config module exist, inherit from it.
439
+ if $(project-config.attributes)
440
+ {
441
+ parent-module = project-config ;
442
+ }
443
+ else
444
+ {
445
+ parent-module = user-config ;
446
+ }
447
+ jamroot = true ;
448
+ }
449
+ }
450
+ }
451
+
452
+ # TODO: need to consider if standalone projects can do anything but define
453
+ # prebuilt targets. If so, we need to give it a more sensible "location", so
454
+ # that source paths are correct.
455
+ location ?= "" ;
456
+ # Create the module for the Jamfile first.
457
+ module $(module-name)
458
+ {
459
+ }
460
+
461
+ # load-parent can end up loading this module again.
462
+ # Make sure this isn't duplicated.
463
+ if ! $($(module-name).attributes) {
464
+
465
+ $(module-name).attributes = [ new project-attributes $(location)
466
+ $(module-name) ] ;
467
+ local attributes = $($(module-name).attributes) ;
468
+
469
+ if $(location)
470
+ {
471
+ $(attributes).set source-location : [ path.make $(location) ] : exact ;
472
+ }
473
+ else if ! $(module-name) in test-config site-config user-config project-config
474
+ {
475
+ # This is a standalone project with known location. Set source location
476
+ # so that it can declare targets. This is intended so that you can put
477
+ # a .jam file in your sources and use it via 'using'. Standard modules
478
+ # (in 'tools' subdir) may not assume source dir is set.
479
+ local s = [ modules.binding $(module-name) ] ;
480
+ if ! $(s)
481
+ {
482
+ errors.error "Could not determine project location $(module-name)" ;
483
+ }
484
+ $(attributes).set source-location : $(s:D) : exact ;
485
+ }
486
+
487
+ $(attributes).set requirements : [ property-set.empty ] : exact ;
488
+ $(attributes).set usage-requirements : [ property-set.empty ] : exact ;
489
+
490
+ # Import rules common to all project modules from project-rules module,
491
+ # defined at the end of this file.
492
+ local rules = [ RULENAMES project-rules ] ;
493
+ IMPORT project-rules : $(rules) : $(module-name) : $(rules) ;
494
+
495
+ if $(parent-module)
496
+ {
497
+ inherit-attributes $(module-name) : $(parent-module) ;
498
+ $(attributes).set parent-module : $(parent-module) : exact ;
499
+ }
500
+
501
+ if $(jamroot)
502
+ {
503
+ $(attributes).set project-root : $(location) : exact ;
504
+ }
505
+
506
+ local parent ;
507
+ if $(parent-module)
508
+ {
509
+ parent = [ target $(parent-module) ] ;
510
+ }
511
+
512
+ if ! $(.target.$(module-name))
513
+ {
514
+ .target.$(module-name) = [ new project-target $(module-name)
515
+ : $(module-name) $(parent)
516
+ : [ attribute $(module-name) requirements ] ] ;
517
+
518
+ if --debug-loading in [ modules.peek : ARGV ]
519
+ {
520
+ ECHO "Assigned project target" $(.target.$(module-name))
521
+ "to '$(module-name)'" ;
522
+ }
523
+ }
524
+ }
525
+
526
+ .current-project = [ target $(module-name) ] ;
527
+ }
528
+
529
+
530
+ # Make 'project-module' inherit attributes of project root and parent module.
531
+ #
532
+ rule inherit-attributes ( project-module : parent-module )
533
+ {
534
+ local attributes = $($(project-module).attributes) ;
535
+ local pattributes = [ attributes $(parent-module) ] ;
536
+ # Parent module might be locationless configuration module.
537
+ if [ modules.binding $(parent-module) ]
538
+ {
539
+ $(attributes).set parent : [ path.parent
540
+ [ path.make [ modules.binding $(parent-module) ] ] ] ;
541
+ }
542
+ local v = [ $(pattributes).get project-root ] ;
543
+ $(attributes).set project-root : $(v) : exact ;
544
+ $(attributes).set default-build
545
+ : [ $(pattributes).get default-build ] ;
546
+ $(attributes).set requirements
547
+ : [ $(pattributes).get requirements ] : exact ;
548
+ $(attributes).set usage-requirements
549
+ : [ $(pattributes).get usage-requirements ] : exact ;
550
+
551
+ local parent-build-dir = [ $(pattributes).get build-dir ] ;
552
+ if $(parent-build-dir)
553
+ {
554
+ # Have to compute relative path from parent dir to our dir. Convert both
555
+ # paths to absolute, since we cannot find relative path from ".." to
556
+ # ".".
557
+
558
+ local location = [ attribute $(project-module) location ] ;
559
+ local parent-location = [ attribute $(parent-module) location ] ;
560
+
561
+ local pwd = [ path.pwd ] ;
562
+ local parent-dir = [ path.root $(parent-location) $(pwd) ] ;
563
+ local our-dir = [ path.root $(location) $(pwd) ] ;
564
+ $(attributes).set build-dir : [ path.join $(parent-build-dir)
565
+ [ path.relative $(our-dir) $(parent-dir) ] ] : exact ;
566
+ }
567
+ }
568
+
569
+
570
+ # Associate the given id with the given project module.
571
+ #
572
+ rule register-id ( id : module )
573
+ {
574
+ $(id).jamfile-module = $(module) ;
575
+ }
576
+
577
+
578
+ # Class keeping all the attributes of a project.
579
+ #
580
+ # The standard attributes are "id", "location", "project-root", "parent"
581
+ # "requirements", "default-build", "source-location" and "projects-to-build".
582
+ #
583
+ class project-attributes
584
+ {
585
+ import property ;
586
+ import property-set ;
587
+ import errors ;
588
+ import path ;
589
+ import print ;
590
+ import sequence ;
591
+ import project ;
592
+
593
+ rule __init__ ( location project-module )
594
+ {
595
+ self.location = $(location) ;
596
+ self.project-module = $(project-module) ;
597
+ }
598
+
599
+ # Set the named attribute from the specification given by the user. The
600
+ # value actually set may be different.
601
+ #
602
+ rule set ( attribute : specification *
603
+ : exact ? # Sets value from 'specification' without any processing.
604
+ )
605
+ {
606
+ if $(exact)
607
+ {
608
+ self.$(attribute) = $(specification) ;
609
+ }
610
+ else if $(attribute) = "requirements"
611
+ {
612
+ local result = [ property-set.refine-from-user-input
613
+ $(self.requirements) : $(specification)
614
+ : $(self.project-module) : $(self.location) ] ;
615
+
616
+ if $(result[1]) = "@error"
617
+ {
618
+ errors.error Requirements for project at '$(self.location)'
619
+ conflict with parent's. : Explanation: $(result[2-]) ;
620
+ }
621
+ else
622
+ {
623
+ self.requirements = $(result) ;
624
+ }
625
+ }
626
+ else if $(attribute) = "usage-requirements"
627
+ {
628
+ local unconditional ;
629
+ for local p in $(specification)
630
+ {
631
+ local split = [ property.split-conditional $(p) ] ;
632
+ split ?= nothing $(p) ;
633
+ unconditional += $(split[2]) ;
634
+ }
635
+
636
+ local non-free = [ property.remove free : $(unconditional) ] ;
637
+ if $(non-free)
638
+ {
639
+ errors.error usage-requirements $(specification) have non-free
640
+ properties $(non-free) ;
641
+ }
642
+ local t = [ property.translate-paths $(specification)
643
+ : $(self.location) ] ;
644
+ if $(self.usage-requirements)
645
+ {
646
+ self.usage-requirements = [ property-set.create
647
+ [ $(self.usage-requirements).raw ] $(t) ] ;
648
+ }
649
+ else
650
+ {
651
+ self.usage-requirements = [ property-set.create $(t) ] ;
652
+ }
653
+ }
654
+ else if $(attribute) = "default-build"
655
+ {
656
+ self.default-build = [ property.make $(specification) ] ;
657
+ }
658
+ else if $(attribute) = "source-location"
659
+ {
660
+ self.source-location = ;
661
+ for local src-path in $(specification)
662
+ {
663
+ self.source-location += [ path.root [ path.make $(src-path) ]
664
+ $(self.location) ] ;
665
+ }
666
+ }
667
+ else if $(attribute) = "build-dir"
668
+ {
669
+ self.build-dir = [ path.root
670
+ [ path.make $(specification) ] $(self.location) ] ;
671
+ }
672
+ else if $(attribute) = "id"
673
+ {
674
+ id = [ path.root $(specification) / ] ;
675
+ project.register-id $(id) : $(self.project-module) ;
676
+ self.id = $(id) ;
677
+ }
678
+ else if ! $(attribute) in "default-build" "location" "parent"
679
+ "projects-to-build" "project-root" "source-location"
680
+ {
681
+ errors.error Invalid project attribute '$(attribute)' specified for
682
+ project at '$(self.location)' ;
683
+ }
684
+ else
685
+ {
686
+ self.$(attribute) = $(specification) ;
687
+ }
688
+ }
689
+
690
+ # Returns the value of the given attribute.
691
+ #
692
+ rule get ( attribute )
693
+ {
694
+ return $(self.$(attribute)) ;
695
+ }
696
+
697
+ # Prints the project attributes.
698
+ #
699
+ rule print ( )
700
+ {
701
+ local id = $(self.id) ; id ?= (none) ;
702
+ local parent = $(self.parent) ; parent ?= (none) ;
703
+ print.section "'"$(id)"'" ;
704
+ print.list-start ;
705
+ print.list-item "Parent project:" $(parent) ;
706
+ print.list-item "Requirements:" [ $(self.requirements).raw ] ;
707
+ print.list-item "Default build:" $(self.default-build) ;
708
+ print.list-item "Source location:" $(self.source-location) ;
709
+ print.list-item "Projects to build:"
710
+ [ sequence.insertion-sort $(self.projects-to-build) ] ;
711
+ print.list-end ;
712
+ }
713
+ }
714
+
715
+
716
+ # Returns the project which is currently being loaded.
717
+ #
718
+ rule current ( )
719
+ {
720
+ return $(.current-project) ;
721
+ }
722
+
723
+
724
+ # Temporarily changes the current project to 'project'. Should be followed by
725
+ # 'pop-current'.
726
+ #
727
+ rule push-current ( project )
728
+ {
729
+ .saved-current-project += $(.current-project) ;
730
+ .current-project = $(project) ;
731
+ }
732
+
733
+
734
+ rule pop-current ( )
735
+ {
736
+ .current-project = $(.saved-current-project[-1]) ;
737
+ .saved-current-project = $(.saved-current-project[1--2]) ;
738
+ }
739
+
740
+
741
+ # Returns the project-attribute instance for the specified Jamfile module.
742
+ #
743
+ rule attributes ( project )
744
+ {
745
+ return $($(project).attributes) ;
746
+ }
747
+
748
+
749
+ # Returns the value of the specified attribute in the specified Jamfile module.
750
+ #
751
+ rule attribute ( project attribute )
752
+ {
753
+ return [ $($(project).attributes).get $(attribute) ] ;
754
+ }
755
+
756
+
757
+ # Returns the project target corresponding to the 'project-module'.
758
+ #
759
+ rule target ( project-module )
760
+ {
761
+ if ! $(.target.$(project-module))
762
+ {
763
+ .target.$(project-module) = [ new project-target $(project-module)
764
+ : $(project-module)
765
+ : [ attribute $(project-module) requirements ] ] ;
766
+ }
767
+ return $(.target.$(project-module)) ;
768
+ }
769
+
770
+
771
+ # Use/load a project.
772
+ #
773
+ rule use ( id : location )
774
+ {
775
+ local saved-project = $(.current-project) ;
776
+ local project-module = [ project.load $(location) ] ;
777
+ local declared-id = [ project.attribute $(project-module) id ] ;
778
+
779
+ if ! $(declared-id) || $(declared-id) != $(id)
780
+ {
781
+ # The project at 'location' either has no id or that id is not equal to
782
+ # the 'id' parameter.
783
+ if $($(id).jamfile-module) && ( $($(id).jamfile-module) !=
784
+ $(project-module) )
785
+ {
786
+ errors.user-error Attempt to redeclare already existing project id
787
+ '$(id)'
788
+ location '$(location)' ;
789
+ }
790
+ $(id).jamfile-module = $(project-module) ;
791
+ }
792
+ .current-project = $(saved-project) ;
793
+ }
794
+
795
+
796
+ # Defines a Boost.Build extension project. Such extensions usually contain
797
+ # library targets and features that can be used by many people. Even though
798
+ # extensions are really projects, they can be initialized as a module would be
799
+ # with the "using" (project.project-rules.using) mechanism.
800
+ #
801
+ rule extension ( id : options * : * )
802
+ {
803
+ # The caller is a standalone module for the extension.
804
+ local mod = [ CALLER_MODULE ] ;
805
+
806
+ # We need to do the rest within the extension module.
807
+ module $(mod)
808
+ {
809
+ import path ;
810
+
811
+ # Find the root project.
812
+ local root-project = [ project.current ] ;
813
+ root-project = [ $(root-project).project-module ] ;
814
+ while
815
+ [ project.attribute $(root-project) parent-module ] &&
816
+ [ project.attribute $(root-project) parent-module ] != user-config
817
+ {
818
+ root-project = [ project.attribute $(root-project) parent-module ] ;
819
+ }
820
+
821
+ # Create the project data, and bring in the project rules into the
822
+ # module.
823
+ project.initialize $(__name__) : [ path.join [ project.attribute
824
+ $(root-project) location ] ext $(1:L) ] ;
825
+
826
+ # Create the project itself, i.e. the attributes. All extensions are
827
+ # created in the "/ext" project space.
828
+ project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) :
829
+ $(9) ;
830
+ local attributes = [ project.attributes $(__name__) ] ;
831
+
832
+ # Inherit from the root project of whomever is defining us.
833
+ project.inherit-attributes $(__name__) : $(root-project) ;
834
+ $(attributes).set parent-module : $(root-project) : exact ;
835
+ }
836
+ }
837
+
838
+
839
+ rule glob-internal ( project : wildcards + : excludes * : rule-name )
840
+ {
841
+ local location = [ $(project).get source-location ] ;
842
+
843
+ local result ;
844
+ local paths = [ path.$(rule-name) $(location) :
845
+ [ sequence.transform path.make : $(wildcards) ] :
846
+ [ sequence.transform path.make : $(excludes) ] ] ;
847
+ if $(wildcards:D) || $(rule-name) != glob
848
+ {
849
+ # The paths we have found are relative to the current directory, but the
850
+ # names specified in the sources list are assumed to be relative to the
851
+ # source directory of the corresponding project. So, just make the names
852
+ # absolute.
853
+ for local p in $(paths)
854
+ {
855
+ # If the path is below source location, use relative path.
856
+ # Otherwise, use full path just to avoid any ambiguities.
857
+ local rel = [ path.relative $(p) $(location) : no-error ] ;
858
+ if $(rel) = not-a-child
859
+ {
860
+ result += [ path.root $(p) [ path.pwd ] ] ;
861
+ }
862
+ else
863
+ {
864
+ result += $(rel) ;
865
+ }
866
+ }
867
+ }
868
+ else
869
+ {
870
+ # There were no wildcards in the directory path, so the files are all in
871
+ # the source directory of the project. Just drop the directory, instead
872
+ # of making paths absolute.
873
+ result = $(paths:D="") ;
874
+ }
875
+
876
+ return $(result) ;
877
+ }
878
+
879
+
880
+ # This module defines rules common to all projects.
881
+ #
882
+ module project-rules
883
+ {
884
+ rule using ( toolset-module : * )
885
+ {
886
+ import toolset ;
887
+ import modules ;
888
+ import project ;
889
+
890
+ # Temporarily change the search path so the module referred to by
891
+ # 'using' can be placed in the same directory as Jamfile. User will
892
+ # expect the module to be found even though the directory is not in
893
+ # BOOST_BUILD_PATH.
894
+ local x = [ modules.peek : BOOST_BUILD_PATH ] ;
895
+ local caller = [ CALLER_MODULE ] ;
896
+ local caller-location = [ modules.binding $(caller) ] ;
897
+ modules.poke : BOOST_BUILD_PATH : $(caller-location:D) $(x) ;
898
+ toolset.using $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
899
+ modules.poke : BOOST_BUILD_PATH : $(x) ;
900
+
901
+ # The above might have clobbered .current-project. Restore the correct
902
+ # value.
903
+ modules.poke project : .current-project
904
+ : [ project.target $(caller) ] ;
905
+ }
906
+
907
+ import modules ;
908
+
909
+ rule import ( * : * : * )
910
+ {
911
+ modules.import project ;
912
+
913
+ local caller = [ CALLER_MODULE ] ;
914
+ local saved = [ modules.peek project : .current-project ] ;
915
+ module $(caller)
916
+ {
917
+ modules.import $(1) : $(2) : $(3) ;
918
+ }
919
+ modules.poke project : .current-project : $(saved) ;
920
+ }
921
+
922
+ rule project ( id ? : options * : * )
923
+ {
924
+ import errors ;
925
+ import path ;
926
+ import project ;
927
+
928
+ local caller = [ CALLER_MODULE ] ;
929
+ local attributes = [ project.attributes $(caller) ] ;
930
+ if $(id)
931
+ {
932
+ $(attributes).set id : $(id) ;
933
+ }
934
+
935
+ local explicit-build-dir ;
936
+
937
+ for n in 2 3 4 5 6 7 8 9
938
+ {
939
+ local option = $($(n)) ;
940
+ if $(option)
941
+ {
942
+ $(attributes).set $(option[1]) : $(option[2-]) ;
943
+ }
944
+ if $(option[1]) = "build-dir"
945
+ {
946
+ explicit-build-dir = [ path.make $(option[2-]) ] ;
947
+ }
948
+ }
949
+
950
+ # If '--build-dir' is specified, change the build dir for the project.
951
+ local global-build-dir =
952
+ [ modules.peek project : .global-build-dir ] ;
953
+
954
+ if $(global-build-dir)
955
+ {
956
+ local location = [ $(attributes).get location ] ;
957
+ # Project with an empty location is a 'standalone' project such as
958
+ # user-config or qt. It has no build dir. If we try to set build dir
959
+ # for user-config, we shall then try to inherit it, with either
960
+ # weird or wrong consequences.
961
+ if $(location) && $(location) = [ $(attributes).get project-root ]
962
+ {
963
+ # Re-read the project id, since it might have been changed in
964
+ # the project's attributes.
965
+ id = [ $(attributes).get id ] ;
966
+ # This is Jamroot.
967
+ if $(id)
968
+ {
969
+ if $(explicit-build-dir) &&
970
+ [ path.is-rooted $(explicit-build-dir) ]
971
+ {
972
+ errors.user-error Absolute directory specified via
973
+ 'build-dir' project attribute : Do not know how to
974
+ combine that with the --build-dir option. ;
975
+ }
976
+ # Strip the leading slash from id.
977
+ local rid = [ MATCH /(.*) : $(id) ] ;
978
+ local p = [ path.join
979
+ $(global-build-dir) $(rid) $(explicit-build-dir) ] ;
980
+
981
+ $(attributes).set build-dir : $(p) : exact ;
982
+ }
983
+ }
984
+ else
985
+ {
986
+ # Not Jamroot.
987
+ if $(explicit-build-dir)
988
+ {
989
+ errors.user-error When --build-dir is specified, the
990
+ 'build-dir' project : attribute is allowed only for
991
+ top-level 'project' invocations ;
992
+ }
993
+ }
994
+ }
995
+ }
996
+
997
+ # Declare and set a project global constant. Project global constants are
998
+ # normal variables but should not be changed. They are applied to every
999
+ # child Jamfile.
1000
+ #
1001
+ rule constant (
1002
+ name # Variable name of the constant.
1003
+ : value + # Value of the constant.
1004
+ )
1005
+ {
1006
+ import project ;
1007
+ local caller = [ CALLER_MODULE ] ;
1008
+ local p = [ project.target $(caller) ] ;
1009
+ $(p).add-constant $(name) : $(value) ;
1010
+ }
1011
+
1012
+ # Declare and set a project global constant, whose value is a path. The path
1013
+ # is adjusted to be relative to the invocation directory. The given value
1014
+ # path is taken to be either absolute, or relative to this project root.
1015
+ #
1016
+ rule path-constant (
1017
+ name # Variable name of the constant.
1018
+ : value + # Value of the constant.
1019
+ )
1020
+ {
1021
+ import project ;
1022
+ local caller = [ CALLER_MODULE ] ;
1023
+ local p = [ project.target $(caller) ] ;
1024
+ $(p).add-constant $(name) : $(value) : path ;
1025
+ }
1026
+
1027
+ rule use-project ( id : where )
1028
+ {
1029
+ import modules ;
1030
+ # See comment in 'load' for explanation.
1031
+ local caller = [ CALLER_MODULE ] ;
1032
+ modules.poke $(caller) : .used-projects :
1033
+ [ modules.peek $(caller) : .used-projects ]
1034
+ $(id) $(where) ;
1035
+ }
1036
+
1037
+ rule build-project ( dir )
1038
+ {
1039
+ import project ;
1040
+ local caller = [ CALLER_MODULE ] ;
1041
+ local attributes = [ project.attributes $(caller) ] ;
1042
+
1043
+ local now = [ $(attributes).get projects-to-build ] ;
1044
+ $(attributes).set projects-to-build : $(now) $(dir) ;
1045
+ }
1046
+
1047
+ rule explicit ( target-names * )
1048
+ {
1049
+ import project ;
1050
+ # If 'explicit' is used in a helper rule defined in Jamroot and
1051
+ # inherited by children, then most of the time we want 'explicit' to
1052
+ # operate on the Jamfile where the helper rule is invoked.
1053
+ local t = [ project.current ] ;
1054
+ for local n in $(target-names)
1055
+ {
1056
+ $(t).mark-target-as-explicit $(n) ;
1057
+ }
1058
+ }
1059
+
1060
+ rule always ( target-names * )
1061
+ {
1062
+ import project ;
1063
+ local t = [ project.current ] ;
1064
+ for local n in $(target-names)
1065
+ {
1066
+ $(t).mark-target-as-always $(n) ;
1067
+ }
1068
+ }
1069
+
1070
+ rule glob ( wildcards + : excludes * )
1071
+ {
1072
+ import project ;
1073
+ return [ project.glob-internal [ project.current ] : $(wildcards) :
1074
+ $(excludes) : glob ] ;
1075
+ }
1076
+
1077
+ rule glob-tree ( wildcards + : excludes * )
1078
+ {
1079
+ import project ;
1080
+
1081
+ if $(wildcards:D) || $(excludes:D)
1082
+ {
1083
+ errors.user-error The patterns to 'glob-tree' may not include
1084
+ directory ;
1085
+ }
1086
+ return [ project.glob-internal [ project.current ] : $(wildcards) :
1087
+ $(excludes) : glob-tree ] ;
1088
+ }
1089
+
1090
+ # Calculates conditional requirements for multiple requirements at once.
1091
+ # This is a shorthand to reduce duplication and to keep an inline
1092
+ # declarative syntax. For example:
1093
+ #
1094
+ # lib x : x.cpp : [ conditional <toolset>gcc <variant>debug :
1095
+ # <define>DEBUG_EXCEPTION <define>DEBUG_TRACE ] ;
1096
+ #
1097
+ rule conditional ( condition + : requirements * )
1098
+ {
1099
+ local condition = $(condition:J=,) ;
1100
+ if [ MATCH (:) : $(condition) ]
1101
+ {
1102
+ return $(condition)$(requirements) ;
1103
+ }
1104
+ else
1105
+ {
1106
+ return $(condition):$(requirements) ;
1107
+ }
1108
+ }
1109
+
1110
+ rule option ( name : value )
1111
+ {
1112
+ local m = [ CALLER_MODULE ] ;
1113
+ if $(m) != site-config && $(m) != user-config && $(m) != project-config
1114
+ {
1115
+ import errors ;
1116
+ errors.error "The 'option' rule may be used only in site-config or user-config" ;
1117
+ }
1118
+ import option ;
1119
+ option.set $(name) : $(value) ;
1120
+ }
1121
+ }
mosesdecoder/jam-files/boost-build/build/property-set.jam ADDED
@@ -0,0 +1,489 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2003 Dave Abrahams
2
+ # Copyright 2003, 2004, 2005, 2006 Vladimir Prus
3
+ # Distributed under the Boost Software License, Version 1.0.
4
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
+
6
+ import "class" : new ;
7
+ import feature ;
8
+ import path ;
9
+ import project ;
10
+ import property ;
11
+ import sequence ;
12
+ import set ;
13
+ import option ;
14
+
15
+ # Class for storing a set of properties.
16
+ #
17
+ # There is 1<->1 correspondence between identity and value. No two instances
18
+ # of the class are equal. To maintain this property, the 'property-set.create'
19
+ # rule should be used to create new instances. Instances are immutable.
20
+ #
21
+ # Each property is classified with regard to its effect on build results.
22
+ # Incidental properties have no effect on build results, from Boost.Build's
23
+ # point of view. Others are either free, or non-free and we refer to non-free
24
+ # ones as 'base'. Each property belongs to exactly one of those categories.
25
+ #
26
+ # It is possible to get a list of properties belonging to each category as
27
+ # well as a list of properties with a specific attribute.
28
+ #
29
+ # Several operations, like and refine and as-path are provided. They all use
30
+ # caching whenever possible.
31
+ #
32
+ class property-set
33
+ {
34
+ import errors ;
35
+ import feature ;
36
+ import path ;
37
+ import property ;
38
+ import property-set ;
39
+ import set ;
40
+
41
+ rule __init__ ( raw-properties * )
42
+ {
43
+ self.raw = $(raw-properties) ;
44
+
45
+ for local p in $(raw-properties)
46
+ {
47
+ if ! $(p:G)
48
+ {
49
+ errors.error "Invalid property: '$(p)'" ;
50
+ }
51
+ }
52
+ }
53
+
54
+ # Returns Jam list of stored properties.
55
+ #
56
+ rule raw ( )
57
+ {
58
+ return $(self.raw) ;
59
+ }
60
+
61
+ rule str ( )
62
+ {
63
+ return "[" $(self.raw) "]" ;
64
+ }
65
+
66
+ # Returns properties that are neither incidental nor free.
67
+ #
68
+ rule base ( )
69
+ {
70
+ if ! $(self.base-initialized)
71
+ {
72
+ init-base ;
73
+ }
74
+ return $(self.base) ;
75
+ }
76
+
77
+ # Returns free properties which are not incidental.
78
+ #
79
+ rule free ( )
80
+ {
81
+ if ! $(self.base-initialized)
82
+ {
83
+ init-base ;
84
+ }
85
+ return $(self.free) ;
86
+ }
87
+
88
+ # Returns dependency properties.
89
+ #
90
+ rule dependency ( )
91
+ {
92
+ if ! $(self.dependency-initialized)
93
+ {
94
+ init-dependency ;
95
+ }
96
+ return $(self.dependency) ;
97
+ }
98
+
99
+ rule non-dependency ( )
100
+ {
101
+ if ! $(self.dependency-initialized)
102
+ {
103
+ init-dependency ;
104
+ }
105
+ return $(self.non-dependency) ;
106
+ }
107
+
108
+ rule conditional ( )
109
+ {
110
+ if ! $(self.conditional-initialized)
111
+ {
112
+ init-conditional ;
113
+ }
114
+ return $(self.conditional) ;
115
+ }
116
+
117
+ rule non-conditional ( )
118
+ {
119
+ if ! $(self.conditional-initialized)
120
+ {
121
+ init-conditional ;
122
+ }
123
+ return $(self.non-conditional) ;
124
+ }
125
+
126
+ # Returns incidental properties.
127
+ #
128
+ rule incidental ( )
129
+ {
130
+ if ! $(self.base-initialized)
131
+ {
132
+ init-base ;
133
+ }
134
+ return $(self.incidental) ;
135
+ }
136
+
137
+ rule refine ( ps )
138
+ {
139
+ if ! $(self.refined.$(ps))
140
+ {
141
+ local r = [ property.refine $(self.raw) : [ $(ps).raw ] ] ;
142
+ if $(r[1]) != "@error"
143
+ {
144
+ self.refined.$(ps) = [ property-set.create $(r) ] ;
145
+ }
146
+ else
147
+ {
148
+ self.refined.$(ps) = $(r) ;
149
+ }
150
+ }
151
+ return $(self.refined.$(ps)) ;
152
+ }
153
+
154
+ rule expand ( )
155
+ {
156
+ if ! $(self.expanded)
157
+ {
158
+ self.expanded = [ property-set.create [ feature.expand $(self.raw) ] ] ;
159
+ }
160
+ return $(self.expanded) ;
161
+ }
162
+
163
+ rule expand-composites ( )
164
+ {
165
+ if ! $(self.composites)
166
+ {
167
+ self.composites = [ property-set.create
168
+ [ feature.expand-composites $(self.raw) ] ] ;
169
+ }
170
+ return $(self.composites) ;
171
+ }
172
+
173
+ rule evaluate-conditionals ( context ? )
174
+ {
175
+ context ?= $(__name__) ;
176
+ if ! $(self.evaluated.$(context))
177
+ {
178
+ self.evaluated.$(context) = [ property-set.create
179
+ [ property.evaluate-conditionals-in-context $(self.raw) : [ $(context).raw ] ] ] ;
180
+ }
181
+ return $(self.evaluated.$(context)) ;
182
+ }
183
+
184
+ rule propagated ( )
185
+ {
186
+ if ! $(self.propagated-ps)
187
+ {
188
+ local result ;
189
+ for local p in $(self.raw)
190
+ {
191
+ if propagated in [ feature.attributes $(p:G) ]
192
+ {
193
+ result += $(p) ;
194
+ }
195
+ }
196
+ self.propagated-ps = [ property-set.create $(result) ] ;
197
+ }
198
+ return $(self.propagated-ps) ;
199
+ }
200
+
201
+ rule add-defaults ( )
202
+ {
203
+ if ! $(self.defaults)
204
+ {
205
+ self.defaults = [ property-set.create
206
+ [ feature.add-defaults $(self.raw) ] ] ;
207
+ }
208
+ return $(self.defaults) ;
209
+ }
210
+
211
+ rule as-path ( )
212
+ {
213
+ if ! $(self.as-path)
214
+ {
215
+ self.as-path = [ property.as-path [ base ] ] ;
216
+ }
217
+ return $(self.as-path) ;
218
+ }
219
+
220
+ # Computes the path to be used for a target with the given properties.
221
+ # Returns a list of
222
+ # - the computed path
223
+ # - if the path is relative to the build directory, a value of 'true'.
224
+ #
225
+ rule target-path ( )
226
+ {
227
+ if ! $(self.target-path)
228
+ {
229
+ # The <location> feature can be used to explicitly change the
230
+ # location of generated targets.
231
+ local l = [ get <location> ] ;
232
+ if $(l)
233
+ {
234
+ self.target-path = $(l) ;
235
+ }
236
+ else
237
+ {
238
+ local p = [ as-path ] ;
239
+ p = [ property-set.hash-maybe $(p) ] ;
240
+
241
+ # A real ugly hack. Boost regression test system requires
242
+ # specific target paths, and it seems that changing it to handle
243
+ # other directory layout is really hard. For that reason, we
244
+ # teach V2 to do the things regression system requires. The
245
+ # value of '<location-prefix>' is prepended to the path.
246
+ local prefix = [ get <location-prefix> ] ;
247
+ if $(prefix)
248
+ {
249
+ self.target-path = [ path.join $(prefix) $(p) ] ;
250
+ }
251
+ else
252
+ {
253
+ self.target-path = $(p) ;
254
+ }
255
+ if ! $(self.target-path)
256
+ {
257
+ self.target-path = . ;
258
+ }
259
+ # The path is relative to build dir.
260
+ self.target-path += true ;
261
+ }
262
+ }
263
+ return $(self.target-path) ;
264
+ }
265
+
266
+ rule add ( ps )
267
+ {
268
+ if ! $(self.added.$(ps))
269
+ {
270
+ self.added.$(ps) = [ property-set.create $(self.raw) [ $(ps).raw ] ] ;
271
+ }
272
+ return $(self.added.$(ps)) ;
273
+ }
274
+
275
+ rule add-raw ( properties * )
276
+ {
277
+ return [ add [ property-set.create $(properties) ] ] ;
278
+ }
279
+
280
+ # Returns all values of 'feature'.
281
+ #
282
+ rule get ( feature )
283
+ {
284
+ if ! $(self.map-built)
285
+ {
286
+ # For each feature, create a member var and assign all values to it.
287
+ # Since all regular member vars start with 'self', there will be no
288
+ # conflicts between names.
289
+ self.map-built = true ;
290
+ for local v in $(self.raw)
291
+ {
292
+ $(v:G) += $(v:G=) ;
293
+ }
294
+ }
295
+ return $($(feature)) ;
296
+ }
297
+
298
+ # private
299
+
300
+ rule init-base ( )
301
+ {
302
+ for local p in $(self.raw)
303
+ {
304
+ local att = [ feature.attributes $(p:G) ] ;
305
+ # A feature can be both incidental and free, in which case we add it
306
+ # to incidental.
307
+ if incidental in $(att)
308
+ {
309
+ self.incidental += $(p) ;
310
+ }
311
+ else if free in $(att)
312
+ {
313
+ self.free += $(p) ;
314
+ }
315
+ else
316
+ {
317
+ self.base += $(p) ;
318
+ }
319
+ }
320
+ self.base-initialized = true ;
321
+ }
322
+
323
+ rule init-dependency ( )
324
+ {
325
+ for local p in $(self.raw)
326
+ {
327
+ local att = [ feature.attributes $(p:G) ] ;
328
+
329
+ if dependency in $(att)
330
+ {
331
+ self.dependency += $(p) ;
332
+ }
333
+ else
334
+ {
335
+ self.non-dependency += $(p) ;
336
+ }
337
+ }
338
+ self.dependency-initialized = true ;
339
+ }
340
+
341
+ rule init-conditional ( )
342
+ {
343
+ for local p in $(self.raw)
344
+ {
345
+ if [ MATCH (:) : $(p:G=) ]
346
+ {
347
+ self.conditional += $(p) ;
348
+ }
349
+ else
350
+ {
351
+ self.non-conditional += $(p) ;
352
+ }
353
+ }
354
+ self.conditional-initialized = true ;
355
+ }
356
+ }
357
+
358
+
359
+ # Creates a new 'property-set' instance for the given raw properties or returns
360
+ # an already existing ones.
361
+ #
362
+ rule create ( raw-properties * )
363
+ {
364
+ raw-properties = [ sequence.unique
365
+ [ sequence.insertion-sort $(raw-properties) ] ] ;
366
+
367
+ local key = $(raw-properties:J=-:E=) ;
368
+
369
+ if ! $(.ps.$(key))
370
+ {
371
+ .ps.$(key) = [ new property-set $(raw-properties) ] ;
372
+ }
373
+ return $(.ps.$(key)) ;
374
+ }
375
+ NATIVE_RULE property-set : create ;
376
+
377
+
378
+ # Creates a new 'property-set' instance after checking that all properties are
379
+ # valid and converting incidental properties into gristed form.
380
+ #
381
+ rule create-with-validation ( raw-properties * )
382
+ {
383
+ property.validate $(raw-properties) ;
384
+ return [ create [ property.make $(raw-properties) ] ] ;
385
+ }
386
+
387
+
388
+ # Creates a property-set from the input given by the user, in the context of
389
+ # 'jamfile-module' at 'location'.
390
+ #
391
+ rule create-from-user-input ( raw-properties * : jamfile-module location )
392
+ {
393
+ local specification = [ property.translate-paths $(raw-properties)
394
+ : $(location) ] ;
395
+ specification = [ property.translate-indirect $(specification)
396
+ : $(jamfile-module) ] ;
397
+ local project-id = [ project.attribute $(jamfile-module) id ] ;
398
+ project-id ?= [ path.root $(location) [ path.pwd ] ] ;
399
+ specification = [ property.translate-dependencies
400
+ $(specification) : $(project-id) : $(location) ] ;
401
+ specification =
402
+ [ property.expand-subfeatures-in-conditions $(specification) ] ;
403
+ specification = [ property.make $(specification) ] ;
404
+ return [ property-set.create $(specification) ] ;
405
+ }
406
+
407
+
408
+ # Refines requirements with requirements provided by the user. Specially handles
409
+ # "-<property>value" syntax in specification to remove given requirements.
410
+ # - parent-requirements -- property-set object with requirements to refine.
411
+ # - specification -- string list of requirements provided by the user.
412
+ # - project-module -- module to which context indirect features will be
413
+ # bound.
414
+ # - location -- path to which path features are relative.
415
+ #
416
+ rule refine-from-user-input ( parent-requirements : specification * :
417
+ project-module : location )
418
+ {
419
+ if ! $(specification)
420
+ {
421
+ return $(parent-requirements) ;
422
+ }
423
+ else
424
+ {
425
+ local add-requirements ;
426
+ local remove-requirements ;
427
+
428
+ for local r in $(specification)
429
+ {
430
+ local m = [ MATCH "^-(.*)" : $(r) ] ;
431
+ if $(m)
432
+ {
433
+ remove-requirements += $(m) ;
434
+ }
435
+ else
436
+ {
437
+ add-requirements += $(r) ;
438
+ }
439
+ }
440
+
441
+ if $(remove-requirements)
442
+ {
443
+ # Need to create a property set, so that path features and indirect
444
+ # features are translated just like they are in project
445
+ # requirements.
446
+ local ps = [ property-set.create-from-user-input
447
+ $(remove-requirements) : $(project-module) $(location) ] ;
448
+
449
+ parent-requirements = [ property-set.create
450
+ [ set.difference [ $(parent-requirements).raw ]
451
+ : [ $(ps).raw ] ] ] ;
452
+ specification = $(add-requirements) ;
453
+ }
454
+
455
+ local requirements = [ property-set.create-from-user-input
456
+ $(specification) : $(project-module) $(location) ] ;
457
+
458
+ return [ $(parent-requirements).refine $(requirements) ] ;
459
+ }
460
+ }
461
+
462
+
463
+ # Returns a property-set with an empty set of properties.
464
+ #
465
+ rule empty ( )
466
+ {
467
+ if ! $(.empty)
468
+ {
469
+ .empty = [ create ] ;
470
+ }
471
+ return $(.empty) ;
472
+ }
473
+
474
+ if [ option.get hash : : yes ] = yes
475
+ {
476
+ rule hash-maybe ( path ? )
477
+ {
478
+ path ?= "" ;
479
+ return [ MD5 $(path) ] ;
480
+ }
481
+ }
482
+ else
483
+ {
484
+ rule hash-maybe ( path ? )
485
+ {
486
+ return $(path) ;
487
+ }
488
+ }
489
+
mosesdecoder/jam-files/boost-build/build/targets.jam ADDED
@@ -0,0 +1,1659 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright Vladimir Prus 2002.
2
+ # Copyright Rene Rivera 2006.
3
+ #
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or copy at
6
+ # http://www.boost.org/LICENSE_1_0.txt)
7
+
8
+ # Supports 'abstract' targets, which are targets explicitly defined in a
9
+ # Jamfile.
10
+ #
11
+ # Abstract targets are represented by classes derived from 'abstract-target'
12
+ # class. The first abstract target is 'project-target', which is created for
13
+ # each Jamfile, and can be obtained by the 'target' rule in the Jamfile's module
14
+ # (see project.jam).
15
+ #
16
+ # Project targets keep a list of 'main-target' instances. A main target is what
17
+ # the user explicitly defines in a Jamfile. It is possible to have several
18
+ # definitions for a main target, for example to have different lists of sources
19
+ # for different platforms. So, main targets keep a list of alternatives.
20
+ #
21
+ # Each alternative is an instance of 'abstract-target'. When a main target
22
+ # subvariant is defined by some rule, that rule will decide what class to use,
23
+ # create an instance of that class and add it to the list of alternatives for
24
+ # the main target.
25
+ #
26
+ # Rules supplied by the build system will use only targets derived from
27
+ # 'basic-target' class, which will provide some default behaviour. There will be
28
+ # different classes derived from it such as 'make-target', created by the 'make'
29
+ # rule, and 'typed-target', created by rules such as 'exe' and 'lib'.
30
+
31
+ #
32
+ # +------------------------+
33
+ # |abstract-target |
34
+ # +========================+
35
+ # |name |
36
+ # |project |
37
+ # | |
38
+ # |generate(properties) = 0|
39
+ # +-----------+------------+
40
+ # |
41
+ # ^
42
+ # / \
43
+ # +-+-+
44
+ # |
45
+ # |
46
+ # +------------------------+------+------------------------------+
47
+ # | | |
48
+ # | | |
49
+ # +----------+-----------+ +------+------+ +------+-------+
50
+ # | project-target | | main-target | | basic-target |
51
+ # +======================+ 1 * +=============+ alternatives +==============+
52
+ # | generate(properties) |o-----------+ generate |<>------------->| generate |
53
+ # | main-target | +-------------+ | construct = 0|
54
+ # +----------------------+ +--------------+
55
+ # |
56
+ # ^
57
+ # / \
58
+ # +-+-+
59
+ # |
60
+ # |
61
+ # ...--+----------------+------------------+----------------+---+
62
+ # | | | |
63
+ # | | | |
64
+ # ... ---+-----+ +------+-------+ +------+------+ +--------+-----+
65
+ # | | typed-target | | make-target | | stage-target |
66
+ # . +==============+ +=============+ +==============+
67
+ # . | construct | | construct | | construct |
68
+ # +--------------+ +-------------+ +--------------+
69
+
70
+ import assert ;
71
+ import "class" : new ;
72
+ import errors ;
73
+ import feature ;
74
+ import indirect ;
75
+ import path ;
76
+ import property ;
77
+ import property-set ;
78
+ import sequence ;
79
+ import set ;
80
+ import toolset ;
81
+ import build-request ;
82
+
83
+
84
+ # Base class for all abstract targets.
85
+ #
86
+ class abstract-target
87
+ {
88
+ import project ;
89
+ import assert ;
90
+ import "class" ;
91
+ import errors ;
92
+
93
+ rule __init__ ( name # Name of the target in Jamfile.
94
+ : project-target # The project target to which this one belongs.
95
+ )
96
+ {
97
+ # Note: it might seem that we don't need either name or project at all.
98
+ # However, there are places where we really need it. One example is
99
+ # error messages which should name problematic targets. Another is
100
+ # setting correct paths for sources and generated files.
101
+
102
+ self.name = $(name) ;
103
+ self.project = $(project-target) ;
104
+ self.location = [ errors.nearest-user-location ] ;
105
+ }
106
+
107
+ # Returns the name of this target.
108
+ rule name ( )
109
+ {
110
+ return $(self.name) ;
111
+ }
112
+
113
+ # Returns the project for this target.
114
+ rule project ( )
115
+ {
116
+ return $(self.project) ;
117
+ }
118
+
119
+ # Return the location where the target was declared.
120
+ rule location ( )
121
+ {
122
+ return $(self.location) ;
123
+ }
124
+
125
+ # Returns a user-readable name for this target.
126
+ rule full-name ( )
127
+ {
128
+ local location = [ $(self.project).get location ] ;
129
+ return $(location)/$(self.name) ;
130
+ }
131
+
132
+ # Generates virtual targets for this abstract target using the specified
133
+ # properties, unless a different value of some feature is required by the
134
+ # target.
135
+ # On success, returns:
136
+ # - a property-set with the usage requirements to be applied to dependants
137
+ # - a list of produced virtual targets, which may be empty.
138
+ # If 'property-set' is empty, performs the default build of this target, in
139
+ # a way specific to the derived class.
140
+ #
141
+ rule generate ( property-set )
142
+ {
143
+ errors.error "method should be defined in derived classes" ;
144
+ }
145
+
146
+ rule rename ( new-name )
147
+ {
148
+ self.name = $(new-name) ;
149
+ }
150
+ }
151
+
152
+
153
+ if --debug-building in [ modules.peek : ARGV ]
154
+ {
155
+ modules.poke : .debug-building : true ;
156
+ }
157
+
158
+
159
+ rule indent ( )
160
+ {
161
+ return $(.indent:J="") ;
162
+ }
163
+
164
+
165
+ rule increase-indent ( )
166
+ {
167
+ .indent += " " ;
168
+ }
169
+
170
+
171
+ rule decrease-indent ( )
172
+ {
173
+ .indent = $(.indent[2-]) ;
174
+ }
175
+
176
+
177
+ # Project target class (derived from 'abstract-target').
178
+ #
179
+ # This class has the following responsibilities:
180
+ # - Maintaining a list of main targets in this project and building them.
181
+ #
182
+ # Main targets are constructed in two stages:
183
+ # - When Jamfile is read, a number of calls to 'add-alternative' is made. At
184
+ # that time, alternatives can also be renamed to account for inline targets.
185
+ # - The first time 'main-target' or 'has-main-target' rule is called, all
186
+ # alternatives are enumerated and main targets are created.
187
+ #
188
+ class project-target : abstract-target
189
+ {
190
+ import project ;
191
+ import targets ;
192
+ import path ;
193
+ import print ;
194
+ import property-set ;
195
+ import set ;
196
+ import sequence ;
197
+ import "class" : new ;
198
+ import errors ;
199
+
200
+ rule __init__ ( name : project-module parent-project ?
201
+ : requirements * : default-build * )
202
+ {
203
+ abstract-target.__init__ $(name) : $(__name__) ;
204
+
205
+ self.project-module = $(project-module) ;
206
+ self.location = [ project.attribute $(project-module) location ] ;
207
+ self.requirements = $(requirements) ;
208
+ self.default-build = $(default-build) ;
209
+
210
+ if $(parent-project)
211
+ {
212
+ inherit $(parent-project) ;
213
+ }
214
+ }
215
+
216
+ # This is needed only by the 'make' rule. Need to find the way to make
217
+ # 'make' work without this method.
218
+ #
219
+ rule project-module ( )
220
+ {
221
+ return $(self.project-module) ;
222
+ }
223
+
224
+ rule get ( attribute )
225
+ {
226
+ return [ project.attribute $(self.project-module) $(attribute) ] ;
227
+ }
228
+
229
+ rule build-dir ( )
230
+ {
231
+ if ! $(self.build-dir)
232
+ {
233
+ self.build-dir = [ get build-dir ] ;
234
+ if ! $(self.build-dir)
235
+ {
236
+ self.build-dir = [ path.join [ $(self.project).get location ]
237
+ bin ] ;
238
+ }
239
+ }
240
+ return $(self.build-dir) ;
241
+ }
242
+
243
+ # Generates all possible targets contained in this project.
244
+ #
245
+ rule generate ( property-set * )
246
+ {
247
+ if [ modules.peek : .debug-building ]
248
+ {
249
+ ECHO [ targets.indent ] "building project" [ name ] " ('$(__name__)') with" [ $(property-set).raw ] ;
250
+ targets.increase-indent ;
251
+ }
252
+
253
+ local usage-requirements = [ property-set.empty ] ;
254
+ local targets ;
255
+
256
+ for local t in [ targets-to-build ]
257
+ {
258
+ local g = [ $(t).generate $(property-set) ] ;
259
+ usage-requirements = [ $(usage-requirements).add $(g[1]) ] ;
260
+ targets += $(g[2-]) ;
261
+ }
262
+ targets.decrease-indent ;
263
+ return $(usage-requirements) [ sequence.unique $(targets) ] ;
264
+ }
265
+
266
+ # Computes and returns a list of abstract-target instances which must be
267
+ # built when this project is built.
268
+ #
269
+ rule targets-to-build ( )
270
+ {
271
+ local result ;
272
+
273
+ if ! $(self.built-main-targets)
274
+ {
275
+ build-main-targets ;
276
+ }
277
+
278
+ # Collect all main targets here, except for "explicit" ones.
279
+ for local t in $(self.main-targets)
280
+ {
281
+ if ! [ $(t).name ] in $(self.explicit-targets)
282
+ {
283
+ result += $(t) ;
284
+ }
285
+ }
286
+
287
+ # Collect all projects referenced via "projects-to-build" attribute.
288
+ local self-location = [ get location ] ;
289
+ for local pn in [ get projects-to-build ]
290
+ {
291
+ result += [ find $(pn)/ ] ;
292
+ }
293
+
294
+ return $(result) ;
295
+ }
296
+
297
+ # Add 'target' to the list of targets in this project that should be build
298
+ # only by explicit request
299
+ #
300
+ rule mark-target-as-explicit ( target-name * )
301
+ {
302
+ # Record the name of the target, not instance, since this rule is called
303
+ # before main target instances are created.
304
+ self.explicit-targets += $(target-name) ;
305
+ }
306
+
307
+ rule mark-target-as-always ( target-name * )
308
+ {
309
+ # Record the name of the target, not instance, since this rule is called
310
+ # before main target instances are created.
311
+ self.always-targets += $(target-name) ;
312
+ }
313
+
314
+ # Add new target alternative
315
+ #
316
+ rule add-alternative ( target-instance )
317
+ {
318
+ if $(self.built-main-targets)
319
+ {
320
+ errors.error add-alternative called when main targets are already
321
+ created. : in project [ full-name ] ;
322
+ }
323
+ self.alternatives += $(target-instance) ;
324
+ }
325
+
326
+ # Returns a 'main-target' class instance corresponding to 'name'.
327
+ #
328
+ rule main-target ( name )
329
+ {
330
+ if ! $(self.built-main-targets)
331
+ {
332
+ build-main-targets ;
333
+ }
334
+ return $(self.main-target.$(name)) ;
335
+ }
336
+
337
+ # Returns whether a main target with the specified name exists.
338
+ #
339
+ rule has-main-target ( name )
340
+ {
341
+ if ! $(self.built-main-targets)
342
+ {
343
+ build-main-targets ;
344
+ }
345
+
346
+ if $(self.main-target.$(name))
347
+ {
348
+ return true ;
349
+ }
350
+ }
351
+
352
+ # Worker function for the find rule not implementing any caching and simply
353
+ # returning nothing in case the target can not be found.
354
+ #
355
+ rule find-really ( id )
356
+ {
357
+ local result ;
358
+ local current-location = [ get location ] ;
359
+
360
+ local split = [ MATCH (.*)//(.*) : $(id) ] ;
361
+ local project-part = $(split[1]) ;
362
+ local target-part = $(split[2]) ;
363
+
364
+ local extra-error-message ;
365
+ if $(project-part)
366
+ {
367
+ # There is an explicitly specified project part in id. Looks up the
368
+ # project and passes the request to it.
369
+ local pm = [ project.find $(project-part) : $(current-location) ] ;
370
+ if $(pm)
371
+ {
372
+ project-target = [ project.target $(pm) ] ;
373
+ result = [ $(project-target).find $(target-part) : no-error ] ;
374
+ }
375
+ else
376
+ {
377
+ # TODO: This extra error message will not get displayed most
378
+ # likely due to some buggy refactoring. Refactor the code so the
379
+ # message gets diplayed again.
380
+ extra-error-message = error: could not find project
381
+ '$(project-part)' ;
382
+ }
383
+ }
384
+ else
385
+ {
386
+ # Interpret target-name as name of main target. Need to do this
387
+ # before checking for file. Consider the following scenario with a
388
+ # toolset not modifying its executable's names, e.g. gcc on
389
+ # Unix-like platforms:
390
+ #
391
+ # exe test : test.cpp ;
392
+ # install s : test : <location>. ;
393
+ #
394
+ # After the first build we would have a target named 'test' in the
395
+ # Jamfile and a file named 'test' on the disk. We need the target to
396
+ # override the file.
397
+ result = [ main-target $(id) ] ;
398
+
399
+ # Interpret id as an existing file reference.
400
+ if ! $(result)
401
+ {
402
+ result = [ new file-reference [ path.make $(id) ] :
403
+ $(self.project) ] ;
404
+ if ! [ $(result).exists ]
405
+ {
406
+ result = ;
407
+ }
408
+ }
409
+
410
+ # Interpret id as project-id.
411
+ if ! $(result)
412
+ {
413
+ local project-module = [ project.find $(id) :
414
+ $(current-location) ] ;
415
+ if $(project-module)
416
+ {
417
+ result = [ project.target $(project-module) ] ;
418
+ }
419
+ }
420
+ }
421
+
422
+ return $(result) ;
423
+ }
424
+
425
+ # Find and return the target with the specified id, treated relative to
426
+ # self. Id may specify either a target or a file name with the target taking
427
+ # priority. May report an error or return nothing if the target is not found
428
+ # depending on the 'no-error' parameter.
429
+ #
430
+ rule find ( id : no-error ? )
431
+ {
432
+ local v = $(.id.$(id)) ;
433
+ if ! $(v)
434
+ {
435
+ v = [ find-really $(id) ] ;
436
+ if ! $(v)
437
+ {
438
+ v = none ;
439
+ }
440
+ .id.$(id) = $(v) ;
441
+ }
442
+
443
+ if $(v) != none
444
+ {
445
+ return $(v) ;
446
+ }
447
+ else
448
+ {
449
+ if ! $(no-error)
450
+ {
451
+ local current-location = [ get location ] ;
452
+ ECHO "error: Unable to find file or target named" ;
453
+ ECHO "error: '$(id)'" ;
454
+ ECHO "error: referred from project at" ;
455
+ ECHO "error: '$(current-location)'" ;
456
+ ECHO $(extra-error-message) ;
457
+ EXIT ;
458
+ }
459
+ }
460
+ }
461
+
462
+ rule build-main-targets ( )
463
+ {
464
+ self.built-main-targets = true ;
465
+ for local a in $(self.alternatives)
466
+ {
467
+ local name = [ $(a).name ] ;
468
+ local target = $(self.main-target.$(name)) ;
469
+ if ! $(target)
470
+ {
471
+ local t = [ new main-target $(name) : $(self.project) ] ;
472
+ self.main-target.$(name) = $(t) ;
473
+ self.main-targets += $(t) ;
474
+ target = $(self.main-target.$(name)) ;
475
+ }
476
+
477
+ if $(name) in $(self.always-targets)
478
+ {
479
+ $(a).always ;
480
+ }
481
+
482
+ $(target).add-alternative $(a) ;
483
+ }
484
+ }
485
+
486
+ # Accessor, add a constant.
487
+ #
488
+ rule add-constant (
489
+ name # Variable name of the constant.
490
+ : value + # Value of the constant.
491
+ : type ? # Optional type of value.
492
+ )
493
+ {
494
+ switch $(type)
495
+ {
496
+ case path :
497
+ local r ;
498
+ for local v in $(value)
499
+ {
500
+ local l = $(self.location) ;
501
+ if ! $(l)
502
+ {
503
+ # Project corresponding to config files do not have
504
+ # 'location' attribute, but do have source location.
505
+ # It might be more reasonable to make every project have
506
+ # a location and use some other approach to prevent buildable
507
+ # targets in config files, but that's for later.
508
+ l = [ get source-location ] ;
509
+ }
510
+ v = [ path.root [ path.make $(v) ] $(l) ] ;
511
+ # Now make the value absolute path.
512
+ v = [ path.root $(v) [ path.pwd ] ] ;
513
+ # Constants should be in platform-native form.
514
+ v = [ path.native $(v) ] ;
515
+ r += $(v) ;
516
+ }
517
+ value = $(r) ;
518
+ }
519
+ if ! $(name) in $(self.constants)
520
+ {
521
+ self.constants += $(name) ;
522
+ }
523
+ self.constant.$(name) = $(value) ;
524
+ # Inject the constant in the scope of the Jamroot module.
525
+ modules.poke $(self.project-module) : $(name) : $(value) ;
526
+ }
527
+
528
+ rule inherit ( parent )
529
+ {
530
+ for local c in [ modules.peek $(parent) : self.constants ]
531
+ {
532
+ # No need to pass the type. Path constants were converted to
533
+ # absolute paths already by parent.
534
+ add-constant $(c)
535
+ : [ modules.peek $(parent) : self.constant.$(c) ] ;
536
+ }
537
+
538
+ # Import rules from parent.
539
+ local this-module = [ project-module ] ;
540
+ local parent-module = [ $(parent).project-module ] ;
541
+ # Do not import rules coming from 'project-rules' as they must be
542
+ # imported localized.
543
+ local user-rules = [ set.difference
544
+ [ RULENAMES $(parent-module) ] :
545
+ [ RULENAMES project-rules ] ] ;
546
+ IMPORT $(parent-module) : $(user-rules) : $(this-module) : $(user-rules) ;
547
+ EXPORT $(this-module) : $(user-rules) ;
548
+ }
549
+ }
550
+
551
+
552
+ # Helper rules to detect cycles in main target references.
553
+ #
554
+ local rule start-building ( main-target-instance )
555
+ {
556
+ if $(main-target-instance) in $(.targets-being-built)
557
+ {
558
+ local names ;
559
+ for local t in $(.targets-being-built) $(main-target-instance)
560
+ {
561
+ names += [ $(t).full-name ] ;
562
+ }
563
+
564
+ errors.error "Recursion in main target references"
565
+ : "the following target are being built currently:"
566
+ : $(names) ;
567
+ }
568
+ .targets-being-built += $(main-target-instance) ;
569
+ }
570
+
571
+
572
+ local rule end-building ( main-target-instance )
573
+ {
574
+ .targets-being-built = $(.targets-being-built[1--2]) ;
575
+ }
576
+
577
+
578
+ # A named top-level target in Jamfile.
579
+ #
580
+ class main-target : abstract-target
581
+ {
582
+ import assert ;
583
+ import errors ;
584
+ import feature ;
585
+ import print ;
586
+ import property-set ;
587
+ import sequence ;
588
+ import targets : start-building end-building ;
589
+
590
+ rule __init__ ( name : project )
591
+ {
592
+ abstract-target.__init__ $(name) : $(project) ;
593
+ }
594
+
595
+ # Add a new alternative for this target
596
+ rule add-alternative ( target )
597
+ {
598
+ local d = [ $(target).default-build ] ;
599
+ if $(self.alternatives) && ( $(self.default-build) != $(d) )
600
+ {
601
+ errors.error "default build must be identical in all alternatives"
602
+ : "main target is" [ full-name ]
603
+ : "with" [ $(d).raw ]
604
+ : "differing from previous default build" [ $(self.default-build).raw ] ;
605
+ }
606
+ else
607
+ {
608
+ self.default-build = $(d) ;
609
+ }
610
+ self.alternatives += $(target) ;
611
+ }
612
+
613
+ # Returns the best viable alternative for this property-set. See the
614
+ # documentation for selection rules.
615
+ #
616
+ local rule select-alternatives ( property-set debug ? )
617
+ {
618
+ # When selecting alternatives we have to consider defaults, for example:
619
+ # lib l : l.cpp : <variant>debug ;
620
+ # lib l : l_opt.cpp : <variant>release ;
621
+ # won't work unless we add default value <variant>debug.
622
+ property-set = [ $(p).add-defaults ] ;
623
+
624
+ # The algorithm: we keep the current best viable alternative. When we've
625
+ # got a new best viable alternative, we compare it with the current one.
626
+
627
+ local best ;
628
+ local best-properties ;
629
+
630
+ if $(self.alternatives[2-])
631
+ {
632
+ local bad ;
633
+ local worklist = $(self.alternatives) ;
634
+ while $(worklist) && ! $(bad)
635
+ {
636
+ local v = $(worklist[1]) ;
637
+ local properties = [ $(v).match $(property-set) $(debug) ] ;
638
+
639
+ if $(properties) != no-match
640
+ {
641
+ if ! $(best)
642
+ {
643
+ best = $(v) ;
644
+ best-properties = $(properties) ;
645
+ }
646
+ else
647
+ {
648
+ if $(properties) = $(best-properties)
649
+ {
650
+ bad = true ;
651
+ }
652
+ else if $(properties) in $(best-properties)
653
+ {
654
+ # Do nothing, this alternative is worse
655
+ }
656
+ else if $(best-properties) in $(properties)
657
+ {
658
+ best = $(v) ;
659
+ best-properties = $(properties) ;
660
+ }
661
+ else
662
+ {
663
+ bad = true ;
664
+ }
665
+ }
666
+ }
667
+ worklist = $(worklist[2-]) ;
668
+ }
669
+ if ! $(bad)
670
+ {
671
+ return $(best) ;
672
+ }
673
+ }
674
+ else
675
+ {
676
+ return $(self.alternatives) ;
677
+ }
678
+ }
679
+
680
+ rule apply-default-build ( property-set )
681
+ {
682
+ return [ targets.apply-default-build $(property-set)
683
+ : $(self.default-build) ] ;
684
+ }
685
+
686
+ # Select an alternative for this main target, by finding all alternatives
687
+ # which requirements are satisfied by 'properties' and picking the one with
688
+ # the longest requirements set. Returns the result of calling 'generate' on
689
+ # that alternative.
690
+ #
691
+ rule generate ( property-set )
692
+ {
693
+ start-building $(__name__) ;
694
+
695
+ # We want composite properties in build request act as if all the
696
+ # properties it expands too are explicitly specified.
697
+ property-set = [ $(property-set).expand ] ;
698
+
699
+ local all-property-sets = [ apply-default-build $(property-set) ] ;
700
+ local usage-requirements = [ property-set.empty ] ;
701
+ local result ;
702
+ for local p in $(all-property-sets)
703
+ {
704
+ local r = [ generate-really $(p) ] ;
705
+ if $(r)
706
+ {
707
+ usage-requirements = [ $(usage-requirements).add $(r[1]) ] ;
708
+ result += $(r[2-]) ;
709
+ }
710
+ }
711
+ end-building $(__name__) ;
712
+ return $(usage-requirements) [ sequence.unique $(result) ] ;
713
+ }
714
+
715
+ # Generates the main target with the given property set and returns a list
716
+ # which first element is property-set object containing usage-requirements
717
+ # of generated target and with generated virtual target in other elements.
718
+ # It is possible that no targets are generated.
719
+ #
720
+ local rule generate-really ( property-set )
721
+ {
722
+ local best-alternatives = [ select-alternatives $(property-set) ] ;
723
+ if ! $(best-alternatives)
724
+ {
725
+ ECHO "error: No best alternative for" [ full-name ] ;
726
+ select-alternatives $(property-set) debug ;
727
+ return [ property-set.empty ] ;
728
+ }
729
+ else
730
+ {
731
+ # Now return virtual targets for the only alternative.
732
+ return [ $(best-alternatives).generate $(property-set) ] ;
733
+ }
734
+ }
735
+
736
+ rule rename ( new-name )
737
+ {
738
+ abstract-target.rename $(new-name) ;
739
+ for local a in $(self.alternatives)
740
+ {
741
+ $(a).rename $(new-name) ;
742
+ }
743
+ }
744
+ }
745
+
746
+
747
+ # Abstract target refering to a source file. This is an artificial entity
748
+ # allowing sources to a target to be represented using a list of abstract target
749
+ # instances.
750
+ #
751
+ class file-reference : abstract-target
752
+ {
753
+ import virtual-target ;
754
+ import property-set ;
755
+ import path ;
756
+
757
+ rule __init__ ( file : project )
758
+ {
759
+ abstract-target.__init__ $(file) : $(project) ;
760
+ }
761
+
762
+ rule generate ( properties )
763
+ {
764
+ return [ property-set.empty ] [ virtual-target.from-file $(self.name) :
765
+ [ location ] : $(self.project) ] ;
766
+ }
767
+
768
+ # Returns true if the referred file really exists.
769
+ rule exists ( )
770
+ {
771
+ location ;
772
+ return $(self.file-path) ;
773
+ }
774
+
775
+ # Returns the location of target. Needed by 'testing.jam'.
776
+ rule location ( )
777
+ {
778
+ if ! $(self.file-location)
779
+ {
780
+ local source-location = [ $(self.project).get source-location ] ;
781
+ for local src-dir in $(source-location)
782
+ {
783
+ if ! $(self.file-location)
784
+ {
785
+ local location = [ path.root $(self.name) $(src-dir) ] ;
786
+ if [ CHECK_IF_FILE [ path.native $(location) ] ]
787
+ {
788
+ self.file-location = $(src-dir) ;
789
+ self.file-path = $(location) ;
790
+ }
791
+ }
792
+ }
793
+ }
794
+ return $(self.file-location) ;
795
+ }
796
+ }
797
+
798
+
799
+ # Given a target-reference, made in context of 'project', returns the
800
+ # abstract-target instance that is referred to, as well as properties explicitly
801
+ # specified for this reference.
802
+ #
803
+ rule resolve-reference ( target-reference : project )
804
+ {
805
+ # Separate target name from properties override.
806
+ local split = [ MATCH "^([^<]*)(/(<.*))?$" : $(target-reference) ] ;
807
+ local id = $(split[1]) ;
808
+ local sproperties = ;
809
+ if $(split[3])
810
+ {
811
+ sproperties = [ property.make [ feature.split $(split[3]) ] ] ;
812
+ sproperties = [ feature.expand-composites $(sproperties) ] ;
813
+ }
814
+
815
+ # Find the target.
816
+ local target = [ $(project).find $(id) ] ;
817
+
818
+ return $(target) [ property-set.create $(sproperties) ] ;
819
+ }
820
+
821
+
822
+ # Attempts to generate the target given by target reference, which can refer
823
+ # both to a main target or to a file. Returns a list consisting of
824
+ # - usage requirements
825
+ # - generated virtual targets, if any
826
+ #
827
+ rule generate-from-reference (
828
+ target-reference # Target reference.
829
+ : project # Project where the reference is made.
830
+ : property-set # Properties of the main target that makes the reference.
831
+ )
832
+ {
833
+ local r = [ resolve-reference $(target-reference) : $(project) ] ;
834
+ local target = $(r[1]) ;
835
+ local sproperties = $(r[2]) ;
836
+
837
+ # Take properties which should be propagated and refine them with
838
+ # source-specific requirements.
839
+ local propagated = [ $(property-set).propagated ] ;
840
+ local rproperties = [ $(propagated).refine $(sproperties) ] ;
841
+ if $(rproperties[1]) = "@error"
842
+ {
843
+ errors.error
844
+ "When building" [ full-name ] " with properties " $(properties) :
845
+ "Invalid properties specified for " $(source) ":"
846
+ $(rproperties[2-]) ;
847
+ }
848
+ return [ $(target).generate $(rproperties) ] ;
849
+ }
850
+
851
+ rule apply-default-build ( property-set : default-build )
852
+ {
853
+ # 1. First, see what properties from default-build are already present
854
+ # in property-set.
855
+
856
+ local raw = [ $(property-set).raw ] ;
857
+ local specified-features = $(raw:G) ;
858
+
859
+ local defaults-to-apply ;
860
+ for local d in [ $(default-build).raw ]
861
+ {
862
+ if ! $(d:G) in $(specified-features)
863
+ {
864
+ defaults-to-apply += $(d) ;
865
+ }
866
+ }
867
+
868
+ # 2. If there are any defaults to be applied, form a new build request.
869
+ # Pass it through to 'expand-no-defaults' since default-build might
870
+ # contain "release debug" resulting in two property-sets.
871
+ local result ;
872
+ if $(defaults-to-apply)
873
+ {
874
+ properties = [
875
+ build-request.expand-no-defaults
876
+
877
+ # We have to compress subproperties here to prevent property
878
+ # lists like:
879
+ #
880
+ # <toolset>msvc <toolset-msvc:version>7.1 <threading>multi
881
+ #
882
+ # from being expanded into:
883
+ #
884
+ # <toolset-msvc:version>7.1/<threading>multi
885
+ # <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi
886
+ #
887
+ # due to a cross-product property combination. That may be an
888
+ # indication that build-request.expand-no-defaults is the wrong
889
+ # rule to use here.
890
+ [ feature.compress-subproperties $(raw) ]
891
+ $(defaults-to-apply)
892
+ ] ;
893
+
894
+ if $(properties)
895
+ {
896
+ for local p in $(properties)
897
+ {
898
+ result += [ property-set.create
899
+ [ feature.expand [ feature.split $(p) ] ] ] ;
900
+ }
901
+ }
902
+ else
903
+ {
904
+ result = [ property-set.empty ] ;
905
+ }
906
+ }
907
+ else
908
+ {
909
+ result = $(property-set) ;
910
+ }
911
+ return $(result) ;
912
+ }
913
+
914
+
915
+ # Given a build request and requirements, return properties common to dependency
916
+ # build request and target requirements.
917
+ #
918
+ # TODO: Document exactly what 'common properties' are, whether they should
919
+ # include default property values, whether they should contain any conditional
920
+ # properties or should those be already processed, etc. See whether there are
921
+ # any differences between use cases with empty and non-empty build-request as
922
+ # well as with requirements containing and those not containing any non-free
923
+ # features.
924
+ #
925
+ rule common-properties ( build-request requirements )
926
+ {
927
+ # For optimization, we add free requirements directly, without using a
928
+ # complex algorithm. This gives the complex algorithm a better chance of
929
+ # caching results.
930
+ local free = [ $(requirements).free ] ;
931
+ local non-free = [ property-set.create [ $(requirements).base ]
932
+ [ $(requirements).incidental ] ] ;
933
+
934
+ local key = .rp.$(build-request)-$(non-free) ;
935
+ if ! $($(key))
936
+ {
937
+ $(key) = [ common-properties2 $(build-request) $(non-free) ] ;
938
+ }
939
+ return [ $($(key)).add-raw $(free) ] ;
940
+ }
941
+
942
+
943
+ # Given a 'context' -- a set of already present properties, and 'requirements',
944
+ # decide which extra properties should be applied to 'context'. For conditional
945
+ # requirements, this means evaluating the condition. For indirect conditional
946
+ # requirements, this means calling a rule. Ordinary requirements are always
947
+ # applied.
948
+ #
949
+ # Handles the situation where evaluating one conditional requirement affects
950
+ # conditions of another conditional requirements, such as:
951
+ # <toolset>gcc:<variant>release <variant>release:<define>RELEASE
952
+ #
953
+ # If 'what' is 'refined' returns context refined with new requirements. If
954
+ # 'what' is 'added' returns just the requirements to be applied.
955
+ #
956
+ rule evaluate-requirements ( requirements : context : what )
957
+ {
958
+ # Apply non-conditional requirements. It is possible that further
959
+ # conditional requirement change a value set by non-conditional
960
+ # requirements. For example:
961
+ #
962
+ # exe a : a.cpp : <threading>single <toolset>foo:<threading>multi ;
963
+ #
964
+ # I am not sure if this should be an error, or not, especially given that
965
+ #
966
+ # <threading>single
967
+ #
968
+ # might come from project's requirements.
969
+
970
+ local unconditional = [ feature.expand [ $(requirements).non-conditional ] ] ;
971
+
972
+ local raw = [ $(context).raw ] ;
973
+ raw = [ property.refine $(raw) : $(unconditional) ] ;
974
+
975
+ # We have collected properties that surely must be present in common
976
+ # properties. We now try to figure out what other properties should be added
977
+ # in order to satisfy rules (4)-(6) from the docs.
978
+
979
+ local conditionals = [ $(requirements).conditional ] ;
980
+ # The 'count' variable has one element for each conditional feature and for
981
+ # each occurrence of '<indirect-conditional>' feature. It is used as a loop
982
+ # counter: for each iteration of the loop before we remove one element and
983
+ # the property set should stabilize before we are done. It is assumed that
984
+ # #conditionals iterations should be enough for properties to propagate
985
+ # along conditions in any direction.
986
+ local count = $(conditionals)
987
+ [ $(requirements).get <conditional> ]
988
+ and-once-more ;
989
+
990
+ local added-requirements ;
991
+
992
+ local current = $(raw) ;
993
+
994
+ # It is assumed that ordinary conditional requirements can not add
995
+ # <conditional> properties (a.k.a. indirect conditional properties), and
996
+ # that rules referred to by <conditional> properties can not add new
997
+ # <conditional> properties. So the list of indirect conditionals does not
998
+ # change.
999
+ local indirect = [ $(requirements).get <conditional> ] ;
1000
+ indirect = [ MATCH ^@(.*) : $(indirect) ] ;
1001
+
1002
+ local ok ;
1003
+ while $(count)
1004
+ {
1005
+ # Evaluate conditionals in context of current properties.
1006
+ local e = [ property.evaluate-conditionals-in-context $(conditionals)
1007
+ : $(current) ] ;
1008
+
1009
+ # Evaluate indirect conditionals.
1010
+ for local i in $(indirect)
1011
+ {
1012
+ e += [ indirect.call $(i) $(current) ] ;
1013
+ }
1014
+
1015
+ if $(e) = $(added-requirements)
1016
+ {
1017
+ # If we got the same result, we have found the final properties.
1018
+ count = ;
1019
+ ok = true ;
1020
+ }
1021
+ else
1022
+ {
1023
+ # Oops, conditional evaluation results have changed. Also 'current'
1024
+ # contains leftovers from a previous evaluation. Recompute 'current'
1025
+ # using initial properties and conditional requirements.
1026
+ added-requirements = $(e) ;
1027
+ current = [ property.refine $(raw) : [ feature.expand $(e) ] ] ;
1028
+ }
1029
+ count = $(count[2-]) ;
1030
+ }
1031
+ if ! $(ok)
1032
+ {
1033
+ errors.error "Can not evaluate conditional properties " $(conditionals) ;
1034
+ }
1035
+
1036
+ if $(what) = added
1037
+ {
1038
+ return [ property-set.create $(unconditional) $(added-requirements) ] ;
1039
+ }
1040
+ else if $(what) = refined
1041
+ {
1042
+ return [ property-set.create $(current) ] ;
1043
+ }
1044
+ else
1045
+ {
1046
+ errors.error "Invalid value of the 'what' parameter." ;
1047
+ }
1048
+ }
1049
+
1050
+
1051
+ rule common-properties2 ( build-request requirements )
1052
+ {
1053
+ # This guarantees that default properties are present in the result, unless
1054
+ # they are overriden by some requirement. FIXME: There is possibility that
1055
+ # we have added <foo>bar, which is composite and expands to <foo2>bar2, but
1056
+ # default value of <foo2> is not bar2, in which case it is not clear what to
1057
+ # do.
1058
+ #
1059
+ build-request = [ $(build-request).add-defaults ] ;
1060
+ # Features added by 'add-default' can be composite and expand to features
1061
+ # without default values -- so they are not added yet. It could be clearer/
1062
+ # /faster to expand only newly added properties but that is not critical.
1063
+ build-request = [ $(build-request).expand ] ;
1064
+
1065
+ return [ evaluate-requirements $(requirements) : $(build-request) :
1066
+ refined ] ;
1067
+ }
1068
+
1069
+ rule push-target ( target )
1070
+ {
1071
+ .targets = $(target) $(.targets) ;
1072
+ }
1073
+
1074
+ rule pop-target ( )
1075
+ {
1076
+ .targets = $(.targets[2-]) ;
1077
+ }
1078
+
1079
+ # Return the metatarget that is currently being generated.
1080
+ rule current ( )
1081
+ {
1082
+ return $(.targets[1]) ;
1083
+ }
1084
+
1085
+
1086
+ # Implements the most standard way of constructing main target alternative from
1087
+ # sources. Allows sources to be either file or other main target and handles
1088
+ # generation of those dependency targets.
1089
+ #
1090
+ class basic-target : abstract-target
1091
+ {
1092
+ import build-request ;
1093
+ import build-system ;
1094
+ import "class" : new ;
1095
+ import errors ;
1096
+ import feature ;
1097
+ import property ;
1098
+ import property-set ;
1099
+ import sequence ;
1100
+ import set ;
1101
+ import targets ;
1102
+ import virtual-target ;
1103
+
1104
+ rule __init__ ( name : project : sources * : requirements *
1105
+ : default-build * : usage-requirements * )
1106
+ {
1107
+ abstract-target.__init__ $(name) : $(project) ;
1108
+
1109
+ self.sources = $(sources) ;
1110
+ if ! $(requirements) {
1111
+ requirements = [ property-set.empty ] ;
1112
+ }
1113
+ self.requirements = $(requirements) ;
1114
+ if ! $(default-build)
1115
+ {
1116
+ default-build = [ property-set.empty ] ;
1117
+ }
1118
+ self.default-build = $(default-build) ;
1119
+ if ! $(usage-requirements)
1120
+ {
1121
+ usage-requirements = [ property-set.empty ] ;
1122
+ }
1123
+ self.usage-requirements = $(usage-requirements) ;
1124
+
1125
+ if $(sources:G)
1126
+ {
1127
+ errors.user-error properties found in the 'sources' parameter for
1128
+ [ full-name ] ;
1129
+ }
1130
+ }
1131
+
1132
+ rule always ( )
1133
+ {
1134
+ self.always = 1 ;
1135
+ }
1136
+
1137
+ # Returns the list of abstract-targets which are used as sources. The extra
1138
+ # properties specified for sources are not represented. The only user for
1139
+ # this rule at the moment is the "--dump-tests" feature of the test system.
1140
+ #
1141
+ rule sources ( )
1142
+ {
1143
+ if ! $(self.source-targets)
1144
+ {
1145
+ for local s in $(self.sources)
1146
+ {
1147
+ self.source-targets +=
1148
+ [ targets.resolve-reference $(s) : $(self.project) ] ;
1149
+ }
1150
+ }
1151
+ return $(self.source-targets) ;
1152
+ }
1153
+
1154
+ rule requirements ( )
1155
+ {
1156
+ return $(self.requirements) ;
1157
+ }
1158
+
1159
+ rule default-build ( )
1160
+ {
1161
+ return $(self.default-build) ;
1162
+ }
1163
+
1164
+ # Returns the alternative condition for this alternative, if the condition
1165
+ # is satisfied by 'property-set'.
1166
+ #
1167
+ rule match ( property-set debug ? )
1168
+ {
1169
+ # The condition is composed of all base non-conditional properties. It
1170
+ # is not clear if we should expand 'self.requirements' or not. For one
1171
+ # thing, it would be nice to be able to put
1172
+ # <toolset>msvc-6.0
1173
+ # in requirements. On the other hand, if we have <variant>release as a
1174
+ # condition it does not make sense to require <optimization>full to be
1175
+ # in the build request just to select this variant.
1176
+ local bcondition = [ $(self.requirements).base ] ;
1177
+ local ccondition = [ $(self.requirements).conditional ] ;
1178
+ local condition = [ set.difference $(bcondition) : $(ccondition) ] ;
1179
+ if $(debug)
1180
+ {
1181
+ ECHO " next alternative: required properties:" $(condition:E=(empty)) ;
1182
+ }
1183
+
1184
+ if $(condition) in [ $(property-set).raw ]
1185
+ {
1186
+ if $(debug)
1187
+ {
1188
+ ECHO " matched" ;
1189
+ }
1190
+ return $(condition) ;
1191
+ }
1192
+ else
1193
+ {
1194
+ if $(debug)
1195
+ {
1196
+ ECHO " not matched" ;
1197
+ }
1198
+ return no-match ;
1199
+ }
1200
+ }
1201
+
1202
+ # Takes a target reference, which might be either target id or a dependency
1203
+ # property, and generates that target using 'property-set' as build request.
1204
+ #
1205
+ # The results are added to the variable called 'result-var'. Usage
1206
+ # requirements are added to the variable called 'usage-requirements-var'.
1207
+ #
1208
+ rule generate-dependencies ( dependencies * : property-set
1209
+ : result-var usage-requirements-var )
1210
+ {
1211
+ for local dependency in $(dependencies)
1212
+ {
1213
+ local grist = $(dependency:G) ;
1214
+ local id = $(dependency:G=) ;
1215
+
1216
+ local result = [ targets.generate-from-reference $(id) :
1217
+ $(self.project) : $(property-set) ] ;
1218
+
1219
+ $(result-var) += $(result[2-]:G=$(grist)) ;
1220
+ $(usage-requirements-var) += [ $(result[1]).raw ] ;
1221
+ }
1222
+ }
1223
+
1224
+ # Determines final build properties, generates sources, and calls
1225
+ # 'construct'. This method should not be overridden.
1226
+ #
1227
+ rule generate ( property-set )
1228
+ {
1229
+ if [ modules.peek : .debug-building ]
1230
+ {
1231
+ ECHO ;
1232
+ local fn = [ full-name ] ;
1233
+ ECHO [ targets.indent ] "Building target '$(fn)'" ;
1234
+ targets.increase-indent ;
1235
+ ECHO [ targets.indent ] "Build request: " $(property-set) [ $(property-set).raw ] ;
1236
+ local cf = [ build-system.command-line-free-features ] ;
1237
+ ECHO [ targets.indent ] "Command line free features: " [ $(cf).raw ] ;
1238
+ ECHO [ targets.indent ] "Target requirements: " [ $(self.requirements).raw ] ;
1239
+ }
1240
+ targets.push-target $(__name__) ;
1241
+
1242
+ if ! $(self.generated.$(property-set))
1243
+ {
1244
+ # Apply free features from the command line. If user said
1245
+ # define=FOO
1246
+ # he most likely wants this define to be set for all compiles.
1247
+ property-set = [ $(property-set).refine
1248
+ [ build-system.command-line-free-features ] ] ;
1249
+ local rproperties = [ targets.common-properties $(property-set)
1250
+ $(self.requirements) ] ;
1251
+
1252
+ if [ modules.peek : .debug-building ]
1253
+ {
1254
+ ECHO ;
1255
+ ECHO [ targets.indent ] "Common properties: " [ $(rproperties).raw ] ;
1256
+ }
1257
+
1258
+ if ( $(rproperties[1]) != "@error" ) && ( [ $(rproperties).get
1259
+ <build> ] != no )
1260
+ {
1261
+ local source-targets ;
1262
+ local properties = [ $(rproperties).non-dependency ] ;
1263
+ local usage-requirements ;
1264
+
1265
+ generate-dependencies [ $(rproperties).dependency ] :
1266
+ $(rproperties) : properties usage-requirements ;
1267
+
1268
+ generate-dependencies $(self.sources) : $(rproperties) :
1269
+ source-targets usage-requirements ;
1270
+
1271
+ if [ modules.peek : .debug-building ]
1272
+ {
1273
+ ECHO ;
1274
+ ECHO [ targets.indent ] "Usage requirements for"
1275
+ $(self.name)": " $(usage-requirements) ;
1276
+ }
1277
+
1278
+ rproperties = [ property-set.create $(properties)
1279
+ $(usage-requirements) ] ;
1280
+ usage-requirements = [ property-set.create $(usage-requirements) ] ;
1281
+
1282
+ if [ modules.peek : .debug-building ]
1283
+ {
1284
+ ECHO [ targets.indent ] "Build properties: "
1285
+ [ $(rproperties).raw ] ;
1286
+ }
1287
+
1288
+ local extra = [ $(rproperties).get <source> ] ;
1289
+ source-targets += $(extra:G=) ;
1290
+ # We might get duplicate sources, for example if we link to two
1291
+ # libraries having the same <library> usage requirement.
1292
+ # Use stable sort, since for some targets the order is
1293
+ # important. E.g. RUN_PY target need python source to come
1294
+ # first.
1295
+ source-targets = [ sequence.unique $(source-targets) : stable ] ;
1296
+
1297
+ local result = [ construct $(self.name) : $(source-targets) :
1298
+ $(rproperties) ] ;
1299
+
1300
+ if $(result)
1301
+ {
1302
+ local gur = $(result[1]) ;
1303
+ result = $(result[2-]) ;
1304
+
1305
+ if $(self.always)
1306
+ {
1307
+ for local t in $(result)
1308
+ {
1309
+ $(t).always ;
1310
+ }
1311
+ }
1312
+
1313
+ local s = [ create-subvariant $(result)
1314
+ : [ virtual-target.recent-targets ]
1315
+ : $(property-set) : $(source-targets)
1316
+ : $(rproperties) : $(usage-requirements) ] ;
1317
+ virtual-target.clear-recent-targets ;
1318
+
1319
+ local ur = [ compute-usage-requirements $(s) ] ;
1320
+ ur = [ $(ur).add $(gur) ] ;
1321
+ $(s).set-usage-requirements $(ur) ;
1322
+ if [ modules.peek : .debug-building ]
1323
+ {
1324
+ ECHO [ targets.indent ] "Usage requirements from"
1325
+ $(self.name)": " [ $(ur).raw ] ;
1326
+ }
1327
+
1328
+ self.generated.$(property-set) = $(ur) $(result) ;
1329
+ }
1330
+ }
1331
+ else
1332
+ {
1333
+ if $(rproperties[1]) = "@error"
1334
+ {
1335
+ ECHO [ targets.indent ] "Skipping build of:" [ full-name ]
1336
+ "cannot compute common properties" ;
1337
+ }
1338
+ else if [ $(rproperties).get <build> ] = no
1339
+ {
1340
+ # If we just see <build>no, we cannot produce any reasonable
1341
+ # diagnostics. The code that adds this property is expected
1342
+ # to explain why a target is not built, for example using
1343
+ # the configure.log-component-configuration function.
1344
+ }
1345
+ else
1346
+ {
1347
+ ECHO [ targets.indent ] "Skipping build of: " [ full-name ]
1348
+ " unknown reason" ;
1349
+ }
1350
+
1351
+ # We are here either because there has been an error computing
1352
+ # properties or there is <build>no in properties. In the latter
1353
+ # case we do not want any diagnostic. In the former case, we
1354
+ # need diagnostics. FIXME
1355
+
1356
+ # If this target fails to build, add <build>no to properties to
1357
+ # cause any parent target to fail to build. Except that it
1358
+ # - does not work now, since we check for <build>no only in
1359
+ # common properties, but not in properties that came from
1360
+ # dependencies
1361
+ # - it is not clear if that is a good idea anyway. The alias
1362
+ # target, for example, should not fail to build if a
1363
+ # dependency fails.
1364
+ self.generated.$(property-set) = [ property-set.create <build>no ] ;
1365
+ }
1366
+ }
1367
+ else
1368
+ {
1369
+ if [ modules.peek : .debug-building ]
1370
+ {
1371
+ ECHO [ targets.indent ] "Already built" ;
1372
+ local ur = $(self.generated.$(property-set)) ;
1373
+ ur = $(ur[0]) ;
1374
+ targets.increase-indent ;
1375
+ ECHO [ targets.indent ] "Usage requirements from"
1376
+ $(self.name)": " [ $(ur).raw ] ;
1377
+ targets.decrease-indent ;
1378
+ }
1379
+ }
1380
+
1381
+ targets.pop-target ;
1382
+ targets.decrease-indent ;
1383
+ return $(self.generated.$(property-set)) ;
1384
+ }
1385
+
1386
+ # Given the set of generated targets, and refined build properties,
1387
+ # determines and sets appropriate usage requirements on those targets.
1388
+ #
1389
+ rule compute-usage-requirements ( subvariant )
1390
+ {
1391
+ local rproperties = [ $(subvariant).build-properties ] ;
1392
+ xusage-requirements = [ targets.evaluate-requirements
1393
+ $(self.usage-requirements) : $(rproperties) : added ] ;
1394
+
1395
+ # We generate all dependency properties and add them, as well as their
1396
+ # usage requirements, to the result.
1397
+ local extra ;
1398
+ generate-dependencies [ $(xusage-requirements).dependency ] :
1399
+ $(rproperties) : extra extra ;
1400
+
1401
+ local result = [ property-set.create
1402
+ [ $(xusage-requirements).non-dependency ] $(extra) ] ;
1403
+
1404
+ # Propagate usage requirements we got from sources, except for the
1405
+ # <pch-header> and <pch-file> features.
1406
+ #
1407
+ # That feature specifies which pch file to use, and should apply only to
1408
+ # direct dependents. Consider:
1409
+ #
1410
+ # pch pch1 : ...
1411
+ # lib lib1 : ..... pch1 ;
1412
+ # pch pch2 :
1413
+ # lib lib2 : pch2 lib1 ;
1414
+ #
1415
+ # Here, lib2 should not get <pch-header> property from pch1.
1416
+ #
1417
+ # Essentially, when those two features are in usage requirements, they
1418
+ # are propagated only to direct dependents. We might need a more general
1419
+ # mechanism, but for now, only those two features are special.
1420
+ #
1421
+ # TODO - Actually there are more possible candidates like for instance
1422
+ # when listing static library X as a source for another static library.
1423
+ # Then static library X will be added as a <source> property to the
1424
+ # second library's usage requirements but those requirements should last
1425
+ # only up to the first executable or shared library that actually links
1426
+ # to it.
1427
+ local raw = [ $(subvariant).sources-usage-requirements ] ;
1428
+ raw = [ $(raw).raw ] ;
1429
+ raw = [ property.change $(raw) : <pch-header> ] ;
1430
+ raw = [ property.change $(raw) : <pch-file> ] ;
1431
+ return [ $(result).add [ property-set.create $(raw) ] ] ;
1432
+ }
1433
+
1434
+ # Creates new subvariant instances for 'targets'.
1435
+ # 'root-targets' - virtual targets to be returned to dependants
1436
+ # 'all-targets' - virtual targets created while building this main target
1437
+ # 'build-request' - property-set instance with requested build properties
1438
+ #
1439
+ local rule create-subvariant ( root-targets * : all-targets * :
1440
+ build-request : sources * : rproperties : usage-requirements )
1441
+ {
1442
+ for local e in $(root-targets)
1443
+ {
1444
+ $(e).root true ;
1445
+ }
1446
+
1447
+ # Process all virtual targets that will be created if this main target
1448
+ # is created.
1449
+ local s = [ new subvariant $(__name__) : $(build-request) : $(sources) :
1450
+ $(rproperties) : $(usage-requirements) : $(all-targets) ] ;
1451
+ for local v in $(all-targets)
1452
+ {
1453
+ if ! [ $(v).creating-subvariant ]
1454
+ {
1455
+ $(v).creating-subvariant $(s) ;
1456
+ }
1457
+ }
1458
+ return $(s) ;
1459
+ }
1460
+
1461
+ # Constructs virtual targets for this abstract target and the dependency
1462
+ # graph. Returns a usage-requirements property-set and a list of virtual
1463
+ # targets. Should be overriden in derived classes.
1464
+ #
1465
+ rule construct ( name : source-targets * : properties * )
1466
+ {
1467
+ errors.error "method should be defined in derived classes" ;
1468
+ }
1469
+ }
1470
+
1471
+
1472
+ class typed-target : basic-target
1473
+ {
1474
+ import generators ;
1475
+
1476
+ rule __init__ ( name : project : type : sources * : requirements * :
1477
+ default-build * : usage-requirements * )
1478
+ {
1479
+ basic-target.__init__ $(name) : $(project) : $(sources) :
1480
+ $(requirements) : $(default-build) : $(usage-requirements) ;
1481
+
1482
+ self.type = $(type) ;
1483
+ }
1484
+
1485
+ rule type ( )
1486
+ {
1487
+ return $(self.type) ;
1488
+ }
1489
+
1490
+ rule construct ( name : source-targets * : property-set )
1491
+ {
1492
+ local r = [ generators.construct $(self.project) $(name:S=) : $(self.type)
1493
+ : [ property-set.create [ $(property-set).raw ]
1494
+ <main-target-type>$(self.type) ]
1495
+ : $(source-targets) : true ] ;
1496
+ if ! $(r)
1497
+ {
1498
+ ECHO "warn: Unable to construct" [ full-name ] ;
1499
+
1500
+ # Are there any top-level generators for this type/property set.
1501
+ if ! [ generators.find-viable-generators $(self.type)
1502
+ : $(property-set) ]
1503
+ {
1504
+ ECHO "error: no generators were found for type '$(self.type)'" ;
1505
+ ECHO "error: and the requested properties" ;
1506
+ ECHO "error: make sure you've configured the needed tools" ;
1507
+ ECHO "See http://boost.org/boost-build2/doc/html/bbv2/advanced/configuration.html" ;
1508
+ ECHO "To debug this problem, try the --debug-generators option." ;
1509
+ EXIT ;
1510
+ }
1511
+ }
1512
+ return $(r) ;
1513
+ }
1514
+ }
1515
+
1516
+
1517
+ # Return the list of sources to use, if main target rule is invoked with
1518
+ # 'sources'. If there are any objects in 'sources', they are treated as main
1519
+ # target instances, and the name of such targets are adjusted to be
1520
+ # '<name_of_this_target>__<name_of_source_target>'. Such renaming is disabled if
1521
+ # a non-empty value is passed as the 'no-renaming' parameter.
1522
+ #
1523
+ rule main-target-sources ( sources * : main-target-name : no-renaming ? )
1524
+ {
1525
+ local result ;
1526
+ for local t in $(sources)
1527
+ {
1528
+ if [ class.is-instance $(t) ]
1529
+ {
1530
+ local name = [ $(t).name ] ;
1531
+ if ! $(no-renaming)
1532
+ {
1533
+ name = $(main-target-name)__$(name) ;
1534
+ $(t).rename $(name) ;
1535
+ }
1536
+ # Inline targets are not built by default.
1537
+ local p = [ $(t).project ] ;
1538
+ $(p).mark-target-as-explicit $(name) ;
1539
+ result += $(name) ;
1540
+ }
1541
+ else
1542
+ {
1543
+ result += $(t) ;
1544
+ }
1545
+ }
1546
+ return $(result) ;
1547
+ }
1548
+
1549
+
1550
+ # Returns the requirements to use when declaring a main target, obtained by
1551
+ # translating all specified property paths and refining project requirements
1552
+ # with the ones specified for the target.
1553
+ #
1554
+ rule main-target-requirements (
1555
+ specification * # Properties explicitly specified for the main target.
1556
+ : project # Project where the main target is to be declared.
1557
+ )
1558
+ {
1559
+ specification += [ toolset.requirements ] ;
1560
+
1561
+ local requirements = [ property-set.refine-from-user-input
1562
+ [ $(project).get requirements ] : $(specification) :
1563
+ [ $(project).project-module ] : [ $(project).get location ] ] ;
1564
+ if $(requirements[1]) = "@error"
1565
+ {
1566
+ errors.error "Conflicting requirements for target:" $(requirements) ;
1567
+ }
1568
+ return $(requirements) ;
1569
+ }
1570
+
1571
+
1572
+ # Returns the usage requirements to use when declaring a main target, which are
1573
+ # obtained by translating all specified property paths and adding project's
1574
+ # usage requirements.
1575
+ #
1576
+ rule main-target-usage-requirements (
1577
+ specification * # Use-properties explicitly specified for a main target.
1578
+ : project # Project where the main target is to be declared.
1579
+ )
1580
+ {
1581
+ local project-usage-requirements = [ $(project).get usage-requirements ] ;
1582
+
1583
+ # We do not use 'refine-from-user-input' because:
1584
+ # - I am not sure if removing parent's usage requirements makes sense
1585
+ # - refining usage requirements is not needed, since usage requirements are
1586
+ # always free.
1587
+ local usage-requirements = [ property-set.create-from-user-input
1588
+ $(specification)
1589
+ : [ $(project).project-module ] [ $(project).get location ] ] ;
1590
+
1591
+ return [ $(project-usage-requirements).add $(usage-requirements) ] ;
1592
+ }
1593
+
1594
+
1595
+ # Return the default build value to use when declaring a main target, which is
1596
+ # obtained by using the specified value if not empty and parent's default build
1597
+ # attribute otherwise.
1598
+ #
1599
+ rule main-target-default-build (
1600
+ specification * # Default build explicitly specified for a main target.
1601
+ : project # Project where the main target is to be declared.
1602
+ )
1603
+ {
1604
+ local result ;
1605
+ if $(specification)
1606
+ {
1607
+ result = $(specification) ;
1608
+ }
1609
+ else
1610
+ {
1611
+ result = [ $(project).get default-build ] ;
1612
+ }
1613
+ return [ property-set.create-with-validation $(result) ] ;
1614
+ }
1615
+
1616
+
1617
+ # Registers the specified target as a main target alternative and returns it.
1618
+ #
1619
+ rule main-target-alternative ( target )
1620
+ {
1621
+ local ptarget = [ $(target).project ] ;
1622
+ $(ptarget).add-alternative $(target) ;
1623
+ return $(target) ;
1624
+ }
1625
+
1626
+ # Creates a new metargets with the specified properties, using 'klass' as
1627
+ # the class. The 'name', 'sources',
1628
+ # 'requirements', 'default-build' and 'usage-requirements' are assumed to be in
1629
+ # the form specified by the user in Jamfile corresponding to 'project'.
1630
+ #
1631
+ rule create-metatarget ( klass : project : name : sources * : requirements * :
1632
+ default-build * : usage-requirements * )
1633
+ {
1634
+ return [
1635
+ targets.main-target-alternative
1636
+ [ new $(klass) $(name) : $(project)
1637
+ : [ targets.main-target-sources $(sources) : $(name) ]
1638
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
1639
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
1640
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
1641
+ ] ] ;
1642
+ }
1643
+
1644
+ # Creates a typed-target with the specified properties. The 'name', 'sources',
1645
+ # 'requirements', 'default-build' and 'usage-requirements' are assumed to be in
1646
+ # the form specified by the user in Jamfile corresponding to 'project'.
1647
+ #
1648
+ rule create-typed-target ( type : project : name : sources * : requirements * :
1649
+ default-build * : usage-requirements * )
1650
+ {
1651
+ return [
1652
+ targets.main-target-alternative
1653
+ [ new typed-target $(name) : $(project) : $(type)
1654
+ : [ targets.main-target-sources $(sources) : $(name) ]
1655
+ : [ targets.main-target-requirements $(requirements) : $(project) ]
1656
+ : [ targets.main-target-default-build $(default-build) : $(project) ]
1657
+ : [ targets.main-target-usage-requirements $(usage-requirements) : $(project) ]
1658
+ ] ] ;
1659
+ }
mosesdecoder/jam-files/boost-build/build/version.jam ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2002, 2003, 2004, 2006 Vladimir Prus
2
+ # Copyright 2008 Jurko Gospodnetic
3
+ # Distributed under the Boost Software License, Version 1.0.
4
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
+
6
+ import errors ;
7
+ import numbers ;
8
+
9
+ major = "2011" ;
10
+ minor = "12" ;
11
+
12
+ rule boost-build ( )
13
+ {
14
+ return "$(major).$(minor)-svn" ;
15
+ }
16
+
17
+ rule print ( )
18
+ {
19
+ if [ verify-engine-version ]
20
+ {
21
+ ECHO "Boost.Build" [ boost-build ] ;
22
+ }
23
+ }
24
+
25
+ rule verify-engine-version ( )
26
+ {
27
+ local v = [ modules.peek : JAM_VERSION ] ;
28
+
29
+ if $(v[1]) != $(major) || $(v[2]) != $(minor)
30
+ {
31
+ local argv = [ modules.peek : ARGV ] ;
32
+ local e = $(argv[1]) ;
33
+ local l = [ modules.binding version ] ;
34
+ l = $(l:D) ;
35
+ l = $(l:D) ;
36
+ ECHO "warning: mismatched versions of Boost.Build engine and core" ;
37
+ ECHO "warning: Boost.Build engine ($(e)) is $(v:J=.)" ;
38
+ ECHO "warning: Boost.Build core (at $(l)) is" [ boost-build ] ;
39
+ }
40
+ else
41
+ {
42
+ return true ;
43
+ }
44
+ }
45
+
46
+
47
+
48
+ # Utility rule for testing whether all elements in a sequence are equal to 0.
49
+ #
50
+ local rule is-all-zeroes ( sequence * )
51
+ {
52
+ local result = "true" ;
53
+ for local e in $(sequence)
54
+ {
55
+ if $(e) != "0"
56
+ {
57
+ result = "" ;
58
+ }
59
+ }
60
+ return $(result) ;
61
+ }
62
+
63
+
64
+ # Returns "true" if the first version is less than the second one.
65
+ #
66
+ rule version-less ( lhs + : rhs + )
67
+ {
68
+ numbers.check $(lhs) ;
69
+ numbers.check $(rhs) ;
70
+
71
+ local done ;
72
+ local result ;
73
+
74
+ while ! $(done) && $(lhs) && $(rhs)
75
+ {
76
+ if [ numbers.less $(lhs[1]) $(rhs[1]) ]
77
+ {
78
+ done = "true" ;
79
+ result = "true" ;
80
+ }
81
+ else if [ numbers.less $(rhs[1]) $(lhs[1]) ]
82
+ {
83
+ done = "true" ;
84
+ }
85
+ else
86
+ {
87
+ lhs = $(lhs[2-]) ;
88
+ rhs = $(rhs[2-]) ;
89
+ }
90
+ }
91
+ if ( ! $(done) && ! $(lhs) && ! [ is-all-zeroes $(rhs) ] )
92
+ {
93
+ result = "true" ;
94
+ }
95
+
96
+ return $(result) ;
97
+ }
98
+
99
+
100
+ # Returns "true" if the current JAM version version is at least the given
101
+ # version.
102
+ #
103
+ rule check-jam-version ( version + )
104
+ {
105
+ local version-tag = $(version:J=.) ;
106
+ if ! $(version-tag)
107
+ {
108
+ errors.error Invalid version specifier: : $(version:E="(undefined)") ;
109
+ }
110
+
111
+ if ! $(.jam-version-check.$(version-tag))-is-not-empty
112
+ {
113
+ local jam-version = [ modules.peek : JAM_VERSION ] ;
114
+ if ! $(jam-version)
115
+ {
116
+ errors.error "Unable to deduce Boost Jam version. Your Boost Jam"
117
+ "installation is most likely terribly outdated." ;
118
+ }
119
+ .jam-version-check.$(version-tag) = "true" ;
120
+ if [ version-less [ modules.peek : JAM_VERSION ] : $(version) ]
121
+ {
122
+ .jam-version-check.$(version-tag) = "" ;
123
+ }
124
+ }
125
+ return $(.jam-version-check.$(version-tag)) ;
126
+ }
127
+
128
+
129
+ rule __test__ ( )
130
+ {
131
+ import assert ;
132
+
133
+ local jam-version = [ modules.peek : JAM_VERSION ] ;
134
+ local future-version = $(jam-version) ;
135
+ future-version += "1" ;
136
+
137
+ assert.true check-jam-version $(jam-version) ;
138
+ assert.false check-jam-version $(future-version) ;
139
+
140
+ assert.true version-less 0 : 1 ;
141
+ assert.false version-less 0 : 0 ;
142
+ assert.true version-less 1 : 2 ;
143
+ assert.false version-less 1 : 1 ;
144
+ assert.false version-less 2 : 1 ;
145
+ assert.true version-less 3 1 20 : 3 4 10 ;
146
+ assert.false version-less 3 1 10 : 3 1 10 ;
147
+ assert.false version-less 3 4 10 : 3 1 20 ;
148
+ assert.true version-less 3 1 20 5 1 : 3 4 10 ;
149
+ assert.false version-less 3 1 10 5 1 : 3 1 10 ;
150
+ assert.false version-less 3 4 10 5 1 : 3 1 20 ;
151
+ assert.true version-less 3 1 20 : 3 4 10 5 1 ;
152
+ assert.true version-less 3 1 10 : 3 1 10 5 1 ;
153
+ assert.false version-less 3 4 10 : 3 1 20 5 1 ;
154
+ assert.false version-less 3 1 10 : 3 1 10 0 0 ;
155
+ assert.false version-less 3 1 10 0 0 : 3 1 10 ;
156
+ assert.false version-less 3 1 10 0 : 3 1 10 0 0 ;
157
+ assert.false version-less 3 1 10 0 : 03 1 10 0 0 ;
158
+ assert.false version-less 03 1 10 0 : 3 1 10 0 0 ;
159
+
160
+ # TODO: Add tests for invalid input data being sent to version-less.
161
+ }
mosesdecoder/jam-files/boost-build/build/virtual-target.jam ADDED
@@ -0,0 +1,1317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2003 Dave Abrahams
2
+ # Copyright 2005, 2006 Rene Rivera
3
+ # Copyright 2002, 2003, 2004, 2005, 2006 Vladimir Prus
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ # Implements virtual targets, which correspond to actual files created during a
8
+ # build, but are not yet targets in Jam sense. They are needed, for example,
9
+ # when searching for possible transformation sequences, when it is not yet known
10
+ # whether a particular target should be created at all.
11
+
12
+ import "class" : new ;
13
+ import errors ;
14
+ import path ;
15
+ import sequence ;
16
+ import set ;
17
+ import type ;
18
+ import utility ;
19
+
20
+
21
+ # +--------------------------+
22
+ # | virtual-target |
23
+ # +==========================+
24
+ # | actualize |
25
+ # +--------------------------+
26
+ # | actualize-action() = 0 |
27
+ # | actualize-location() = 0 |
28
+ # +----------------+---------+
29
+ # |
30
+ # ^
31
+ # / \
32
+ # +-+-+
33
+ # |
34
+ # +---------------------+ +-------+--------------+
35
+ # | action | | abstract-file-target |
36
+ # +=====================| * +======================+
37
+ # | action-name | +--+ action |
38
+ # | properties | | +----------------------+
39
+ # +---------------------+--+ | actualize-action() |
40
+ # | actualize() |0..1 +-----------+----------+
41
+ # | path() | |
42
+ # | adjust-properties() | sources |
43
+ # | actualize-sources() | targets |
44
+ # +------+--------------+ ^
45
+ # | / \
46
+ # ^ +-+-+
47
+ # / \ |
48
+ # +-+-+ +-------------+-------------+
49
+ # | | |
50
+ # | +------+---------------+ +--------+-------------+
51
+ # | | file-target | | searched-lib-target |
52
+ # | +======================+ +======================+
53
+ # | | actualize-location() | | actualize-location() |
54
+ # | +----------------------+ +----------------------+
55
+ # |
56
+ # +-+------------------------------+
57
+ # | |
58
+ # +----+----------------+ +---------+-----------+
59
+ # | compile-action | | link-action |
60
+ # +=====================+ +=====================+
61
+ # | adjust-properties() | | adjust-properties() |
62
+ # +---------------------+ | actualize-sources() |
63
+ # +---------------------+
64
+ #
65
+ # The 'compile-action' and 'link-action' classes are not defined here but in
66
+ # builtin.jam modules. They are shown in the diagram to give the big picture.
67
+
68
+
69
+ # Models a potential target. It can be converted into a Jam target and used in
70
+ # building, if needed. However, it can be also dropped, which allows us to
71
+ # search for different transformations and select only one.
72
+ #
73
+ class virtual-target
74
+ {
75
+ import scanner ;
76
+ import sequence ;
77
+ import utility ;
78
+ import virtual-target ;
79
+
80
+ rule __init__ (
81
+ name # Target/project name.
82
+ : project # Project to which this target belongs.
83
+ )
84
+ {
85
+ self.name = $(name) ;
86
+ self.project = $(project) ;
87
+ self.dependencies = ;
88
+ }
89
+
90
+ # Name of this target.
91
+ #
92
+ rule name ( )
93
+ {
94
+ return $(self.name) ;
95
+ }
96
+
97
+ # Project of this target.
98
+ #
99
+ rule project ( )
100
+ {
101
+ return $(self.project) ;
102
+ }
103
+
104
+ # Adds additional 'virtual-target' instances this one depends on.
105
+ #
106
+ rule depends ( d + )
107
+ {
108
+ self.dependencies = [ sequence.merge $(self.dependencies) :
109
+ [ sequence.insertion-sort $(d) ] ] ;
110
+ }
111
+
112
+ rule dependencies ( )
113
+ {
114
+ return $(self.dependencies) ;
115
+ }
116
+
117
+ rule always ( )
118
+ {
119
+ .always = 1 ;
120
+ }
121
+
122
+ # Generates all the actual targets and sets up build actions for this
123
+ # target.
124
+ #
125
+ # If 'scanner' is specified, creates an additional target with the same
126
+ # location as the actual target, which will depend on the actual target and
127
+ # be associated with a 'scanner'. That additional target is returned. See
128
+ # the docs (#dependency_scanning) for rationale. Target must correspond to a
129
+ # file if 'scanner' is specified.
130
+ #
131
+ # If scanner is not specified then the actual target is returned.
132
+ #
133
+ rule actualize ( scanner ? )
134
+ {
135
+ local actual-name = [ actualize-no-scanner ] ;
136
+
137
+ if $(.always)
138
+ {
139
+ ALWAYS $(actual-name) ;
140
+ }
141
+
142
+ if ! $(scanner)
143
+ {
144
+ return $(actual-name) ;
145
+ }
146
+ else
147
+ {
148
+ # Add the scanner instance to the grist for name.
149
+ local g = [ sequence.join
150
+ [ utility.ungrist $(actual-name:G) ] $(scanner) : - ] ;
151
+ local name = $(actual-name:G=$(g)) ;
152
+
153
+ if ! $(self.made.$(name))
154
+ {
155
+ self.made.$(name) = true ;
156
+
157
+ DEPENDS $(name) : $(actual-name) ;
158
+
159
+ actualize-location $(name) ;
160
+
161
+ scanner.install $(scanner) : $(name) $(__name__) ;
162
+ }
163
+ return $(name) ;
164
+ }
165
+ }
166
+
167
+ # private: (overridables)
168
+
169
+ # Sets up build actions for 'target'. Should call appropriate rules and set
170
+ # target variables.
171
+ #
172
+ rule actualize-action ( target )
173
+ {
174
+ errors.error "method should be defined in derived classes" ;
175
+ }
176
+
177
+ # Sets up variables on 'target' which specify its location.
178
+ #
179
+ rule actualize-location ( target )
180
+ {
181
+ errors.error "method should be defined in derived classes" ;
182
+ }
183
+
184
+ # If the target is a generated one, returns the path where it will be
185
+ # generated. Otherwise, returns an empty list.
186
+ #
187
+ rule path ( )
188
+ {
189
+ errors.error "method should be defined in derived classes" ;
190
+ }
191
+
192
+ # Returns the actual target name to be used in case when no scanner is
193
+ # involved.
194
+ #
195
+ rule actual-name ( )
196
+ {
197
+ errors.error "method should be defined in derived classes" ;
198
+ }
199
+
200
+ # implementation
201
+ rule actualize-no-scanner ( )
202
+ {
203
+ # In fact, we just need to merge virtual-target with
204
+ # abstract-file-target as the latter is the only class derived from the
205
+ # former. But that has been left for later.
206
+
207
+ errors.error "method should be defined in derived classes" ;
208
+ }
209
+ }
210
+
211
+
212
+ # Target corresponding to a file. The exact mapping for file is not yet
213
+ # specified in this class. (TODO: Actually, the class name could be better...)
214
+ #
215
+ # May be a source file (when no action is specified) or a derived file
216
+ # (otherwise).
217
+ #
218
+ # The target's grist is a concatenation of its project's location, action
219
+ # properties (for derived targets) and, optionally, value identifying the main
220
+ # target.
221
+ #
222
+ class abstract-file-target : virtual-target
223
+ {
224
+ import project ;
225
+ import regex ;
226
+ import sequence ;
227
+ import path ;
228
+ import type ;
229
+ import property-set ;
230
+ import indirect ;
231
+
232
+ rule __init__ (
233
+ name # Target's name.
234
+ exact ? # If non-empty, the name is exactly the name created file
235
+ # should have. Otherwise, the '__init__' method will add a
236
+ # suffix obtained from 'type' by calling
237
+ # 'type.generated-target-suffix'.
238
+ : type ? # Target's type.
239
+ : project
240
+ : action ?
241
+ )
242
+ {
243
+ virtual-target.__init__ $(name) : $(project) ;
244
+
245
+ self.type = $(type) ;
246
+ self.action = $(action) ;
247
+ if $(action)
248
+ {
249
+ $(action).add-targets $(__name__) ;
250
+
251
+ if $(self.type) && ! $(exact)
252
+ {
253
+ _adjust-name $(name) ;
254
+ }
255
+ }
256
+ }
257
+
258
+ rule type ( )
259
+ {
260
+ return $(self.type) ;
261
+ }
262
+
263
+ # Sets the path. When generating target name, it will override any path
264
+ # computation from properties.
265
+ #
266
+ rule set-path ( path )
267
+ {
268
+ self.path = [ path.native $(path) ] ;
269
+ }
270
+
271
+ # Returns the currently set action.
272
+ #
273
+ rule action ( )
274
+ {
275
+ return $(self.action) ;
276
+ }
277
+
278
+ # Sets/gets the 'root' flag. Target is root if it directly corresponds to
279
+ # some variant of a main target.
280
+ #
281
+ rule root ( set ? )
282
+ {
283
+ if $(set)
284
+ {
285
+ self.root = true ;
286
+ }
287
+ return $(self.root) ;
288
+ }
289
+
290
+ # Gets or sets the subvariant which created this target. Subvariant is set
291
+ # when target is brought into existance and is never changed after that. In
292
+ # particular, if a target is shared by a subvariant, only the first is
293
+ # stored.
294
+ #
295
+ rule creating-subvariant ( s ? # If specified, specifies the value to set,
296
+ # which should be a 'subvariant' class
297
+ # instance.
298
+ )
299
+ {
300
+ if $(s) && ! $(self.creating-subvariant)
301
+ {
302
+ self.creating-subvariant = $(s) ;
303
+ }
304
+ return $(self.creating-subvariant) ;
305
+ }
306
+
307
+ rule actualize-action ( target )
308
+ {
309
+ if $(self.action)
310
+ {
311
+ $(self.action).actualize ;
312
+ }
313
+ }
314
+
315
+ # Return a human-readable representation of this target. If this target has
316
+ # an action, that is:
317
+ #
318
+ # { <action-name>-<self.name>.<self.type> <action-sources>... }
319
+ #
320
+ # otherwise, it is:
321
+ #
322
+ # { <self.name>.<self.type> }
323
+ #
324
+ rule str ( )
325
+ {
326
+ local action = [ action ] ;
327
+ local name-dot-type = [ sequence.join $(self.name) "." $(self.type) ] ;
328
+
329
+ if $(action)
330
+ {
331
+ local sources = [ $(action).sources ] ;
332
+ local action-name = [ $(action).action-name ] ;
333
+
334
+ local ss ;
335
+ for local s in $(sources)
336
+ {
337
+ ss += [ $(s).str ] ;
338
+ }
339
+
340
+ return "{" $(action-name)-$(name-dot-type) $(ss) "}" ;
341
+ }
342
+ else
343
+ {
344
+ return "{" $(name-dot-type) "}" ;
345
+ }
346
+ }
347
+
348
+ rule less ( a )
349
+ {
350
+ if [ str ] < [ $(a).str ]
351
+ {
352
+ return true ;
353
+ }
354
+ }
355
+
356
+ rule equal ( a )
357
+ {
358
+ if [ str ] = [ $(a).str ]
359
+ {
360
+ return true ;
361
+ }
362
+ }
363
+
364
+ # private:
365
+ rule actual-name ( )
366
+ {
367
+ if ! $(self.actual-name)
368
+ {
369
+ local grist = [ grist ] ;
370
+ local basename = [ path.native $(self.name) ] ;
371
+ self.actual-name = <$(grist)>$(basename) ;
372
+ }
373
+ return $(self.actual-name) ;
374
+ }
375
+
376
+ # Helper to 'actual-name', above. Computes a unique prefix used to
377
+ # distinguish this target from other targets with the same name creating
378
+ # different files.
379
+ #
380
+ rule grist ( )
381
+ {
382
+ # Depending on target, there may be different approaches to generating
383
+ # unique prefixes. We generate prefixes in the form:
384
+ # <one letter approach code> <the actual prefix>
385
+ local path = [ path ] ;
386
+ if $(path)
387
+ {
388
+ # The target will be generated to a known path. Just use the path
389
+ # for identification, since path is as unique as it can get.
390
+ return p$(path) ;
391
+ }
392
+ else
393
+ {
394
+ # File is either source, which will be searched for, or is not a
395
+ # file at all. Use the location of project for distinguishing.
396
+ local project-location = [ $(self.project).get location ] ;
397
+ local location-grist = [ sequence.join [ regex.split
398
+ $(project-location) "/" ] : "!" ] ;
399
+
400
+ if $(self.action)
401
+ {
402
+ local ps = [ $(self.action).properties ] ;
403
+ local property-grist = [ $(ps).as-path ] ;
404
+ # 'property-grist' can be empty when 'ps' is an empty property
405
+ # set.
406
+ if $(property-grist)
407
+ {
408
+ location-grist = $(location-grist)/$(property-grist) ;
409
+ }
410
+ }
411
+
412
+ return l$(location-grist) ;
413
+ }
414
+ }
415
+
416
+ # Given the target name specified in constructor, returns the name which
417
+ # should be really used, by looking at the <tag> properties. Tag properties
418
+ # need to be specified as <tag>@rule-name. This makes Boost Build call the
419
+ # specified rule with the target name, type and properties to get the new
420
+ # name. If no <tag> property is specified or the rule specified by <tag>
421
+ # returns nothing, returns the result of calling
422
+ # virtual-target.add-prefix-and-suffix.
423
+ #
424
+ rule _adjust-name ( specified-name )
425
+ {
426
+ local ps ;
427
+ if $(self.action)
428
+ {
429
+ ps = [ $(self.action).properties ] ;
430
+ }
431
+ else
432
+ {
433
+ ps = [ property-set.empty ] ;
434
+ }
435
+
436
+ # We add ourselves to the properties so that any tag rule can get more
437
+ # direct information about the target than just that available through
438
+ # the properties. This is useful in implementing name changes based on
439
+ # the sources of the target. For example to make unique names of object
440
+ # files based on the source file. --grafik
441
+ ps = [ property-set.create [ $(ps).raw ] <target>$(__name__) ] ;
442
+
443
+ local tag = [ $(ps).get <tag> ] ;
444
+
445
+ if $(tag)
446
+ {
447
+ local rule-name = [ MATCH ^@(.*) : $(tag) ] ;
448
+ if $(rule-name)
449
+ {
450
+ if $(tag[2])
451
+ {
452
+ errors.error "<tag>@rulename is present but is not the only"
453
+ "<tag> feature" ;
454
+ }
455
+
456
+ self.name = [ indirect.call $(rule-name) $(specified-name)
457
+ : $(self.type) : $(ps) ] ;
458
+ }
459
+ else
460
+ {
461
+ errors.error
462
+ "The value of the <tag> feature must be '@rule-name'" ;
463
+ }
464
+ }
465
+
466
+ # If there is no tag or the tag rule returned nothing.
467
+ if ! $(tag) || ! $(self.name)
468
+ {
469
+ self.name = [ virtual-target.add-prefix-and-suffix $(specified-name)
470
+ : $(self.type) : $(ps) ] ;
471
+ }
472
+ }
473
+
474
+ rule actualize-no-scanner ( )
475
+ {
476
+ local name = [ actual-name ] ;
477
+
478
+ # Do anything only on the first invocation.
479
+ if ! $(self.made.$(name))
480
+ {
481
+ self.made.$(name) = true ;
482
+
483
+ if $(self.action)
484
+ {
485
+ # For non-derived target, we do not care if there are several
486
+ # virtual targets that refer to the same name. One case when
487
+ # this is unavoidable is when the file name is main.cpp and two
488
+ # targets have types CPP (for compiling) and MOCCABLE_CPP (for
489
+ # conversion to H via Qt tools).
490
+ virtual-target.register-actual-name $(name) : $(__name__) ;
491
+ }
492
+
493
+ for local i in $(self.dependencies)
494
+ {
495
+ DEPENDS $(name) : [ $(i).actualize ] ;
496
+ }
497
+
498
+ actualize-location $(name) ;
499
+ actualize-action $(name) ;
500
+ }
501
+ return $(name) ;
502
+ }
503
+ }
504
+
505
+
506
+ # Appends the suffix appropriate to 'type/property-set' combination to the
507
+ # specified name and returns the result.
508
+ #
509
+ rule add-prefix-and-suffix ( specified-name : type ? : property-set )
510
+ {
511
+ local suffix = [ type.generated-target-suffix $(type) : $(property-set) ] ;
512
+
513
+ # Handle suffixes for which no leading dot is desired. Those are specified
514
+ # by enclosing them in <...>. Needed by python so it can create "_d.so"
515
+ # extensions, for example.
516
+ if $(suffix:G)
517
+ {
518
+ suffix = [ utility.ungrist $(suffix) ] ;
519
+ }
520
+ else
521
+ {
522
+ suffix = .$(suffix) ;
523
+ }
524
+
525
+ local prefix = [ type.generated-target-prefix $(type) : $(property-set) ] ;
526
+
527
+ if [ MATCH ^($(prefix)) : $(specified-name) ]
528
+ {
529
+ prefix = ;
530
+ }
531
+ return $(prefix:E="")$(specified-name)$(suffix:E="") ;
532
+ }
533
+
534
+
535
+ # File targets with explicitly known location.
536
+ #
537
+ # The file path is determined as
538
+ # * Value passed to the 'set-path' method, if any.
539
+ # * For derived files, project's build dir, joined with components that
540
+ # describe action properties. If free properties are not equal to the
541
+ # project's reference properties an element with the name of the main
542
+ # target is added.
543
+ # * For source files, project's source dir.
544
+ #
545
+ # The file suffix is determined as:
546
+ # * The value passed to the 'suffix' method, if any.
547
+ # * The suffix corresponding to the target's type.
548
+ #
549
+ class file-target : abstract-file-target
550
+ {
551
+ import "class" : new ;
552
+ import common ;
553
+ import errors ;
554
+
555
+ rule __init__ (
556
+ name exact ?
557
+ : type ? # Optional type for this target.
558
+ : project
559
+ : action ?
560
+ : path ?
561
+ )
562
+ {
563
+ abstract-file-target.__init__ $(name) $(exact) : $(type) : $(project) :
564
+ $(action) ;
565
+
566
+ self.path = $(path) ;
567
+ }
568
+
569
+ rule clone-with-different-type ( new-type )
570
+ {
571
+ return [ new file-target $(self.name) exact : $(new-type) :
572
+ $(self.project) : $(self.action) : $(self.path) ] ;
573
+ }
574
+
575
+ rule actualize-location ( target )
576
+ {
577
+ if $(self.action)
578
+ {
579
+ # This is a derived file.
580
+ local path = [ path ] ;
581
+ LOCATE on $(target) = $(path) ;
582
+
583
+ # Make sure the path exists.
584
+ DEPENDS $(target) : $(path) ;
585
+ common.MkDir $(path) ;
586
+
587
+ # It is possible that the target name includes a directory too, for
588
+ # example when installing headers. Create that directory.
589
+ if $(target:D)
590
+ {
591
+ local d = $(target:D) ;
592
+ d = $(d:R=$(path)) ;
593
+ DEPENDS $(target) : $(d) ;
594
+ common.MkDir $(d) ;
595
+ }
596
+
597
+ # For a real file target, we create a fake target depending on the
598
+ # real target. This allows us to run
599
+ #
600
+ # bjam hello.o
601
+ #
602
+ # without trying to guess the name of the real target. Note that the
603
+ # target has no directory name and uses a special <e> grist.
604
+ #
605
+ # First, that means that "bjam hello.o" will build all known hello.o
606
+ # targets. Second, the <e> grist makes sure this target will not be
607
+ # confused with other targets, for example, if we have subdir 'test'
608
+ # with target 'test' in it that includes a 'test.o' file, then the
609
+ # target for directory will be just 'test' the target for test.o
610
+ # will be <ptest/bin/gcc/debug>test.o and the target we create below
611
+ # will be <e>test.o
612
+ DEPENDS $(target:G=e) : $(target) ;
613
+ # Allow bjam <path-to-file>/<file> to work. This will not catch all
614
+ # possible ways to refer to the path (relative/absolute, extra ".",
615
+ # various "..", but should help in obvious cases.
616
+ DEPENDS $(target:G=e:R=$(path)) : $(target) ;
617
+ }
618
+ else
619
+ {
620
+ SEARCH on $(target) = [ path.native $(self.path) ] ;
621
+ }
622
+ }
623
+
624
+ # Returns the directory for this target.
625
+ #
626
+ rule path ( )
627
+ {
628
+ if ! $(self.path)
629
+ {
630
+ if $(self.action)
631
+ {
632
+ local p = [ $(self.action).properties ] ;
633
+ local path,relative-to-build-dir = [ $(p).target-path ] ;
634
+ local path = $(path,relative-to-build-dir[1]) ;
635
+ local relative-to-build-dir = $(path,relative-to-build-dir[2]) ;
636
+
637
+ if $(relative-to-build-dir)
638
+ {
639
+ path = [ path.join [ $(self.project).build-dir ] $(path) ] ;
640
+ }
641
+
642
+ self.path = [ path.native $(path) ] ;
643
+ }
644
+ }
645
+ return $(self.path) ;
646
+ }
647
+ }
648
+
649
+
650
+ class notfile-target : abstract-file-target
651
+ {
652
+ rule __init__ ( name : project : action ? )
653
+ {
654
+ abstract-file-target.__init__ $(name) : : $(project) : $(action) ;
655
+ }
656
+
657
+ # Returns nothing to indicate that the target's path is not known.
658
+ #
659
+ rule path ( )
660
+ {
661
+ return ;
662
+ }
663
+
664
+ rule actualize-location ( target )
665
+ {
666
+ NOTFILE $(target) ;
667
+ ALWAYS $(target) ;
668
+ # TEMPORARY $(target) ;
669
+ NOUPDATE $(target) ;
670
+ }
671
+ }
672
+
673
+
674
+ # Class representing an action. Both 'targets' and 'sources' should list
675
+ # instances of 'virtual-target'. Action name should name a rule with this
676
+ # prototype:
677
+ # rule action-name ( targets + : sources * : properties * )
678
+ # Targets and sources are passed as actual Jam targets. The rule may not
679
+ # establish additional dependency relationships.
680
+ #
681
+ class action
682
+ {
683
+ import "class" ;
684
+ import errors ;
685
+ import type ;
686
+ import toolset ;
687
+ import property-set ;
688
+ import indirect ;
689
+ import path ;
690
+ import set : difference ;
691
+
692
+ rule __init__ ( sources * : action-name + : property-set ? )
693
+ {
694
+ self.sources = $(sources) ;
695
+
696
+ self.action-name = [ indirect.make-qualified $(action-name) ] ;
697
+
698
+ if ! $(property-set)
699
+ {
700
+ property-set = [ property-set.empty ] ;
701
+ }
702
+
703
+ if ! [ class.is-instance $(property-set) ]
704
+ {
705
+ errors.error "Property set instance required" ;
706
+ }
707
+
708
+ self.properties = $(property-set) ;
709
+ }
710
+
711
+ rule add-targets ( targets * )
712
+ {
713
+ self.targets += $(targets) ;
714
+ }
715
+
716
+ rule replace-targets ( old-targets * : new-targets * )
717
+ {
718
+ self.targets = [ set.difference $(self.targets) : $(old-targets) ] ;
719
+ self.targets += $(new-targets) ;
720
+ }
721
+
722
+ rule targets ( )
723
+ {
724
+ return $(self.targets) ;
725
+ }
726
+
727
+ rule sources ( )
728
+ {
729
+ return $(self.sources) ;
730
+ }
731
+
732
+ rule action-name ( )
733
+ {
734
+ return $(self.action-name) ;
735
+ }
736
+
737
+ rule properties ( )
738
+ {
739
+ return $(self.properties) ;
740
+ }
741
+
742
+ # Generates actual build instructions.
743
+ #
744
+ rule actualize ( )
745
+ {
746
+ if ! $(self.actualized)
747
+ {
748
+ self.actualized = true ;
749
+
750
+ local ps = [ properties ] ;
751
+ local properties = [ adjust-properties $(ps) ] ;
752
+
753
+ local actual-targets ;
754
+ for local i in [ targets ]
755
+ {
756
+ actual-targets += [ $(i).actualize ] ;
757
+ }
758
+
759
+ actualize-sources [ sources ] : $(properties) ;
760
+
761
+ DEPENDS $(actual-targets) : $(self.actual-sources)
762
+ $(self.dependency-only-sources) ;
763
+
764
+ # This works around a bug with -j and actions that
765
+ # produce multiple target, where:
766
+ # - dependency on the first output is found, and
767
+ # the action is started
768
+ # - dependency on the second output is found, and
769
+ # bjam noticed that command is already running
770
+ # - instead of waiting for the command, dependents
771
+ # of the second targets are immediately updated.
772
+ if $(actual-targets[2])
773
+ {
774
+ INCLUDES $(actual-targets) : $(actual-targets) ;
775
+ }
776
+
777
+ # Action name can include additional argument to rule, which should
778
+ # not be passed to 'set-target-variables'
779
+ toolset.set-target-variables
780
+ [ indirect.get-rule $(self.action-name[1]) ] $(actual-targets)
781
+ : $(properties) ;
782
+
783
+ # Reflect ourselves in a variable for the target. This allows
784
+ # looking up additional info for the action given the raw target.
785
+ # For example to debug or output action information from action
786
+ # rules.
787
+ .action on $(actual-targets) = $(__name__) ;
788
+
789
+ indirect.call $(self.action-name) $(actual-targets)
790
+ : $(self.actual-sources) : [ $(properties).raw ] ;
791
+
792
+ # Since we set up the creating action here, we set up the action for
793
+ # cleaning up as well.
794
+ common.Clean clean-all : $(actual-targets) ;
795
+ }
796
+ }
797
+
798
+ # Helper for 'actualize-sources'. For each passed source, actualizes it with
799
+ # the appropriate scanner. Returns the actualized virtual targets.
800
+ #
801
+ rule actualize-source-type ( sources * : property-set )
802
+ {
803
+ local result = ;
804
+ for local i in $(sources)
805
+ {
806
+ local scanner ;
807
+ if [ $(i).type ]
808
+ {
809
+ scanner = [ type.get-scanner [ $(i).type ] : $(property-set) ] ;
810
+ }
811
+ result += [ $(i).actualize $(scanner) ] ;
812
+ }
813
+ return $(result) ;
814
+ }
815
+
816
+ # Creates actual Jam targets for sources. Initializes the following member
817
+ # variables:
818
+ # 'self.actual-sources' -- sources passed to the updating action.
819
+ # 'self.dependency-only-sources' -- sources marked as dependencies, but
820
+ # are not used otherwise.
821
+ #
822
+ # New values will be *appended* to the variables. They may be non-empty if
823
+ # caller wants it.
824
+ #
825
+ rule actualize-sources ( sources * : property-set )
826
+ {
827
+ local dependencies = [ $(self.properties).get <dependency> ] ;
828
+
829
+ self.dependency-only-sources +=
830
+ [ actualize-source-type $(dependencies) : $(property-set) ] ;
831
+ self.actual-sources +=
832
+ [ actualize-source-type $(sources) : $(property-set) ] ;
833
+
834
+ # This is used to help bjam find dependencies in generated headers and
835
+ # other main targets, e.g. in:
836
+ #
837
+ # make a.h : ....... ;
838
+ # exe hello : hello.cpp : <implicit-dependency>a.h ;
839
+ #
840
+ # For bjam to find the dependency the generated target must be
841
+ # actualized (i.e. have its Jam target constructed). In the above case,
842
+ # if we are building just hello ("bjam hello"), 'a.h' will not be
843
+ # actualized unless we do it here.
844
+ local implicit = [ $(self.properties).get <implicit-dependency> ] ;
845
+ for local i in $(implicit)
846
+ {
847
+ $(i:G=).actualize ;
848
+ }
849
+ }
850
+
851
+ # Determines real properties when trying to build with 'properties'. This is
852
+ # the last chance to fix properties, for example to adjust includes to get
853
+ # generated headers correctly. Default implementation simply returns its
854
+ # argument.
855
+ #
856
+ rule adjust-properties ( property-set )
857
+ {
858
+ return $(property-set) ;
859
+ }
860
+ }
861
+
862
+
863
+ # Action class which does nothing --- it produces the targets with specific
864
+ # properties out of nowhere. It is needed to distinguish virtual targets with
865
+ # different properties that are known to exist and have no actions which create
866
+ # them.
867
+ #
868
+ class null-action : action
869
+ {
870
+ rule __init__ ( property-set ? )
871
+ {
872
+ action.__init__ : .no-action : $(property-set) ;
873
+ }
874
+
875
+ rule actualize ( )
876
+ {
877
+ if ! $(self.actualized)
878
+ {
879
+ self.actualized = true ;
880
+ for local i in [ targets ]
881
+ {
882
+ $(i).actualize ;
883
+ }
884
+ }
885
+ }
886
+ }
887
+
888
+
889
+ # Class which acts exactly like 'action', except that its sources are not
890
+ # scanned for dependencies.
891
+ #
892
+ class non-scanning-action : action
893
+ {
894
+ rule __init__ ( sources * : action-name + : property-set ? )
895
+ {
896
+ action.__init__ $(sources) : $(action-name) : $(property-set) ;
897
+ }
898
+
899
+ rule actualize-source-type ( sources * : property-set )
900
+ {
901
+ local result ;
902
+ for local i in $(sources)
903
+ {
904
+ result += [ $(i).actualize ] ;
905
+ }
906
+ return $(result) ;
907
+ }
908
+ }
909
+
910
+
911
+ # Creates a virtual target with an appropriate name and type from 'file'. If a
912
+ # target with that name in that project already exists, returns that already
913
+ # created target.
914
+ #
915
+ # FIXME: a more correct way would be to compute the path to the file, based on
916
+ # name and source location for the project, and use that path to determine if
917
+ # the target has already been created. This logic should be shared with how we
918
+ # usually find targets identified by a specific target id. It should also be
919
+ # updated to work correctly when the file is specified using both relative and
920
+ # absolute paths.
921
+ #
922
+ # TODO: passing a project with all virtual targets is starting to be annoying.
923
+ #
924
+ rule from-file ( file : file-loc : project )
925
+ {
926
+ import type ; # Had to do this here to break a circular dependency.
927
+
928
+ # Check whether we already created a target corresponding to this file.
929
+ local path = [ path.root [ path.root $(file) $(file-loc) ] [ path.pwd ] ] ;
930
+
931
+ if $(.files.$(path))
932
+ {
933
+ return $(.files.$(path)) ;
934
+ }
935
+ else
936
+ {
937
+ local name = [ path.make $(file) ] ;
938
+ local type = [ type.type $(file) ] ;
939
+ local result ;
940
+
941
+ result = [ new file-target $(file) : $(type) : $(project) : :
942
+ $(file-loc) ] ;
943
+
944
+ .files.$(path) = $(result) ;
945
+ return $(result) ;
946
+ }
947
+ }
948
+
949
+
950
+ # Registers a new virtual target. Checks if there is already a registered target
951
+ # with the same name, type, project and subvariant properties as well as the
952
+ # same sources and equal action. If such target is found it is returned and a
953
+ # new 'target' is not registered. Otherwise, 'target' is registered and
954
+ # returned.
955
+ #
956
+ rule register ( target )
957
+ {
958
+ local signature = [ sequence.join
959
+ [ $(target).path ] [ $(target).name ] : - ] ;
960
+
961
+ local result ;
962
+ for local t in $(.cache.$(signature))
963
+ {
964
+ local a1 = [ $(t).action ] ;
965
+ local a2 = [ $(target).action ] ;
966
+
967
+ if ! $(result)
968
+ {
969
+ if ! $(a1) && ! $(a2)
970
+ {
971
+ result = $(t) ;
972
+ }
973
+ else
974
+ {
975
+ if $(a1) && $(a2) &&
976
+ ( [ $(a1).action-name ] = [ $(a2).action-name ] ) &&
977
+ ( [ $(a1).sources ] = [ $(a2).sources ] )
978
+ {
979
+ local ps1 = [ $(a1).properties ] ;
980
+ local ps2 = [ $(a2).properties ] ;
981
+ local p1 = [ $(ps1).base ] [ $(ps1).free ] [ set.difference
982
+ [ $(ps1).dependency ] : [ $(ps1).incidental ] ] ;
983
+ local p2 = [ $(ps2).base ] [ $(ps2).free ] [ set.difference
984
+ [ $(ps2).dependency ] : [ $(ps2).incidental ] ] ;
985
+ if $(p1) = $(p2)
986
+ {
987
+ result = $(t) ;
988
+ }
989
+ }
990
+ }
991
+ }
992
+ }
993
+
994
+ if ! $(result)
995
+ {
996
+ .cache.$(signature) += $(target) ;
997
+ result = $(target) ;
998
+ }
999
+
1000
+ .recent-targets += $(result) ;
1001
+ .all-targets += $(result) ;
1002
+
1003
+ return $(result) ;
1004
+ }
1005
+
1006
+
1007
+ # Each target returned by 'register' is added to the .recent-targets list,
1008
+ # returned by this function. This allows us to find all virtual targets created
1009
+ # when building a specific main target, even those constructed only as
1010
+ # intermediate targets.
1011
+ #
1012
+ rule recent-targets ( )
1013
+ {
1014
+ return $(.recent-targets) ;
1015
+ }
1016
+
1017
+
1018
+ rule clear-recent-targets ( )
1019
+ {
1020
+ .recent-targets = ;
1021
+ }
1022
+
1023
+
1024
+ # Returns all virtual targets ever created.
1025
+ #
1026
+ rule all-targets ( )
1027
+ {
1028
+ return $(.all-targets) ;
1029
+ }
1030
+
1031
+
1032
+ # Returns all targets from 'targets' with types equal to 'type' or derived from
1033
+ # it.
1034
+ #
1035
+ rule select-by-type ( type : targets * )
1036
+ {
1037
+ local result ;
1038
+ for local t in $(targets)
1039
+ {
1040
+ if [ type.is-subtype [ $(t).type ] $(type) ]
1041
+ {
1042
+ result += $(t) ;
1043
+ }
1044
+ }
1045
+ return $(result) ;
1046
+ }
1047
+
1048
+
1049
+ rule register-actual-name ( actual-name : virtual-target )
1050
+ {
1051
+ if $(.actual.$(actual-name))
1052
+ {
1053
+ local cs1 = [ $(.actual.$(actual-name)).creating-subvariant ] ;
1054
+ local cs2 = [ $(virtual-target).creating-subvariant ] ;
1055
+ local cmt1 = [ $(cs1).main-target ] ;
1056
+ local cmt2 = [ $(cs2).main-target ] ;
1057
+
1058
+ local action1 = [ $(.actual.$(actual-name)).action ] ;
1059
+ local action2 = [ $(virtual-target).action ] ;
1060
+ local properties-added ;
1061
+ local properties-removed ;
1062
+ if $(action1) && $(action2)
1063
+ {
1064
+ local p1 = [ $(action1).properties ] ;
1065
+ p1 = [ $(p1).raw ] ;
1066
+ local p2 = [ $(action2).properties ] ;
1067
+ p2 = [ $(p2).raw ] ;
1068
+ properties-removed = [ set.difference $(p1) : $(p2) ] ;
1069
+ properties-removed ?= "none" ;
1070
+ properties-added = [ set.difference $(p2) : $(p1) ] ;
1071
+ properties-added ?= "none" ;
1072
+ }
1073
+ errors.error "Duplicate name of actual target:" $(actual-name)
1074
+ : "previous virtual target" [ $(.actual.$(actual-name)).str ]
1075
+ : "created from" [ $(cmt1).full-name ]
1076
+ : "another virtual target" [ $(virtual-target).str ]
1077
+ : "created from" [ $(cmt2).full-name ]
1078
+ : "added properties:" $(properties-added)
1079
+ : "removed properties:" $(properties-removed) ;
1080
+ }
1081
+ else
1082
+ {
1083
+ .actual.$(actual-name) = $(virtual-target) ;
1084
+ }
1085
+ }
1086
+
1087
+
1088
+ # Traverses the dependency graph of 'target' and return all targets that will be
1089
+ # created before this one is created. If the root of some dependency graph is
1090
+ # found during traversal, it is either included or not, depending on the
1091
+ # 'include-roots' value. In either case traversal stops at root targets, i.e.
1092
+ # root target sources are not traversed.
1093
+ #
1094
+ rule traverse ( target : include-roots ? : include-sources ? )
1095
+ {
1096
+ local result ;
1097
+ if [ $(target).action ]
1098
+ {
1099
+ local action = [ $(target).action ] ;
1100
+ # This includes the 'target' as well.
1101
+ result += [ $(action).targets ] ;
1102
+
1103
+ for local t in [ $(action).sources ]
1104
+ {
1105
+ if ! [ $(t).root ]
1106
+ {
1107
+ result += [ traverse $(t) : $(include-roots) : $(include-sources) ] ;
1108
+ }
1109
+ else if $(include-roots)
1110
+ {
1111
+ result += $(t) ;
1112
+ }
1113
+ }
1114
+ }
1115
+ else if $(include-sources)
1116
+ {
1117
+ result = $(target) ;
1118
+ }
1119
+ return $(result) ;
1120
+ }
1121
+
1122
+
1123
+ # Takes an 'action' instance and creates a new instance of it and all targets
1124
+ # produced by the action. The rule-name and properties are set to
1125
+ # 'new-rule-name' and 'new-properties', if those are specified. Returns the
1126
+ # cloned action.
1127
+ #
1128
+ rule clone-action ( action : new-project : new-action-name ? : new-properties ? )
1129
+ {
1130
+ if ! $(new-action-name)
1131
+ {
1132
+ new-action-name = [ $(action).action-name ] ;
1133
+ }
1134
+ if ! $(new-properties)
1135
+ {
1136
+ new-properties = [ $(action).properties ] ;
1137
+ }
1138
+
1139
+ local action-class = [ modules.peek $(action) : __class__ ] ;
1140
+ local cloned-action = [ class.new $(action-class)
1141
+ [ $(action).sources ] : $(new-action-name) : $(new-properties) ] ;
1142
+
1143
+ local cloned-targets ;
1144
+ for local target in [ $(action).targets ]
1145
+ {
1146
+ local n = [ $(target).name ] ;
1147
+ # Do not modify produced target names.
1148
+ local cloned-target = [ class.new file-target $(n) exact :
1149
+ [ $(target).type ] : $(new-project) : $(cloned-action) ] ;
1150
+ local d = [ $(target).dependencies ] ;
1151
+ if $(d)
1152
+ {
1153
+ $(cloned-target).depends $(d) ;
1154
+ }
1155
+ $(cloned-target).root [ $(target).root ] ;
1156
+ $(cloned-target).creating-subvariant [ $(target).creating-subvariant ] ;
1157
+
1158
+ cloned-targets += $(cloned-target) ;
1159
+ }
1160
+
1161
+ return $(cloned-action) ;
1162
+ }
1163
+
1164
+
1165
+ class subvariant
1166
+ {
1167
+ import sequence ;
1168
+ import type ;
1169
+
1170
+ rule __init__ ( main-target # The instance of main-target class.
1171
+ : property-set # Properties requested for this target.
1172
+ : sources *
1173
+ : build-properties # Actually used properties.
1174
+ : sources-usage-requirements # Properties propagated from sources.
1175
+ : created-targets * ) # Top-level created targets.
1176
+ {
1177
+ self.main-target = $(main-target) ;
1178
+ self.properties = $(property-set) ;
1179
+ self.sources = $(sources) ;
1180
+ self.build-properties = $(build-properties) ;
1181
+ self.sources-usage-requirements = $(sources-usage-requirements) ;
1182
+ self.created-targets = $(created-targets) ;
1183
+
1184
+ # Pre-compose a list of other dependency graphs this one depends on.
1185
+ local deps = [ $(build-properties).get <implicit-dependency> ] ;
1186
+ for local d in $(deps)
1187
+ {
1188
+ self.other-dg += [ $(d:G=).creating-subvariant ] ;
1189
+ }
1190
+
1191
+ self.other-dg = [ sequence.unique $(self.other-dg) ] ;
1192
+ }
1193
+
1194
+ rule main-target ( )
1195
+ {
1196
+ return $(self.main-target) ;
1197
+ }
1198
+
1199
+ rule created-targets ( )
1200
+ {
1201
+ return $(self.created-targets) ;
1202
+ }
1203
+
1204
+ rule requested-properties ( )
1205
+ {
1206
+ return $(self.properties) ;
1207
+ }
1208
+
1209
+ rule build-properties ( )
1210
+ {
1211
+ return $(self.build-properties) ;
1212
+ }
1213
+
1214
+ rule sources-usage-requirements ( )
1215
+ {
1216
+ return $(self.sources-usage-requirements) ;
1217
+ }
1218
+
1219
+ rule set-usage-requirements ( usage-requirements )
1220
+ {
1221
+ self.usage-requirements = $(usage-requirements) ;
1222
+ }
1223
+
1224
+ rule usage-requirements ( )
1225
+ {
1226
+ return $(self.usage-requirements) ;
1227
+ }
1228
+
1229
+ # Returns all targets referenced by this subvariant, either directly or
1230
+ # indirectly, and either as sources, or as dependency properties. Targets
1231
+ # referred to using the dependency property are returned as properties, not
1232
+ # targets.
1233
+ #
1234
+ rule all-referenced-targets ( theset )
1235
+ {
1236
+ # Find directly referenced targets.
1237
+ local deps = [ $(self.build-properties).dependency ] ;
1238
+ local all-targets = $(self.sources) $(deps) ;
1239
+
1240
+ # Find other subvariants.
1241
+ local r ;
1242
+ for local t in $(all-targets)
1243
+ {
1244
+ if ! [ $(theset).contains $(t) ]
1245
+ {
1246
+ $(theset).add $(t) ;
1247
+ r += [ $(t:G=).creating-subvariant ] ;
1248
+ }
1249
+ }
1250
+ r = [ sequence.unique $(r) ] ;
1251
+ for local s in $(r)
1252
+ {
1253
+ if $(s) != $(__name__)
1254
+ {
1255
+ $(s).all-referenced-targets $(theset) ;
1256
+ }
1257
+ }
1258
+ }
1259
+
1260
+ # Returns the properties specifying implicit include paths to generated
1261
+ # headers. This traverses all targets in this subvariant and subvariants
1262
+ # referred by <implcit-dependecy> properties. For all targets of type
1263
+ # 'target-type' (or for all targets, if 'target-type' is not specified), the
1264
+ # result will contain <$(feature)>path-to-that-target.
1265
+ #
1266
+ rule implicit-includes ( feature : target-type ? )
1267
+ {
1268
+ local key = ii$(feature)-$(target-type:E="") ;
1269
+ if ! $($(key))-is-not-empty
1270
+ {
1271
+ local target-paths = [ all-target-directories $(target-type) ] ;
1272
+ target-paths = [ sequence.unique $(target-paths) ] ;
1273
+ local result = $(target-paths:G=$(feature)) ;
1274
+ if ! $(result)
1275
+ {
1276
+ result = "" ;
1277
+ }
1278
+ $(key) = $(result) ;
1279
+ }
1280
+ if $($(key)) = ""
1281
+ {
1282
+ return ;
1283
+ }
1284
+ else
1285
+ {
1286
+ return $($(key)) ;
1287
+ }
1288
+ }
1289
+
1290
+ rule all-target-directories ( target-type ? )
1291
+ {
1292
+ if ! $(self.target-directories)
1293
+ {
1294
+ compute-target-directories $(target-type) ;
1295
+ }
1296
+ return $(self.target-directories) ;
1297
+ }
1298
+
1299
+ rule compute-target-directories ( target-type ? )
1300
+ {
1301
+ local result ;
1302
+ for local t in $(self.created-targets)
1303
+ {
1304
+ # Skip targets of the wrong type.
1305
+ if ! $(target-type) ||
1306
+ [ type.is-derived [ $(t).type ] $(target-type) ]
1307
+ {
1308
+ result = [ sequence.merge $(result) : [ $(t).path ] ] ;
1309
+ }
1310
+ }
1311
+ for local d in $(self.other-dg)
1312
+ {
1313
+ result += [ $(d).all-target-directories $(target-type) ] ;
1314
+ }
1315
+ self.target-directories = $(result) ;
1316
+ }
1317
+ }
mosesdecoder/jam-files/boost-build/util/assert.jam ADDED
@@ -0,0 +1,336 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2001, 2002, 2003 Dave Abrahams
2
+ # Copyright 2006 Rene Rivera
3
+ # Copyright 2002, 2003 Vladimir Prus
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ import errors ;
8
+ import modules ;
9
+
10
+
11
+ ################################################################################
12
+ #
13
+ # Private implementation details.
14
+ #
15
+ ################################################################################
16
+
17
+ # Rule added as a replacement for the regular Jam = operator but which does not
18
+ # ignore trailing empty string elements.
19
+ #
20
+ local rule exact-equal-test ( lhs * : rhs * )
21
+ {
22
+ local lhs_extended = $(lhs) xxx ;
23
+ local rhs_extended = $(rhs) xxx ;
24
+ if $(lhs_extended) = $(rhs_extended)
25
+ {
26
+ return true ;
27
+ }
28
+ }
29
+
30
+
31
+ # Two lists are considered set-equal if they contain the same elements, ignoring
32
+ # duplicates and ordering.
33
+ #
34
+ local rule set-equal-test ( set1 * : set2 * )
35
+ {
36
+ if ( $(set1) in $(set2) ) && ( $(set2) in $(set1) )
37
+ {
38
+ return true ;
39
+ }
40
+ }
41
+
42
+
43
+ ################################################################################
44
+ #
45
+ # Public interface.
46
+ #
47
+ ################################################################################
48
+
49
+ # Assert the equality of A and B, ignoring trailing empty string elements.
50
+ #
51
+ rule equal ( a * : b * )
52
+ {
53
+ if $(a) != $(b)
54
+ {
55
+ errors.error-skip-frames 3 assertion failure: \"$(a)\" "==" \"$(b)\"
56
+ (ignoring trailing empty strings) ;
57
+ }
58
+ }
59
+
60
+
61
+ # Assert that the result of calling RULE-NAME on the given arguments has a false
62
+ # logical value (is either an empty list or all empty strings).
63
+ #
64
+ rule false ( rule-name args * : * )
65
+ {
66
+ local result ;
67
+ module [ CALLER_MODULE ]
68
+ {
69
+ modules.poke assert : result : [ $(1) : $(2) : $(3) : $(4) : $(5) : $(6)
70
+ : $(7) : $(8) : $(9) ] ;
71
+ }
72
+
73
+ if $(result)
74
+ {
75
+ errors.error-skip-frames 3 assertion failure: Expected false result from
76
+ "[" $(rule-name) [ errors.lol->list $(args) : $(2) : $(3) : $(4) :
77
+ $(5) : $(6) : $(7) : $(8) : $(9) ] "]" : Got: "[" \"$(result)\" "]" ;
78
+ }
79
+ }
80
+
81
+
82
+ # Assert that ELEMENT is present in LIST.
83
+ #
84
+ rule "in" ( element : list * )
85
+ {
86
+ if ! $(element) in $(list)
87
+ {
88
+ errors.error-skip-frames 3 assertion failure: Expected \"$(element)\" in
89
+ "[" \"$(list)\" "]" ;
90
+ }
91
+ }
92
+
93
+
94
+ # Assert the inequality of A and B, ignoring trailing empty string elements.
95
+ #
96
+ rule not-equal ( a * : b * )
97
+ {
98
+ if $(a) = $(b)
99
+ {
100
+ errors.error-skip-frames 3 assertion failure: \"$(a)\" "!=" \"$(b)\"
101
+ (ignoring trailing empty strings) ;
102
+ }
103
+ }
104
+
105
+
106
+ # Assert that ELEMENT is not present in LIST.
107
+ #
108
+ rule not-in ( element : list * )
109
+ {
110
+ if $(element) in $(list)
111
+ {
112
+ errors.error-skip-frames 3 assertion failure: Did not expect
113
+ \"$(element)\" in "[" \"$(list)\" "]" ;
114
+ }
115
+ }
116
+
117
+
118
+ # Assert the inequality of A and B as sets.
119
+ #
120
+ rule not-set-equal ( a * : b * )
121
+ {
122
+ if [ set-equal-test $(a) : $(b) ]
123
+ {
124
+ errors.error-skip-frames 3 assertion failure: Expected "[" \"$(a)\" "]"
125
+ and "[" \"$(b)\" "]" to not be equal as sets ;
126
+ }
127
+ }
128
+
129
+
130
+ # Assert that A and B are not exactly equal, not ignoring trailing empty string
131
+ # elements.
132
+ #
133
+ rule not-exact-equal ( a * : b * )
134
+ {
135
+ if [ exact-equal-test $(a) : $(b) ]
136
+ {
137
+ errors.error-skip-frames 3 assertion failure: \"$(a)\" "!=" \"$(b)\" ;
138
+ }
139
+ }
140
+
141
+
142
+ # Assert that EXPECTED is the result of calling RULE-NAME with the given
143
+ # arguments.
144
+ #
145
+ rule result ( expected * : rule-name args * : * )
146
+ {
147
+ local result ;
148
+ module [ CALLER_MODULE ]
149
+ {
150
+ modules.poke assert : result : [ $(2) : $(3) : $(4) : $(5) : $(6) : $(7)
151
+ : $(8) : $(9) ] ;
152
+ }
153
+
154
+ if ! [ exact-equal-test $(result) : $(expected) ]
155
+ {
156
+ errors.error-skip-frames 3 assertion failure: "[" $(rule-name) [
157
+ errors.lol->list $(args) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) :
158
+ $(9) ] "]" : Expected: "[" \"$(expected)\" "]" : Got: "["
159
+ \"$(result)\" "]" ;
160
+ }
161
+ }
162
+
163
+
164
+ # Assert that EXPECTED is set-equal (i.e. duplicates and ordering are ignored)
165
+ # to the result of calling RULE-NAME with the given arguments. Note that rules
166
+ # called this way may accept at most 8 parameters.
167
+ #
168
+ rule result-set-equal ( expected * : rule-name args * : * )
169
+ {
170
+ local result ;
171
+ module [ CALLER_MODULE ]
172
+ {
173
+ modules.poke assert : result : [ $(2) : $(3) : $(4) : $(5) : $(6) : $(7)
174
+ : $(8) : $(9) ] ;
175
+ }
176
+
177
+ if ! [ set-equal-test $(result) : $(expected) ]
178
+ {
179
+ errors.error-skip-frames 3 assertion failure: "[" $(rule-name) [
180
+ errors.lol->list $(args) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) :
181
+ $(9) ] "]" : Expected: "[" \"$(expected)\" "]" : Got: "["
182
+ \"$(result)\" "]" ;
183
+ }
184
+ }
185
+
186
+
187
+ # Assert the equality of A and B as sets.
188
+ #
189
+ rule set-equal ( a * : b * )
190
+ {
191
+ if ! [ set-equal-test $(a) : $(b) ]
192
+ {
193
+ errors.error-skip-frames 3 assertion failure: Expected "[" \"$(a)\" "]"
194
+ and "[" \"$(b)\" "]" to be equal as sets ;
195
+ }
196
+ }
197
+
198
+
199
+ # Assert that the result of calling RULE-NAME on the given arguments has a true
200
+ # logical value (is neither an empty list nor all empty strings).
201
+ #
202
+ rule true ( rule-name args * : * )
203
+ {
204
+ local result ;
205
+ module [ CALLER_MODULE ]
206
+ {
207
+ modules.poke assert : result : [ $(1) : $(2) : $(3) : $(4) : $(5) : $(6)
208
+ : $(7) : $(8) : $(9) ] ;
209
+ }
210
+
211
+ if ! $(result)
212
+ {
213
+ errors.error-skip-frames 3 assertion failure: Expected true result from
214
+ "[" $(rule-name) [ errors.lol->list $(args) : $(2) : $(3) : $(4) :
215
+ $(5) : $(6) : $(7) : $(8) : $(9) ] "]" ;
216
+ }
217
+ }
218
+
219
+
220
+ # Assert the exact equality of A and B, not ignoring trailing empty string
221
+ # elements.
222
+ #
223
+ rule exact-equal ( a * : b * )
224
+ {
225
+ if ! [ exact-equal-test $(a) : $(b) ]
226
+ {
227
+ errors.error-skip-frames 3 assertion failure: \"$(a)\" "==" \"$(b)\" ;
228
+ }
229
+ }
230
+
231
+
232
+ # Assert that the given variable is not an empty list.
233
+ #
234
+ rule variable-not-empty ( name )
235
+ {
236
+ local value = [ modules.peek [ CALLER_MODULE ] : $(name) ] ;
237
+ if ! $(value)-is-not-empty
238
+ {
239
+ errors.error-skip-frames 3 assertion failure: Expected variable
240
+ \"$(name)\" not to be an empty list ;
241
+ }
242
+ }
243
+
244
+
245
+ rule __test__ ( )
246
+ {
247
+ # Helper rule used to avoid test duplication related to different list
248
+ # equality test rules.
249
+ #
250
+ local rule run-equality-test ( equality-assert : ignore-trailing-empty-strings ? )
251
+ {
252
+ local not-equality-assert = not-$(equality-assert) ;
253
+
254
+ # When the given equality test is expected to ignore trailing empty
255
+ # strings some of the test results should be inverted.
256
+ local not-equality-assert-i = not-$(equality-assert) ;
257
+ if $(ignore-trailing-empty-strings)
258
+ {
259
+ not-equality-assert-i = $(equality-assert) ;
260
+ }
261
+
262
+ $(equality-assert) : ;
263
+ $(equality-assert) "" "" : "" "" ;
264
+ $(not-equality-assert-i) : "" "" ;
265
+ $(equality-assert) x : x ;
266
+ $(not-equality-assert) : x ;
267
+ $(not-equality-assert) "" : x ;
268
+ $(not-equality-assert) "" "" : x ;
269
+ $(not-equality-assert-i) x : x "" ;
270
+ $(equality-assert) x "" : x "" ;
271
+ $(not-equality-assert) x : "" x ;
272
+ $(equality-assert) "" x : "" x ;
273
+
274
+ $(equality-assert) 1 2 3 : 1 2 3 ;
275
+ $(not-equality-assert) 1 2 3 : 3 2 1 ;
276
+ $(not-equality-assert) 1 2 3 : 1 5 3 ;
277
+ $(not-equality-assert) 1 2 3 : 1 "" 3 ;
278
+ $(not-equality-assert) 1 2 3 : 1 1 2 3 ;
279
+ $(not-equality-assert) 1 2 3 : 1 2 2 3 ;
280
+ $(not-equality-assert) 1 2 3 : 5 6 7 ;
281
+
282
+ # Extra variables used here just to make sure Boost Jam or Boost Build
283
+ # do not handle lists with empty strings differently depending on
284
+ # whether they are literals or stored in variables.
285
+
286
+ local empty = ;
287
+ local empty-strings = "" "" ;
288
+ local x-empty-strings = x "" "" ;
289
+ local empty-strings-x = "" "" x ;
290
+
291
+ $(equality-assert) : $(empty) ;
292
+ $(not-equality-assert-i) "" : $(empty) ;
293
+ $(not-equality-assert-i) "" "" : $(empty) ;
294
+ $(not-equality-assert-i) : $(empty-strings) ;
295
+ $(not-equality-assert-i) "" : $(empty-strings) ;
296
+ $(equality-assert) "" "" : $(empty-strings) ;
297
+ $(equality-assert) $(empty) : $(empty) ;
298
+ $(equality-assert) $(empty-strings) : $(empty-strings) ;
299
+ $(not-equality-assert-i) $(empty) : $(empty-strings) ;
300
+ $(equality-assert) $(x-empty-strings) : $(x-empty-strings) ;
301
+ $(equality-assert) $(empty-strings-x) : $(empty-strings-x) ;
302
+ $(not-equality-assert) $(empty-strings-x) : $(x-empty-strings) ;
303
+ $(not-equality-assert-i) x : $(x-empty-strings) ;
304
+ $(not-equality-assert) x : $(empty-strings-x) ;
305
+ $(not-equality-assert-i) x : $(x-empty-strings) ;
306
+ $(not-equality-assert-i) x "" : $(x-empty-strings) ;
307
+ $(equality-assert) x "" "" : $(x-empty-strings) ;
308
+ $(not-equality-assert) x : $(empty-strings-x) ;
309
+ $(not-equality-assert) "" x : $(empty-strings-x) ;
310
+ $(equality-assert) "" "" x : $(empty-strings-x) ;
311
+ }
312
+
313
+
314
+ # ---------------
315
+ # Equality tests.
316
+ # ---------------
317
+
318
+ run-equality-test equal : ignore-trailing-empty-strings ;
319
+ run-equality-test exact-equal ;
320
+
321
+
322
+ # -------------------------
323
+ # assert.set-equal() tests.
324
+ # -------------------------
325
+
326
+ set-equal : ;
327
+ not-set-equal "" "" : ;
328
+ set-equal "" "" : "" ;
329
+ set-equal "" "" : "" "" ;
330
+ set-equal a b c : a b c ;
331
+ set-equal a b c : b c a ;
332
+ set-equal a b c a : a b c ;
333
+ set-equal a b c : a b c a ;
334
+ not-set-equal a b c : a b c d ;
335
+ not-set-equal a b c d : a b c ;
336
+ }
mosesdecoder/jam-files/boost-build/util/doc.jam ADDED
@@ -0,0 +1,997 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2002, 2005 Dave Abrahams
2
+ # Copyright 2002, 2003, 2006 Rene Rivera
3
+ # Copyright 2003 Vladimir Prus
4
+ # Distributed under the Boost Software License, Version 1.0.
5
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ # Documentation system, handles --help requests.
8
+ # It defines rules that attach documentation to modules, rules, and variables.
9
+ # Collects and generates documentation for the various parts of the build
10
+ # system. The documentation is collected from comments integrated into the code.
11
+
12
+ import modules ;
13
+ import print ;
14
+ import set ;
15
+ import container ;
16
+ import "class" ;
17
+ import sequence ;
18
+ import path ;
19
+
20
+
21
+ # The type of output to generate.
22
+ # "console" is formated text echoed to the console (the default);
23
+ # "text" is formated text appended to the output file;
24
+ # "html" is HTML output to the file.
25
+ #
26
+ help-output = console ;
27
+
28
+
29
+ # The file to output documentation to when generating "text" or "html" help.
30
+ # This is without extension as the extension is determined by the type of
31
+ # output.
32
+ #
33
+ help-output-file = help ;
34
+
35
+ # Whether to include local rules in help output.
36
+ #
37
+ .option.show-locals ?= ;
38
+
39
+ # When showing documentation for a module, whether to also generate
40
+ # automatically the detailed docs for each item in the module.
41
+ #
42
+ .option.detailed ?= ;
43
+
44
+ # Generate debug output as the help is generated and modules are parsed.
45
+ #
46
+ .option.debug ?= ;
47
+
48
+ # Enable or disable a documentation option.
49
+ #
50
+ local rule set-option (
51
+ option # The option name.
52
+ : value ? # Enabled (non-empty), or disabled (empty)
53
+ )
54
+ {
55
+ .option.$(option) = $(value) ;
56
+ }
57
+
58
+
59
+ # Set the type of output.
60
+ #
61
+ local rule set-output ( type )
62
+ {
63
+ help-output = $(type) ;
64
+ }
65
+
66
+
67
+ # Set the output to a file.
68
+ #
69
+ local rule set-output-file ( file )
70
+ {
71
+ help-output-file = $(file) ;
72
+ }
73
+
74
+
75
+ # Extracts the brief comment from a complete comment. The brief comment is the
76
+ # first sentence.
77
+ #
78
+ local rule brief-comment (
79
+ docs * # The comment documentation.
80
+ )
81
+ {
82
+ local d = $(docs:J=" ") ;
83
+ local p = [ MATCH ".*([.])$" : $(d) ] ;
84
+ if ! $(p) { d = $(d)"." ; }
85
+ d = $(d)" " ;
86
+ local m = [ MATCH "^([^.]+[.])(.*)" : $(d) ] ;
87
+ local brief = $(m[1]) ;
88
+ while $(m[2]) && [ MATCH "^([^ ])" : $(m[2]) ]
89
+ {
90
+ m = [ MATCH "^([^.]+[.])(.*)" : $(m[2]) ] ;
91
+ brief += $(m[1]) ;
92
+ }
93
+ return $(brief:J="") ;
94
+ }
95
+
96
+
97
+ # Specifies the documentation for the current module.
98
+ #
99
+ local rule set-module-doc (
100
+ module-name ? # The name of the module to document.
101
+ : docs * # The documentation for the module.
102
+ )
103
+ {
104
+ module-name ?= * ;
105
+
106
+ $(module-name).brief = [ brief-comment $(docs) ] ;
107
+ $(module-name).docs = $(docs) ;
108
+
109
+ if ! $(module-name) in $(documented-modules)
110
+ {
111
+ documented-modules += $(module-name) ;
112
+ }
113
+ }
114
+
115
+
116
+ # Specifies the documentation for the current module.
117
+ #
118
+ local rule set-module-copyright (
119
+ module-name ? # The name of the module to document.
120
+ : copyright * # The copyright for the module.
121
+ )
122
+ {
123
+ module-name ?= * ;
124
+
125
+ $(module-name).copy-brief = [ brief-comment $(copyright) ] ;
126
+ $(module-name).copy-docs = $(docs) ;
127
+
128
+ if ! $(module-name) in $(documented-modules)
129
+ {
130
+ documented-modules += $(module-name) ;
131
+ }
132
+ }
133
+
134
+
135
+ # Specifies the documentation for a rule in the current module. If called in the
136
+ # global module, this documents a global rule.
137
+ #
138
+ local rule set-rule-doc (
139
+ name # The name of the rule.
140
+ module-name ? # The name of the module to document.
141
+ is-local ? # Whether the rule is local to the module.
142
+ : docs * # The documentation for the rule.
143
+ )
144
+ {
145
+ module-name ?= * ;
146
+
147
+ $(module-name).$(name).brief = [ brief-comment $(docs) ] ;
148
+ $(module-name).$(name).docs = $(docs) ;
149
+ $(module-name).$(name).is-local = $(is-local) ;
150
+
151
+ if ! $(name) in $($(module-name).rules)
152
+ {
153
+ $(module-name).rules += $(name) ;
154
+ }
155
+ }
156
+
157
+
158
+ # Specify a class, will turn a rule into a class.
159
+ #
160
+ local rule set-class-doc (
161
+ name # The name of the class.
162
+ module-name ? # The name of the module to document.
163
+ : super-name ? # The super class name.
164
+ )
165
+ {
166
+ module-name ?= * ;
167
+
168
+ $(module-name).$(name).is-class = true ;
169
+ $(module-name).$(name).super-name = $(super-name) ;
170
+ $(module-name).$(name).class-rules =
171
+ [ MATCH "^($(name)[.].*)" : $($(module-name).rules) ] ;
172
+ $(module-name).$($(module-name).$(name).class-rules).is-class-rule = true ;
173
+
174
+ $(module-name).classes += $(name) ;
175
+ $(module-name).class-rules += $($(module-name).$(name).class-rules) ;
176
+ $(module-name).rules =
177
+ [ set.difference $($(module-name).rules) :
178
+ $(name) $($(module-name).$(name).class-rules) ] ;
179
+ }
180
+
181
+
182
+ # Set the argument call signature of a rule.
183
+ #
184
+ local rule set-rule-arguments-signature (
185
+ name # The name of the rule.
186
+ module-name ? # The name of the module to document.
187
+ : signature * # The arguments signature.
188
+ )
189
+ {
190
+ module-name ?= * ;
191
+
192
+ $(module-name).$(name).signature = $(signature) ;
193
+ }
194
+
195
+
196
+ # Specifies the documentation for an argument of a rule.
197
+ #
198
+ local rule set-argument-doc (
199
+ name # The name of the argument.
200
+ qualifier # Argument syntax qualifier, "*", "+", etc.
201
+ rule-name # The name of the rule.
202
+ module-name ? # THe optional name of the module.
203
+ : docs * # The documentation.
204
+ )
205
+ {
206
+ module-name ?= * ;
207
+
208
+ $(module-name).$(rule-name).args.$(name).qualifier = $(qualifier) ;
209
+ $(module-name).$(rule-name).args.$(name).docs = $(docs) ;
210
+
211
+ if ! $(name) in $($(module-name).$(rule-name).args)
212
+ {
213
+ $(module-name).$(rule-name).args += $(name) ;
214
+ }
215
+ }
216
+
217
+
218
+ # Specifies the documentation for a variable in the current module. If called in
219
+ # the global module, the global variable is documented.
220
+ #
221
+ local rule set-variable-doc (
222
+ name # The name of the variable.
223
+ default # The default value.
224
+ initial # The initial value.
225
+ module-name ? # The name of the module to document.
226
+ : docs * # The documentation for the variable.
227
+ )
228
+ {
229
+ module-name ?= * ;
230
+
231
+ $(module-name).$(name).brief = [ brief-comment $(docs) ] ;
232
+ $(module-name).$(name).default = $(default) ;
233
+ $(module-name).$(name).initial = $(initial) ;
234
+ $(module-name).$(name).docs = $(docs) ;
235
+
236
+ if ! $(name) in $($(module-name).variables)
237
+ {
238
+ $(module-name).variables += $(name) ;
239
+ }
240
+ }
241
+
242
+
243
+ # Generates a general description of the documentation and help system.
244
+ #
245
+ local rule print-help-top ( )
246
+ {
247
+ print.section "General command line usage" ;
248
+
249
+ print.text " bjam [options] [properties] [targets]
250
+
251
+ Options, properties and targets can be specified in any order.
252
+ " ;
253
+
254
+ print.section "Important Options" ;
255
+
256
+ print.list-start ;
257
+ print.list-item "--clean Remove targets instead of building" ;
258
+ print.list-item "-a Rebuild everything" ;
259
+ print.list-item "-n Don't execute the commands, only print them" ;
260
+ print.list-item "-d+2 Show commands as they are executed" ;
261
+ print.list-item "-d0 Supress all informational messages" ;
262
+ print.list-item "-q Stop at first error" ;
263
+ print.list-item "--debug-configuration Diagnose configuration" ;
264
+ print.list-item "--debug-building Report which targets are built with what properties" ;
265
+ print.list-item "--debug-generator Diagnose generator search/execution" ;
266
+ print.list-end ;
267
+
268
+ print.section "Further Help"
269
+ The following options can be used to obtain additional documentation.
270
+ ;
271
+
272
+ print.list-start ;
273
+ print.list-item "--help-options Print more obscure command line options." ;
274
+ print.list-item "--help-internal Boost.Build implementation details." ;
275
+ print.list-item "--help-doc-options Implementation details doc formatting." ;
276
+ print.list-end ;
277
+ }
278
+
279
+
280
+ # Generate Jam/Boost.Jam command usage information.
281
+ #
282
+ local rule print-help-usage ( )
283
+ {
284
+ print.section "Boost.Jam Usage"
285
+ "bjam [ options... ] targets..."
286
+ ;
287
+ print.list-start ;
288
+ print.list-item -a;
289
+ Build all targets, even if they are current. ;
290
+ print.list-item -fx;
291
+ Read '"x"' as the Jamfile for building instead of searching for the
292
+ Boost.Build system. ;
293
+ print.list-item -jx;
294
+ Run up to '"x"' commands concurrently. ;
295
+ print.list-item -n;
296
+ Do not execute build commands. Instead print out the commands as they
297
+ would be executed if building. ;
298
+ print.list-item -ox;
299
+ Output the used build commands to file '"x"'. ;
300
+ print.list-item -q;
301
+ Quit as soon as a build failure is encountered. Without this option
302
+ Boost.Jam will continue building as many targets as it can.
303
+ print.list-item -sx=y;
304
+ Sets a Jam variable '"x"' to the value '"y"', overriding any value that
305
+ variable would have from the environment. ;
306
+ print.list-item -tx;
307
+ Rebuild the target '"x"', even if it is up-to-date. ;
308
+ print.list-item -v;
309
+ Display the version of bjam. ;
310
+ print.list-item --x;
311
+ Any option not explicitly handled by Boost.Jam remains available to
312
+ build scripts using the '"ARGV"' variable. ;
313
+ print.list-item -dn;
314
+ Enables output of diagnostic messages. The debug level '"n"' and all
315
+ below it are enabled by this option. ;
316
+ print.list-item -d+n;
317
+ Enables output of diagnostic messages. Only the output for debug level
318
+ '"n"' is enabled. ;
319
+ print.list-end ;
320
+ print.section "Debug Levels"
321
+ Each debug level shows a different set of information. Usually with
322
+ higher levels producing more verbose information. The following levels
323
+ are supported: ;
324
+ print.list-start ;
325
+ print.list-item 0;
326
+ Turn off all diagnostic output. Only errors are reported. ;
327
+ print.list-item 1;
328
+ Show the actions taken for building targets, as they are executed. ;
329
+ print.list-item 2;
330
+ Show "quiet" actions and display all action text, as they are executed. ;
331
+ print.list-item 3;
332
+ Show dependency analysis, and target/source timestamps/paths. ;
333
+ print.list-item 4;
334
+ Show arguments of shell invocations. ;
335
+ print.list-item 5;
336
+ Show rule invocations and variable expansions. ;
337
+ print.list-item 6;
338
+ Show directory/header file/archive scans, and attempts at binding to targets. ;
339
+ print.list-item 7;
340
+ Show variable settings. ;
341
+ print.list-item 8;
342
+ Show variable fetches, variable expansions, and evaluation of '"if"' expressions. ;
343
+ print.list-item 9;
344
+ Show variable manipulation, scanner tokens, and memory usage. ;
345
+ print.list-item 10;
346
+ Show execution times for rules. ;
347
+ print.list-item 11;
348
+ Show parsing progress of Jamfiles. ;
349
+ print.list-item 12;
350
+ Show graph for target dependencies. ;
351
+ print.list-item 13;
352
+ Show changes in target status (fate). ;
353
+ print.list-end ;
354
+ }
355
+
356
+
357
+ # Generates description of options controlling the help system. This
358
+ # automatically reads the options as all variables in the doc module of the form
359
+ # ".option.*".
360
+ #
361
+ local rule print-help-options (
362
+ module-name # The doc module.
363
+ )
364
+ {
365
+ print.section "Help Options"
366
+ These are all the options available for enabling or disabling to control
367
+ the help system in various ways. Options can be enabled or disabled with
368
+ '"--help-enable-<option>"', and "'--help-disable-<option>'"
369
+ respectively.
370
+ ;
371
+ local options-to-list = [ MATCH ^[.]option[.](.*) : $($(module-name).variables) ] ;
372
+ if $(options-to-list)
373
+ {
374
+ print.list-start ;
375
+ for local option in [ sequence.insertion-sort $(options-to-list) ]
376
+ {
377
+ local def = disabled ;
378
+ if $($(module-name)..option.$(option).default) != "(empty)"
379
+ {
380
+ def = enabled ;
381
+ }
382
+ print.list-item $(option): $($(module-name)..option.$(option).docs)
383
+ Default is $(def). ;
384
+ }
385
+ print.list-end ;
386
+ }
387
+ }
388
+
389
+
390
+ # Generate brief documentation for all the known items in the section for a
391
+ # module. Possible sections are: "rules", and "variables".
392
+ #
393
+ local rule print-help-module-section (
394
+ module # The module name.
395
+ section # rules or variables.
396
+ : section-head # The title of the section.
397
+ section-description * # The detailed description of the section.
398
+ )
399
+ {
400
+ if $($(module).$(section))
401
+ {
402
+ print.section $(section-head) $(section-description) ;
403
+ print.list-start ;
404
+ for local item in [ sequence.insertion-sort $($(module).$(section)) ]
405
+ {
406
+ local show = ;
407
+ if ! $($(module).$(item).is-local)
408
+ {
409
+ show = yes ;
410
+ }
411
+ if $(.option.show-locals)
412
+ {
413
+ show = yes ;
414
+ }
415
+ if $(show)
416
+ {
417
+ print.list-item $(item): $($(module).$(item).brief) ;
418
+ }
419
+ }
420
+ print.list-end ;
421
+ }
422
+ }
423
+
424
+
425
+ # Generate documentation for all possible modules. We attempt to list all known
426
+ # modules together with a brief description of each.
427
+ #
428
+ local rule print-help-all (
429
+ ignored # Usually the module name, but is ignored here.
430
+ )
431
+ {
432
+ print.section "Modules"
433
+ "These are all the known modules. Use --help <module> to get more"
434
+ "detailed information."
435
+ ;
436
+ if $(documented-modules)
437
+ {
438
+ print.list-start ;
439
+ for local module-name in [ sequence.insertion-sort $(documented-modules) ]
440
+ {
441
+ # The brief docs for each module.
442
+ print.list-item $(module-name): $($(module-name).brief) ;
443
+ }
444
+ print.list-end ;
445
+ }
446
+ # The documentation for each module when details are requested.
447
+ if $(documented-modules) && $(.option.detailed)
448
+ {
449
+ for local module-name in [ sequence.insertion-sort $(documented-modules) ]
450
+ {
451
+ # The brief docs for each module.
452
+ print-help-module $(module-name) ;
453
+ }
454
+ }
455
+ }
456
+
457
+
458
+ # Generate documentation for a module. Basic information about the module is
459
+ # generated.
460
+ #
461
+ local rule print-help-module (
462
+ module-name # The module to generate docs for.
463
+ )
464
+ {
465
+ # Print the docs.
466
+ print.section "Module '$(module-name)'" $($(module-name).docs) ;
467
+
468
+ # Print out the documented classes.
469
+ print-help-module-section $(module-name) classes : "Module '$(module-name)' classes"
470
+ Use --help $(module-name).<class-name> to get more information. ;
471
+
472
+ # Print out the documented rules.
473
+ print-help-module-section $(module-name) rules : "Module '$(module-name)' rules"
474
+ Use --help $(module-name).<rule-name> to get more information. ;
475
+
476
+ # Print out the documented variables.
477
+ print-help-module-section $(module-name) variables : "Module '$(module-name)' variables"
478
+ Use --help $(module-name).<variable-name> to get more information. ;
479
+
480
+ # Print out all the same information but indetailed form.
481
+ if $(.option.detailed)
482
+ {
483
+ print-help-classes $(module-name) ;
484
+ print-help-rules $(module-name) ;
485
+ print-help-variables $(module-name) ;
486
+ }
487
+ }
488
+
489
+
490
+ # Generate documentation for a set of rules in a module.
491
+ #
492
+ local rule print-help-rules (
493
+ module-name # Module of the rules.
494
+ : name * # Optional list of rules to describe.
495
+ )
496
+ {
497
+ name ?= $($(module-name).rules) ;
498
+ if [ set.intersection $(name) : $($(module-name).rules) $($(module-name).class-rules) ]
499
+ {
500
+ # Print out the given rules.
501
+ for local rule-name in [ sequence.insertion-sort $(name) ]
502
+ {
503
+ if $(.option.show-locals) || ! $($(module-name).$(rule-name).is-local)
504
+ {
505
+ local signature = $($(module-name).$(rule-name).signature:J=" ") ;
506
+ signature ?= "" ;
507
+ print.section "Rule '$(module-name).$(rule-name) ( $(signature) )'"
508
+ $($(module-name).$(rule-name).docs) ;
509
+ if $($(module-name).$(rule-name).args)
510
+ {
511
+ print.list-start ;
512
+ for local arg-name in $($(module-name).$(rule-name).args)
513
+ {
514
+ print.list-item $(arg-name): $($(module-name).$(rule-name).args.$(arg-name).docs) ;
515
+ }
516
+ print.list-end ;
517
+ }
518
+ }
519
+ }
520
+ }
521
+ }
522
+
523
+
524
+ # Generate documentation for a set of classes in a module.
525
+ #
526
+ local rule print-help-classes (
527
+ module-name # Module of the classes.
528
+ : name * # Optional list of classes to describe.
529
+ )
530
+ {
531
+ name ?= $($(module-name).classes) ;
532
+ if [ set.intersection $(name) : $($(module-name).classes) ]
533
+ {
534
+ # Print out the given classes.
535
+ for local class-name in [ sequence.insertion-sort $(name) ]
536
+ {
537
+ if $(.option.show-locals) || ! $($(module-name).$(class-name).is-local)
538
+ {
539
+ local signature = $($(module-name).$(class-name).signature:J=" ") ;
540
+ signature ?= "" ;
541
+ print.section "Class '$(module-name).$(class-name) ( $(signature) )'"
542
+ $($(module-name).$(class-name).docs)
543
+ "Inherits from '"$($(module-name).$(class-name).super-name)"'." ;
544
+ if $($(module-name).$(class-name).args)
545
+ {
546
+ print.list-start ;
547
+ for local arg-name in $($(module-name).$(class-name).args)
548
+ {
549
+ print.list-item $(arg-name): $($(module-name).$(class-name).args.$(arg-name).docs) ;
550
+ }
551
+ print.list-end ;
552
+ }
553
+ }
554
+
555
+ # Print out the documented rules of the class.
556
+ print-help-module-section $(module-name) $(class-name).class-rules : "Class '$(module-name).$(class-name)' rules"
557
+ Use --help $(module-name).<rule-name> to get more information. ;
558
+
559
+ # Print out all the rules if details are requested.
560
+ if $(.option.detailed)
561
+ {
562
+ print-help-rules $(module-name) : $($(module-name).$(class-name).class-rules) ;
563
+ }
564
+ }
565
+ }
566
+ }
567
+
568
+
569
+ # Generate documentation for a set of variables in a module.
570
+ #
571
+ local rule print-help-variables (
572
+ module-name ? # Module of the variables.
573
+ : name * # Optional list of variables to describe.
574
+ )
575
+ {
576
+ name ?= $($(module-name).variables) ;
577
+ if [ set.intersection $(name) : $($(module-name).variables) ]
578
+ {
579
+ # Print out the given variables.
580
+ for local variable-name in [ sequence.insertion-sort $(name) ]
581
+ {
582
+ print.section "Variable '$(module-name).$(variable-name)'" $($(module-name).$(variable-name).docs) ;
583
+ if $($(module-name).$(variable-name).default) ||
584
+ $($(module-name).$(variable-name).initial)
585
+ {
586
+ print.list-start ;
587
+ if $($(module-name).$(variable-name).default)
588
+ {
589
+ print.list-item "default value:" '$($(module-name).$(variable-name).default:J=" ")' ;
590
+ }
591
+ if $($(module-name).$(variable-name).initial)
592
+ {
593
+ print.list-item "initial value:" '$($(module-name).$(variable-name).initial:J=" ")' ;
594
+ }
595
+ print.list-end ;
596
+ }
597
+ }
598
+ }
599
+ }
600
+
601
+
602
+ # Generate documentation for a project.
603
+ #
604
+ local rule print-help-project (
605
+ unused ?
606
+ : jamfile * # The project Jamfile.
607
+ )
608
+ {
609
+ if $(jamfile<$(jamfile)>.docs)
610
+ {
611
+ # Print the docs.
612
+ print.section "Project-specific help"
613
+ Project has jamfile at $(jamfile) ;
614
+
615
+ print.lines $(jamfile<$(jamfile)>.docs) "" ;
616
+ }
617
+ }
618
+
619
+
620
+ # Generate documentation for a config file.
621
+ #
622
+ local rule print-help-config (
623
+ unused ?
624
+ : type # The type of configuration file user or site.
625
+ config-file # The configuration Jamfile.
626
+ )
627
+ {
628
+ if $(jamfile<$(config-file)>.docs)
629
+ {
630
+ # Print the docs.
631
+ print.section "Configuration help"
632
+ Configuration file at $(config-file) ;
633
+
634
+ print.lines $(jamfile<$(config-file)>.docs) "" ;
635
+ }
636
+ }
637
+
638
+
639
+ ws = " " ;
640
+
641
+ # Extract the text from a block of comments.
642
+ #
643
+ local rule extract-comment (
644
+ var # The name of the variable to extract from.
645
+ )
646
+ {
647
+ local comment = ;
648
+ local line = $($(var)[1]) ;
649
+ local l = [ MATCH "^[$(ws)]*(#)(.*)$" : $(line) ] ;
650
+ while $(l[1]) && $($(var))
651
+ {
652
+ if $(l[2]) { comment += [ MATCH "^[$(ws)]?(.*)$" : $(l[2]) ] ; }
653
+ else { comment += "" ; }
654
+ $(var) = $($(var)[2-]) ;
655
+ line = $($(var)[1]) ;
656
+ l = [ MATCH "^[$(ws)]*(#)(.*)$" : $(line) ] ;
657
+ }
658
+ return $(comment) ;
659
+ }
660
+
661
+
662
+ # Extract s single line of Jam syntax, ignoring any comments.
663
+ #
664
+ local rule extract-syntax (
665
+ var # The name of the variable to extract from.
666
+ )
667
+ {
668
+ local syntax = ;
669
+ local line = $($(var)[1]) ;
670
+ while ! $(syntax) && ! [ MATCH "^[$(ws)]*(#)" : $(line) ] && $($(var))
671
+ {
672
+ local m = [ MATCH "^[$(ws)]*(.*)$" : $(line) ] ;
673
+ if $(m)
674
+ {
675
+ syntax = $(m) ;
676
+ }
677
+ $(var) = $($(var)[2-]) ;
678
+ line = $($(var)[1]) ;
679
+ }
680
+ return $(syntax) ;
681
+ }
682
+
683
+
684
+ # Extract the next token, this is either a single Jam construct or a comment as
685
+ # a single token.
686
+ #
687
+ local rule extract-token (
688
+ var # The name of the variable to extract from.
689
+ )
690
+ {
691
+ local parts = ;
692
+ while ! $(parts)
693
+ {
694
+ parts = [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]*(.*)" : $($(var)[1]) ] ;
695
+ if ! $(parts)
696
+ {
697
+ $(var) = $($(var)[2-]) ;
698
+ }
699
+ }
700
+ local token = ;
701
+ if [ MATCH "^(#)" : $(parts[1]) ]
702
+ {
703
+ token = $(parts:J=" ") ;
704
+ $(var) = $($(var)[2-]) ;
705
+ }
706
+ else
707
+ {
708
+ token = $(parts[1]) ;
709
+ $(var) = $(parts[2-]:J=" ") $($(var)[2-]) ;
710
+ }
711
+ return $(token) ;
712
+ }
713
+
714
+
715
+ # Scan for a rule declaration as the next item in the variable.
716
+ #
717
+ local rule scan-rule (
718
+ syntax ? # The first part of the text which contains the rule declaration.
719
+ : var # The name of the variable to extract from.
720
+ )
721
+ {
722
+ local rule-parts =
723
+ [ MATCH "^[$(ws)]*(rule|local[$(ws)]*rule)[$(ws)]+([^$(ws)]+)[$(ws)]*(.*)" : $(syntax:J=" ") ] ;
724
+ if $(rule-parts[1])
725
+ {
726
+ # Mark as doc for rule.
727
+ local rule-name = $(rule-parts[2]) ;
728
+ if $(scope-name)
729
+ {
730
+ rule-name = $(scope-name).$(rule-name) ;
731
+ }
732
+ local is-local = [ MATCH "^(local).*" : $(rule-parts[1]) ] ;
733
+ if $(comment-block)
734
+ {
735
+ set-rule-doc $(rule-name) $(module-name) $(is-local) : $(comment-block) ;
736
+ }
737
+ # Parse args of rule.
738
+ $(var) = $(rule-parts[3-]) $($(var)) ;
739
+ set-rule-arguments-signature $(rule-name) $(module-name) : [ scan-rule-arguments $(var) ] ;
740
+ # Scan within this rules scope.
741
+ local scope-level = [ extract-token $(var) ] ;
742
+ local scope-name = $(rule-name) ;
743
+ while $(scope-level)
744
+ {
745
+ local comment-block = [ extract-comment $(var) ] ;
746
+ local syntax-block = [ extract-syntax $(var) ] ;
747
+ if [ scan-rule $(syntax-block) : $(var) ]
748
+ {
749
+ }
750
+ else if [ MATCH "^(\\{)" : $(syntax-block) ]
751
+ {
752
+ scope-level += "{" ;
753
+ }
754
+ else if [ MATCH "^[^\\}]*([\\}])[$(ws)]*$" : $(syntax-block) ]
755
+ {
756
+ scope-level = $(scope-level[2-]) ;
757
+ }
758
+ }
759
+
760
+ return true ;
761
+ }
762
+ }
763
+
764
+
765
+ # Scan the arguments of a rule.
766
+ #
767
+ local rule scan-rule-arguments (
768
+ var # The name of the variable to extract from.
769
+ )
770
+ {
771
+ local arg-syntax = ;
772
+ local token = [ extract-token $(var) ] ;
773
+ while $(token) != "(" && $(token) != "{"
774
+ {
775
+ token = [ extract-token $(var) ] ;
776
+ }
777
+ if $(token) != "{"
778
+ {
779
+ token = [ extract-token $(var) ] ;
780
+ }
781
+ local arg-signature = ;
782
+ while $(token) != ")" && $(token) != "{"
783
+ {
784
+ local arg-name = ;
785
+ local arg-qualifier = " " ;
786
+ local arg-doc = ;
787
+ if $(token) = ":"
788
+ {
789
+ arg-signature += $(token) ;
790
+ token = [ extract-token $(var) ] ;
791
+ }
792
+ arg-name = $(token) ;
793
+ arg-signature += $(token) ;
794
+ token = [ extract-token $(var) ] ;
795
+ if [ MATCH "^([\\*\\+\\?])" : $(token) ]
796
+ {
797
+ arg-qualifier = $(token) ;
798
+ arg-signature += $(token) ;
799
+ token = [ extract-token $(var) ] ;
800
+ }
801
+ if $(token) = ":"
802
+ {
803
+ arg-signature += $(token) ;
804
+ token = [ extract-token $(var) ] ;
805
+ }
806
+ if [ MATCH "^(#)" : $(token) ]
807
+ {
808
+ $(var) = $(token) $($(var)) ;
809
+ arg-doc = [ extract-comment $(var) ] ;
810
+ token = [ extract-token $(var) ] ;
811
+ }
812
+ set-argument-doc $(arg-name) $(arg-qualifier) $(rule-name) $(module-name) : $(arg-doc) ;
813
+ }
814
+ while $(token) != "{"
815
+ {
816
+ token = [ extract-token $(var) ] ;
817
+ }
818
+ $(var) = "{" $($(var)) ;
819
+ arg-signature ?= "" ;
820
+ return $(arg-signature) ;
821
+ }
822
+
823
+
824
+ # Scan for a variable declaration.
825
+ #
826
+ local rule scan-variable (
827
+ syntax ? # The first part of the text which contains the variable declaration.
828
+ : var # The name of the variable to extract from.
829
+ )
830
+ {
831
+ # [1] = name, [2] = value(s)
832
+ local var-parts =
833
+ [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]+([\\?\\=]*)[$(ws)]+([^\\;]*)\\;" : $(syntax) ] ;
834
+ if $(var-parts)
835
+ {
836
+ local value = [ MATCH "^(.*)[ ]$" : $(var-parts[3-]:J=" ") ] ;
837
+ local default-value = "" ;
838
+ local initial-valie = "" ;
839
+ if $(var-parts[2]) = "?="
840
+ {
841
+ default-value = $(value) ;
842
+ default-value ?= "(empty)" ;
843
+ }
844
+ else
845
+ {
846
+ initial-value = $(value) ;
847
+ initial-value ?= "(empty)" ;
848
+ }
849
+ if $(comment-block)
850
+ {
851
+ set-variable-doc $(var-parts[1]) $(default-value) $(initial-value) $(module-name) : $(comment-block) ;
852
+ }
853
+ return true ;
854
+ }
855
+ }
856
+
857
+
858
+ # Scan a class declaration.
859
+ #
860
+ local rule scan-class (
861
+ syntax ? # The syntax text for the class declaration.
862
+ )
863
+ {
864
+ # [1] = class?, [2] = name, [3] = superclass
865
+ local class-parts =
866
+ [ MATCH "^[$(ws)]*([^$(ws)]+)[$(ws)]+([^$(ws)]+)[$(ws)]+:*[$(ws)]*([^$(ws);]*)" : $(syntax) ] ;
867
+ if $(class-parts[1]) = "class" || $(class-parts[1]) = "class.class"
868
+ {
869
+ set-class-doc $(class-parts[2]) $(module-name) : $(class-parts[3]) ;
870
+ }
871
+ }
872
+
873
+
874
+ # Scan a module file for documentation comments. This also invokes any actions
875
+ # assigned to the module. The actions are the rules that do the actual output of
876
+ # the documentation. This rule is invoked as the header scan rule for the module
877
+ # file.
878
+ #
879
+ rule scan-module (
880
+ target # The module file.
881
+ : text * # The text in the file, one item per line.
882
+ : action * # Rule to call to output docs for the module.
883
+ )
884
+ {
885
+ if $(.option.debug) { ECHO "HELP:" scanning module target '$(target)' ; }
886
+ local module-name = $(target:B) ;
887
+ local module-documented = ;
888
+ local comment-block = ;
889
+ local syntax-block = ;
890
+ # This is a hack because we can not get the line of a file if it happens to
891
+ # not have a new-line termination.
892
+ text += "}" ;
893
+ while $(text)
894
+ {
895
+ comment-block = [ extract-comment text ] ;
896
+ syntax-block = [ extract-syntax text ] ;
897
+ if $(.option.debug)
898
+ {
899
+ ECHO "HELP:" comment block; '$(comment-block)' ;
900
+ ECHO "HELP:" syntax block; '$(syntax-block)' ;
901
+ }
902
+ if [ scan-rule $(syntax-block) : text ] { }
903
+ else if [ scan-variable $(syntax-block) : text ] { }
904
+ else if [ scan-class $(syntax-block) ] { }
905
+ else if [ MATCH .*([cC]opyright).* : $(comment-block:J=" ") ]
906
+ {
907
+ # mark as the copy for the module.
908
+ set-module-copyright $(module-name) : $(comment-block) ;
909
+ }
910
+ else if $(action[1]) in "print-help-project" "print-help-config"
911
+ && ! $(jamfile<$(target)>.docs)
912
+ {
913
+ # special module docs for the project jamfile.
914
+ jamfile<$(target)>.docs = $(comment-block) ;
915
+ }
916
+ else if ! $(module-documented)
917
+ {
918
+ # document the module.
919
+ set-module-doc $(module-name) : $(comment-block) ;
920
+ module-documented = true ;
921
+ }
922
+ }
923
+ if $(action)
924
+ {
925
+ $(action[1]) $(module-name) : $(action[2-]) ;
926
+ }
927
+ }
928
+
929
+
930
+ # Import scan-module to global scope, so that it is available during header
931
+ # scanning phase.
932
+ #
933
+ IMPORT $(__name__) : scan-module : : doc.scan-module ;
934
+
935
+
936
+ # Read in a file using the SHELL builtin and return the individual lines as
937
+ # would be done for header scanning.
938
+ #
939
+ local rule read-file (
940
+ file # The file to read in.
941
+ )
942
+ {
943
+ file = [ path.native [ path.root [ path.make $(file) ] [ path.pwd ] ] ] ;
944
+ if ! $(.file<$(file)>.lines)
945
+ {
946
+ local content ;
947
+ switch [ modules.peek : OS ]
948
+ {
949
+ case NT :
950
+ content = [ SHELL "TYPE \"$(file)\"" ] ;
951
+
952
+ case * :
953
+ content = [ SHELL "cat \"$(file)\"" ] ;
954
+ }
955
+ local lines ;
956
+ local nl = "
957
+ " ;
958
+ local << = "([^$(nl)]*)[$(nl)](.*)" ;
959
+ local line+ = [ MATCH "$(<<)" : "$(content)" ] ;
960
+ while $(line+)
961
+ {
962
+ lines += $(line+[1]) ;
963
+ line+ = [ MATCH "$(<<)" : "$(line+[2])" ] ;
964
+ }
965
+ .file<$(file)>.lines = $(lines) ;
966
+ }
967
+ return $(.file<$(file)>.lines) ;
968
+ }
969
+
970
+
971
+ # Add a scan action to perform to generate the help documentation. The action
972
+ # rule is passed the name of the module as the first argument. The second
973
+ # argument(s) are optional and passed directly as specified here.
974
+ #
975
+ local rule do-scan (
976
+ modules + # The modules to scan and perform the action on.
977
+ : action * # The action rule, plus the secondary arguments to pass to the action rule.
978
+ )
979
+ {
980
+ if $(help-output) = text
981
+ {
982
+ print.output $(help-output-file).txt plain ;
983
+ ALWAYS $(help-output-file).txt ;
984
+ DEPENDS all : $(help-output-file).txt ;
985
+ }
986
+ if $(help-output) = html
987
+ {
988
+ print.output $(help-output-file).html html ;
989
+ ALWAYS $(help-output-file).html ;
990
+ DEPENDS all : $(help-output-file).html ;
991
+ }
992
+ for local module-file in $(modules[1--2])
993
+ {
994
+ scan-module $(module-file) : [ read-file $(module-file) ] ;
995
+ }
996
+ scan-module $(modules[-1]) : [ read-file $(modules[-1]) ] : $(action) ;
997
+ }
mosesdecoder/jam-files/boost-build/util/numbers.jam ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2001, 2002 Dave Abrahams
2
+ # Copyright 2002, 2003 Vladimir Prus
3
+ # Distributed under the Boost Software License, Version 1.0.
4
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
+
6
+ import errors ;
7
+
8
+
9
+ rule trim-leading-zeroes ( value )
10
+ {
11
+ return [ CALC $(value) + 0 ] ;
12
+ }
13
+
14
+
15
+ rule check ( numbers * )
16
+ {
17
+ for local n in $(numbers)
18
+ {
19
+ switch $(n)
20
+ {
21
+ case *[^0-9]* :
22
+ errors.error $(n) "in" $(numbers) : is not a number ;
23
+ }
24
+ }
25
+ }
26
+
27
+
28
+ rule increment ( number )
29
+ {
30
+ return [ CALC $(number) + 1 ] ;
31
+ }
32
+
33
+
34
+ rule decrement ( number )
35
+ {
36
+ return [ CALC $(number) - 1 ] ;
37
+ }
38
+
39
+
40
+ rule range ( start finish ? : step ? )
41
+ {
42
+ if ! $(finish)
43
+ {
44
+ finish = $(start) ;
45
+ start = 1 ;
46
+ }
47
+ step ?= 1 ;
48
+
49
+ check $(start) $(finish) $(step) ;
50
+
51
+ if $(finish) != 0
52
+ {
53
+ local result ;
54
+ while [ less $(start) $(finish) ] || $(start) = $(finish)
55
+ {
56
+ result += $(start) ;
57
+ start = [ CALC $(start) + $(step) ] ;
58
+ }
59
+ return $(result) ;
60
+ }
61
+ }
62
+
63
+
64
+ rule less ( n1 n2 )
65
+ {
66
+ switch [ CALC $(n2) - $(n1) ]
67
+ {
68
+ case [1-9]* : return true ;
69
+ }
70
+ }
71
+
72
+
73
+ rule log10 ( number )
74
+ {
75
+ switch $(number)
76
+ {
77
+ case *[^0-9]* : errors.error $(number) is not a number ;
78
+ case 0 : errors.error can't take log of zero ;
79
+ case [1-9] : return 0 ;
80
+ case [1-9]? : return 1 ;
81
+ case [1-9]?? : return 2 ;
82
+ case [1-9]??? : return 3 ;
83
+ case [1-9]???? : return 4 ;
84
+ case [1-9]????? : return 5 ;
85
+ case [1-9]?????? : return 6 ;
86
+ case [1-9]??????? : return 7 ;
87
+ case [1-9]???????? : return 8 ;
88
+ case [1-9]????????? : return 9 ;
89
+ case * :
90
+ {
91
+ import sequence ;
92
+ import string ;
93
+ local chars = [ string.chars $(number) ] ;
94
+ while $(chars[1]) = 0
95
+ {
96
+ chars = $(chars[2-]) ;
97
+ }
98
+ if ! $(chars)
99
+ {
100
+ errors.error can't take log of zero ;
101
+ }
102
+ else
103
+ {
104
+ return [ decrement [ sequence.length $(chars) ] ] ;
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+
111
+ rule __test__ ( )
112
+ {
113
+ import assert ;
114
+
115
+ assert.result 1 : increment 0 ;
116
+ assert.result 2 : increment 1 ;
117
+ assert.result 1 : decrement 2 ;
118
+ assert.result 0 : decrement 1 ;
119
+ assert.result 50 : increment 49 ;
120
+ assert.result 49 : decrement 50 ;
121
+ assert.result 99 : increment 98 ;
122
+ assert.result 99 : decrement 100 ;
123
+ assert.result 100 : increment 99 ;
124
+ assert.result 999 : decrement 1000 ;
125
+ assert.result 1000 : increment 999 ;
126
+
127
+ assert.result 1 2 3 : range 3 ;
128
+ assert.result 1 2 3 4 5 6 7 8 9 10 11 12 : range 12 ;
129
+ assert.result 3 4 5 6 7 8 9 10 11 : range 3 11 ;
130
+ assert.result : range 0 ;
131
+ assert.result 1 4 7 10 : range 10 : 3 ;
132
+ assert.result 2 4 6 8 10 : range 2 10 : 2 ;
133
+ assert.result 25 50 75 100 : range 25 100 : 25 ;
134
+
135
+ assert.result 0 : trim-leading-zeroes 0 ;
136
+ assert.result 1234 : trim-leading-zeroes 1234 ;
137
+ assert.result 123456 : trim-leading-zeroes 0000123456 ;
138
+ assert.result 1000123456 : trim-leading-zeroes 1000123456 ;
139
+ assert.result 10000 : trim-leading-zeroes 10000 ;
140
+ assert.result 10000 : trim-leading-zeroes 00010000 ;
141
+
142
+ assert.true less 1 2 ;
143
+ assert.true less 1 12 ;
144
+ assert.true less 1 21 ;
145
+ assert.true less 005 217 ;
146
+ assert.false less 0 0 ;
147
+ assert.false less 03 3 ;
148
+ assert.false less 3 03 ;
149
+ assert.true less 005 217 ;
150
+ assert.true less 0005 217 ;
151
+ assert.true less 5 00217 ;
152
+
153
+ # TEMPORARY disabled, because nested "try"/"catch" do not work and I do no
154
+ # have the time to fix that right now.
155
+ if $(0)
156
+ {
157
+ try ;
158
+ {
159
+ decrement 0 ;
160
+ }
161
+ catch can't decrement zero! ;
162
+
163
+ try ;
164
+ {
165
+ check foo ;
166
+ }
167
+ catch : not a number ;
168
+
169
+ try ;
170
+ {
171
+ increment foo ;
172
+ }
173
+ catch : not a number ;
174
+
175
+ try ;
176
+ {
177
+ log10 0 ;
178
+ }
179
+ catch can't take log of zero ;
180
+
181
+ try ;
182
+ {
183
+ log10 000 ;
184
+ }
185
+ catch can't take log of zero ;
186
+
187
+ }
188
+
189
+ assert.result 0 : log10 1 ;
190
+ assert.result 0 : log10 9 ;
191
+ assert.result 1 : log10 10 ;
192
+ assert.result 1 : log10 99 ;
193
+ assert.result 2 : log10 100 ;
194
+ assert.result 2 : log10 101 ;
195
+ assert.result 2 : log10 125 ;
196
+ assert.result 2 : log10 999 ;
197
+ assert.result 3 : log10 1000 ;
198
+ assert.result 10 : log10 12345678901 ;
199
+
200
+ for local x in [ range 75 110 : 5 ]
201
+ {
202
+ for local y in [ range $(x) 111 : 3 ]
203
+ {
204
+ if $(x) != $(y)
205
+ {
206
+ assert.true less $(x) $(y) ;
207
+ }
208
+ }
209
+ }
210
+
211
+ for local x in [ range 90 110 : 2 ]
212
+ {
213
+ for local y in [ range 80 $(x) : 4 ]
214
+ {
215
+ assert.false less $(x) $(y) ;
216
+ }
217
+ }
218
+ }
mosesdecoder/jam-files/boost-build/util/regex.jam ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2001, 2002 Dave Abrahams
2
+ # Copyright 2003 Douglas Gregor
3
+ # Copyright 2003 Rene Rivera
4
+ # Copyright 2002, 2003, 2004, 2005 Vladimir Prus
5
+ # Distributed under the Boost Software License, Version 1.0.
6
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
7
+
8
+ #
9
+ # Returns a list of the following substrings:
10
+ # 1) from beginning till the first occurrence of 'separator' or till the end,
11
+ # 2) between each occurrence of 'separator' and the next occurrence,
12
+ # 3) from the last occurrence of 'separator' till the end.
13
+ # If no separator is present, the result will contain only one element.
14
+ #
15
+
16
+ rule split ( string separator )
17
+ {
18
+ local result ;
19
+ local s = $(string) ;
20
+
21
+ # Break pieaces off 's' until it has no separators left.
22
+ local match = 1 ;
23
+ while $(match)
24
+ {
25
+ match = [ MATCH ^(.*)($(separator))(.*) : $(s) ] ;
26
+ if $(match)
27
+ {
28
+ match += "" ; # in case 3rd item was empty - works around MATCH bug
29
+ result = $(match[3]) $(result) ;
30
+ s = $(match[1]) ;
31
+ }
32
+ }
33
+ # Combine the remaining part at the beginning, which does not have
34
+ # separators, with the pieces broken off. Note that the rule's signature
35
+ # does not allow the initial s to be empty.
36
+ return $(s) $(result) ;
37
+ }
38
+
39
+
40
+ # Returns the concatenated results of Applying regex.split to every element of
41
+ # the list using the separator pattern.
42
+ #
43
+ rule split-list ( list * : separator )
44
+ {
45
+ local result ;
46
+ for s in $(list)
47
+ {
48
+ result += [ split $(s) $(separator) ] ;
49
+ }
50
+ return $(result) ;
51
+ }
52
+
53
+
54
+ # Match string against pattern, and return the elements indicated by indices.
55
+ #
56
+ rule match ( pattern : string : indices * )
57
+ {
58
+ indices ?= 1 2 3 4 5 6 7 8 9 ;
59
+ local x = [ MATCH $(pattern) : $(string) ] ;
60
+ return $(x[$(indices)]) ;
61
+ }
62
+
63
+
64
+ # Matches all elements of 'list' agains the 'pattern' and returns a list of
65
+ # elements indicated by indices of all successful matches. If 'indices' is
66
+ # omitted returns a list of first paranthethised groups of all successful
67
+ # matches.
68
+ #
69
+ rule transform ( list * : pattern : indices * )
70
+ {
71
+ indices ?= 1 ;
72
+ local result ;
73
+ for local e in $(list)
74
+ {
75
+ local m = [ MATCH $(pattern) : $(e) ] ;
76
+ if $(m)
77
+ {
78
+ result += $(m[$(indices)]) ;
79
+ }
80
+ }
81
+ return $(result) ;
82
+ }
83
+
84
+ NATIVE_RULE regex : transform ;
85
+
86
+
87
+ # Escapes all of the characters in symbols using the escape symbol escape-symbol
88
+ # for the given string, and returns the escaped string.
89
+ #
90
+ rule escape ( string : symbols : escape-symbol )
91
+ {
92
+ local result = "" ;
93
+ local m = 1 ;
94
+ while $(m)
95
+ {
96
+ m = [ MATCH ^([^$(symbols)]*)([$(symbols)])(.*) : $(string) ] ;
97
+ if $(m)
98
+ {
99
+ m += "" ; # Supposedly a bug fix; borrowed from regex.split
100
+ result = "$(result)$(m[1])$(escape-symbol)$(m[2])" ;
101
+ string = $(m[3]) ;
102
+ }
103
+ }
104
+ string ?= "" ;
105
+ result = "$(result)$(string)" ;
106
+ return $(result) ;
107
+ }
108
+
109
+
110
+ # Replaces occurrences of a match string in a given string and returns the new
111
+ # string. The match string can be a regex expression.
112
+ #
113
+ rule replace (
114
+ string # The string to modify.
115
+ match # The characters to replace.
116
+ replacement # The string to replace with.
117
+ )
118
+ {
119
+ local result = "" ;
120
+ local parts = 1 ;
121
+ while $(parts)
122
+ {
123
+ parts = [ MATCH ^(.*)($(match))(.*) : $(string) ] ;
124
+ if $(parts)
125
+ {
126
+ parts += "" ;
127
+ result = "$(replacement)$(parts[3])$(result)" ;
128
+ string = $(parts[1]) ;
129
+ }
130
+ }
131
+ string ?= "" ;
132
+ result = "$(string)$(result)" ;
133
+ return $(result) ;
134
+ }
135
+
136
+
137
+ # Replaces occurrences of a match string in a given list of strings and returns
138
+ # a list of new strings. The match string can be a regex expression.
139
+ #
140
+ # list - the list of strings to modify.
141
+ # match - the search expression.
142
+ # replacement - the string to replace with.
143
+ #
144
+ rule replace-list ( list * : match : replacement )
145
+ {
146
+ local result ;
147
+ for local e in $(list)
148
+ {
149
+ result += [ replace $(e) $(match) $(replacement) ] ;
150
+ }
151
+ return $(result) ;
152
+ }
153
+
154
+
155
+ rule __test__ ( )
156
+ {
157
+ import assert ;
158
+
159
+ assert.result a b c : split "a/b/c" / ;
160
+ assert.result "" a b c : split "/a/b/c" / ;
161
+ assert.result "" "" a b c : split "//a/b/c" / ;
162
+ assert.result "" a "" b c : split "/a//b/c" / ;
163
+ assert.result "" a "" b c "" : split "/a//b/c/" / ;
164
+ assert.result "" a "" b c "" "" : split "/a//b/c//" / ;
165
+
166
+ assert.result a c b d
167
+ : match (.)(.)(.)(.) : abcd : 1 3 2 4 ;
168
+
169
+ assert.result a b c d
170
+ : match (.)(.)(.)(.) : abcd ;
171
+
172
+ assert.result ababab cddc
173
+ : match ((ab)*)([cd]+) : abababcddc : 1 3 ;
174
+
175
+ assert.result a.h c.h
176
+ : transform <a.h> \"b.h\" <c.h> : <(.*)> ;
177
+
178
+ assert.result a.h b.h c.h
179
+ : transform <a.h> \"b.h\" <c.h> : <([^>]*)>|\"([^\"]*)\" : 1 2 ;
180
+
181
+ assert.result "^<?xml version=\"1.0\"^>"
182
+ : escape "<?xml version=\"1.0\">" : "&|()<>^" : "^" ;
183
+
184
+ assert.result "<?xml version=\\\"1.0\\\">"
185
+ : escape "<?xml version=\"1.0\">" : "\\\"" : "\\" ;
186
+
187
+ assert.result "string&nbsp;string&nbsp;" : replace "string string " " " "&nbsp;" ;
188
+ assert.result "&nbsp;string&nbsp;string" : replace " string string" " " "&nbsp;" ;
189
+ assert.result "string&nbsp;&nbsp;string" : replace "string string" " " "&nbsp;" ;
190
+ assert.result "-" : replace "&" "&" "-" ;
191
+
192
+ assert.result "-" "a-b" : replace-list "&" "a&b" : "&" : "-" ;
193
+ }
mosesdecoder/jam-files/engine/build.bat ADDED
@@ -0,0 +1,565 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @ECHO OFF
2
+
3
+ REM ~ Copyright 2002-2007 Rene Rivera.
4
+ REM ~ Distributed under the Boost Software License, Version 1.0.
5
+ REM ~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
6
+
7
+ setlocal
8
+ goto Start
9
+
10
+
11
+ :Set_Error
12
+ color 00
13
+ goto :eof
14
+
15
+
16
+ :Clear_Error
17
+ ver >nul
18
+ goto :eof
19
+
20
+
21
+ :Error_Print
22
+ REM Output an error message and set the errorlevel to indicate failure.
23
+ setlocal
24
+ ECHO ###
25
+ ECHO ### %1
26
+ ECHO ###
27
+ ECHO ### You can specify the toolset as the argument, i.e.:
28
+ ECHO ### .\build.bat msvc
29
+ ECHO ###
30
+ ECHO ### Toolsets supported by this script are: borland, como, gcc, gcc-nocygwin,
31
+ ECHO ### intel-win32, metrowerks, mingw, msvc, vc7, vc8, vc9, vc10, vc11
32
+ ECHO ###
33
+ call :Set_Error
34
+ endlocal
35
+ goto :eof
36
+
37
+
38
+ :Test_Path
39
+ REM Tests for the given file(executable) presence in the directories in the PATH
40
+ REM environment variable. Additionaly sets FOUND_PATH to the path of the
41
+ REM found file.
42
+ call :Clear_Error
43
+ setlocal
44
+ set test=%~$PATH:1
45
+ endlocal
46
+ if not errorlevel 1 set FOUND_PATH=%~dp$PATH:1
47
+ goto :eof
48
+
49
+
50
+ :Test_Option
51
+ REM Tests whether the given string is in the form of an option: "--*"
52
+ call :Clear_Error
53
+ setlocal
54
+ set test=%1
55
+ if not defined test (
56
+ call :Set_Error
57
+ goto Test_Option_End
58
+ )
59
+ set test=###%test%###
60
+ set test=%test:"###=%
61
+ set test=%test:###"=%
62
+ set test=%test:###=%
63
+ if not "-" == "%test:~1,1%" call :Set_Error
64
+ :Test_Option_End
65
+ endlocal
66
+ goto :eof
67
+
68
+
69
+ :Test_Empty
70
+ REM Tests whether the given string is not empty
71
+ call :Clear_Error
72
+ setlocal
73
+ set test=%1
74
+ if not defined test (
75
+ call :Clear_Error
76
+ goto Test_Empty_End
77
+ )
78
+ set test=###%test%###
79
+ set test=%test:"###=%
80
+ set test=%test:###"=%
81
+ set test=%test:###=%
82
+ if not "" == "%test%" call :Set_Error
83
+ :Test_Empty_End
84
+ endlocal
85
+ goto :eof
86
+
87
+
88
+ :Call_If_Exists
89
+ if EXIST %1 call %*
90
+ goto :eof
91
+
92
+
93
+ :Guess_Toolset
94
+ REM Try and guess the toolset to bootstrap the build with...
95
+ REM Sets BOOST_JAM_TOOLSET to the first found toolset.
96
+ REM May also set BOOST_JAM_TOOLSET_ROOT to the
97
+ REM location of the found toolset.
98
+
99
+ call :Clear_Error
100
+ call :Test_Empty %ProgramFiles%
101
+ if not errorlevel 1 set ProgramFiles=C:\Program Files
102
+
103
+ call :Clear_Error
104
+ if NOT "_%VS110COMNTOOLS%_" == "__" (
105
+ set "BOOST_JAM_TOOLSET=vc11"
106
+ set "BOOST_JAM_TOOLSET_ROOT=%VS110COMNTOOLS%..\..\VC\"
107
+ goto :eof)
108
+ call :Clear_Error
109
+ if EXIST "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\VCVARSALL.BAT" (
110
+ set "BOOST_JAM_TOOLSET=vc11"
111
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 11.0\VC\"
112
+ goto :eof)
113
+ call :Clear_Error
114
+ if NOT "_%VS100COMNTOOLS%_" == "__" (
115
+ set "BOOST_JAM_TOOLSET=vc10"
116
+ set "BOOST_JAM_TOOLSET_ROOT=%VS100COMNTOOLS%..\..\VC\"
117
+ goto :eof)
118
+ call :Clear_Error
119
+ if EXIST "%ProgramFiles%\Microsoft Visual Studio 10.0\VC\VCVARSALL.BAT" (
120
+ set "BOOST_JAM_TOOLSET=vc10"
121
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 10.0\VC\"
122
+ goto :eof)
123
+ call :Clear_Error
124
+ if NOT "_%VS90COMNTOOLS%_" == "__" (
125
+ set "BOOST_JAM_TOOLSET=vc9"
126
+ set "BOOST_JAM_TOOLSET_ROOT=%VS90COMNTOOLS%..\..\VC\"
127
+ goto :eof)
128
+ call :Clear_Error
129
+ if EXIST "%ProgramFiles%\Microsoft Visual Studio 9.0\VC\VCVARSALL.BAT" (
130
+ set "BOOST_JAM_TOOLSET=vc9"
131
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 9.0\VC\"
132
+ goto :eof)
133
+ call :Clear_Error
134
+ if NOT "_%VS80COMNTOOLS%_" == "__" (
135
+ set "BOOST_JAM_TOOLSET=vc8"
136
+ set "BOOST_JAM_TOOLSET_ROOT=%VS80COMNTOOLS%..\..\VC\"
137
+ goto :eof)
138
+ call :Clear_Error
139
+ if EXIST "%ProgramFiles%\Microsoft Visual Studio 8\VC\VCVARSALL.BAT" (
140
+ set "BOOST_JAM_TOOLSET=vc8"
141
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 8\VC\"
142
+ goto :eof)
143
+ call :Clear_Error
144
+ if NOT "_%VS71COMNTOOLS%_" == "__" (
145
+ set "BOOST_JAM_TOOLSET=vc7"
146
+ set "BOOST_JAM_TOOLSET_ROOT=%VS71COMNTOOLS%\..\..\VC7\"
147
+ goto :eof)
148
+ call :Clear_Error
149
+ if NOT "_%VCINSTALLDIR%_" == "__" (
150
+ REM %VCINSTALLDIR% is also set for VC9 (and probably VC8)
151
+ set "BOOST_JAM_TOOLSET=vc7"
152
+ set "BOOST_JAM_TOOLSET_ROOT=%VCINSTALLDIR%\VC7\"
153
+ goto :eof)
154
+ call :Clear_Error
155
+ if EXIST "%ProgramFiles%\Microsoft Visual Studio .NET 2003\VC7\bin\VCVARS32.BAT" (
156
+ set "BOOST_JAM_TOOLSET=vc7"
157
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio .NET 2003\VC7\"
158
+ goto :eof)
159
+ call :Clear_Error
160
+ if EXIST "%ProgramFiles%\Microsoft Visual Studio .NET\VC7\bin\VCVARS32.BAT" (
161
+ set "BOOST_JAM_TOOLSET=vc7"
162
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio .NET\VC7\"
163
+ goto :eof)
164
+ call :Clear_Error
165
+ if NOT "_%MSVCDir%_" == "__" (
166
+ set "BOOST_JAM_TOOLSET=msvc"
167
+ set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
168
+ goto :eof)
169
+ call :Clear_Error
170
+ if EXIST "%ProgramFiles%\Microsoft Visual Studio\VC98\bin\VCVARS32.BAT" (
171
+ set "BOOST_JAM_TOOLSET=msvc"
172
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio\VC98\"
173
+ goto :eof)
174
+ call :Clear_Error
175
+ if EXIST "%ProgramFiles%\Microsoft Visual C++\VC98\bin\VCVARS32.BAT" (
176
+ set "BOOST_JAM_TOOLSET=msvc"
177
+ set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual C++\VC98\"
178
+ goto :eof)
179
+ call :Clear_Error
180
+ call :Test_Path cl.exe
181
+ if not errorlevel 1 (
182
+ set "BOOST_JAM_TOOLSET=msvc"
183
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
184
+ goto :eof)
185
+ call :Clear_Error
186
+ call :Test_Path vcvars32.bat
187
+ if not errorlevel 1 (
188
+ set "BOOST_JAM_TOOLSET=msvc"
189
+ call "%FOUND_PATH%VCVARS32.BAT"
190
+ set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
191
+ goto :eof)
192
+ call :Clear_Error
193
+ if EXIST "C:\Borland\BCC55\Bin\bcc32.exe" (
194
+ set "BOOST_JAM_TOOLSET=borland"
195
+ set "BOOST_JAM_TOOLSET_ROOT=C:\Borland\BCC55\"
196
+ goto :eof)
197
+ call :Clear_Error
198
+ call :Test_Path bcc32.exe
199
+ if not errorlevel 1 (
200
+ set "BOOST_JAM_TOOLSET=borland"
201
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
202
+ goto :eof)
203
+ call :Clear_Error
204
+ call :Test_Path icl.exe
205
+ if not errorlevel 1 (
206
+ set "BOOST_JAM_TOOLSET=intel-win32"
207
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
208
+ goto :eof)
209
+ call :Clear_Error
210
+ if EXIST "C:\MinGW\bin\gcc.exe" (
211
+ set "BOOST_JAM_TOOLSET=mingw"
212
+ set "BOOST_JAM_TOOLSET_ROOT=C:\MinGW\"
213
+ goto :eof)
214
+ call :Clear_Error
215
+ if NOT "_%CWFolder%_" == "__" (
216
+ set "BOOST_JAM_TOOLSET=metrowerks"
217
+ set "BOOST_JAM_TOOLSET_ROOT=%CWFolder%\"
218
+ goto :eof )
219
+ call :Clear_Error
220
+ call :Test_Path mwcc.exe
221
+ if not errorlevel 1 (
222
+ set "BOOST_JAM_TOOLSET=metrowerks"
223
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\..\"
224
+ goto :eof)
225
+ call :Clear_Error
226
+ call :Error_Print "Could not find a suitable toolset."
227
+ goto :eof
228
+
229
+
230
+ :Guess_Yacc
231
+ REM Tries to find bison or yacc in common places so we can build the grammar.
232
+ call :Clear_Error
233
+ call :Test_Path yacc.exe
234
+ if not errorlevel 1 (
235
+ set "YACC=yacc -d"
236
+ goto :eof)
237
+ call :Clear_Error
238
+ call :Test_Path bison.exe
239
+ if not errorlevel 1 (
240
+ set "YACC=bison -d --yacc"
241
+ goto :eof)
242
+ call :Clear_Error
243
+ if EXIST "C:\Program Files\GnuWin32\bin\bison.exe" (
244
+ set "YACC=C:\Program Files\GnuWin32\bin\bison.exe" -d --yacc
245
+ goto :eof)
246
+ call :Clear_Error
247
+ call :Error_Print "Could not find Yacc to build the Jam grammar."
248
+ goto :eof
249
+
250
+
251
+ :Start
252
+ set BOOST_JAM_TOOLSET=
253
+ set BOOST_JAM_ARGS=
254
+
255
+ REM If no arguments guess the toolset;
256
+ REM or if first argument is an option guess the toolset;
257
+ REM otherwise the argument is the toolset to use.
258
+ call :Clear_Error
259
+ call :Test_Empty %1
260
+ if not errorlevel 1 (
261
+ call :Guess_Toolset
262
+ if not errorlevel 1 ( goto Setup_Toolset ) else ( goto Finish )
263
+ )
264
+
265
+ call :Clear_Error
266
+ call :Test_Option %1
267
+ if not errorlevel 1 (
268
+ call :Guess_Toolset
269
+ if not errorlevel 1 ( goto Setup_Toolset ) else ( goto Finish )
270
+ )
271
+
272
+ call :Clear_Error
273
+ set BOOST_JAM_TOOLSET=%1
274
+ shift
275
+ goto Setup_Toolset
276
+
277
+
278
+ :Setup_Toolset
279
+ REM Setup the toolset command and options. This bit of code
280
+ REM needs to be flexible enough to handle both when
281
+ REM the toolset was guessed at and found, or when the toolset
282
+ REM was indicated in the command arguments.
283
+ REM NOTE: The strange multiple "if ?? == _toolset_" tests are that way
284
+ REM because in BAT variables are subsituted only once during a single
285
+ REM command. A complete "if ... ( commands ) else ( commands )"
286
+ REM is a single command, even though it's in multiple lines here.
287
+ :Setup_Args
288
+ call :Clear_Error
289
+ call :Test_Empty %1
290
+ if not errorlevel 1 goto Config_Toolset
291
+ call :Clear_Error
292
+ call :Test_Option %1
293
+ if errorlevel 1 (
294
+ set BOOST_JAM_ARGS=%BOOST_JAM_ARGS% %1
295
+ shift
296
+ goto Setup_Args
297
+ )
298
+ :Config_Toolset
299
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_metrowerks_" goto Skip_METROWERKS
300
+ if NOT "_%CWFolder%_" == "__" (
301
+ set "BOOST_JAM_TOOLSET_ROOT=%CWFolder%\"
302
+ )
303
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%Other Metrowerks Tools\Command Line Tools;%PATH%"
304
+ set "BOOST_JAM_CC=mwcc -runtime ss -cwd include -DNT -lkernel32.lib -ladvapi32.lib -luser32.lib"
305
+ set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
306
+ set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
307
+ set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
308
+ set "_known_=1"
309
+ :Skip_METROWERKS
310
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_msvc_" goto Skip_MSVC
311
+ if NOT "_%MSVCDir%_" == "__" (
312
+ set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
313
+ )
314
+ call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%bin\VCVARS32.BAT"
315
+ if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
316
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
317
+ )
318
+ set "BOOST_JAM_CC=cl /nologo /GZ /Zi /MLd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG kernel32.lib advapi32.lib user32.lib"
319
+ set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
320
+ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
321
+ set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
322
+ set "_known_=1"
323
+ :Skip_MSVC
324
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc7_" goto Skip_VC7
325
+ if NOT "_%VS71COMNTOOLS%_" == "__" (
326
+ set "BOOST_JAM_TOOLSET_ROOT=%VS71COMNTOOLS%..\..\VC7\"
327
+ )
328
+ if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%bin\VCVARS32.BAT"
329
+ if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
330
+ if "_%VCINSTALLDIR%_" == "__" (
331
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
332
+ ) )
333
+ set "BOOST_JAM_CC=cl /nologo /GZ /Zi /MLd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG kernel32.lib advapi32.lib user32.lib"
334
+ set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
335
+ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
336
+ set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
337
+ set "_known_=1"
338
+ :Skip_VC7
339
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc8_" goto Skip_VC8
340
+ if NOT "_%VS80COMNTOOLS%_" == "__" (
341
+ set "BOOST_JAM_TOOLSET_ROOT=%VS80COMNTOOLS%..\..\VC\"
342
+ )
343
+ if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
344
+ if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
345
+ if "_%VCINSTALLDIR%_" == "__" (
346
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
347
+ ) )
348
+ set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
349
+ set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
350
+ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
351
+ set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
352
+ set "_known_=1"
353
+ :Skip_VC8
354
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc9_" goto Skip_VC9
355
+ if NOT "_%VS90COMNTOOLS%_" == "__" (
356
+ set "BOOST_JAM_TOOLSET_ROOT=%VS90COMNTOOLS%..\..\VC\"
357
+ )
358
+ if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
359
+ if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
360
+ if "_%VCINSTALLDIR%_" == "__" (
361
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
362
+ ) )
363
+ set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
364
+ set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
365
+ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
366
+ set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
367
+ set "_known_=1"
368
+ :Skip_VC9
369
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc10_" goto Skip_VC10
370
+ if NOT "_%VS100COMNTOOLS%_" == "__" (
371
+ set "BOOST_JAM_TOOLSET_ROOT=%VS100COMNTOOLS%..\..\VC\"
372
+ )
373
+ if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
374
+ if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
375
+ if "_%VCINSTALLDIR%_" == "__" (
376
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
377
+ ) )
378
+ set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
379
+ set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
380
+ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
381
+ set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
382
+ set "_known_=1"
383
+ :Skip_VC10
384
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc11_" goto Skip_VC11
385
+ if NOT "_%VS110COMNTOOLS%_" == "__" (
386
+ set "BOOST_JAM_TOOLSET_ROOT=%VS110COMNTOOLS%..\..\VC\"
387
+ )
388
+ if "_%VCINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%VCVARSALL.BAT" %BOOST_JAM_ARGS%
389
+ if NOT "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
390
+ if "_%VCINSTALLDIR%_" == "__" (
391
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
392
+ ) )
393
+ set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib"
394
+ set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
395
+ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
396
+ set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
397
+ set "_known_=1"
398
+ :Skip_VC11
399
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_borland_" goto Skip_BORLAND
400
+ if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
401
+ call :Test_Path bcc32.exe )
402
+ if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
403
+ if not errorlevel 1 (
404
+ set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
405
+ ) )
406
+ if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
407
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%Bin;%PATH%"
408
+ )
409
+ set "BOOST_JAM_CC=bcc32 -WC -w- -q -I%BOOST_JAM_TOOLSET_ROOT%Include -L%BOOST_JAM_TOOLSET_ROOT%Lib /DNT -nbootstrap"
410
+ set "BOOST_JAM_OPT_JAM=-ejam0"
411
+ set "BOOST_JAM_OPT_MKJAMBASE=-emkjambasejam0"
412
+ set "BOOST_JAM_OPT_YYACC=-eyyacc0"
413
+ set "_known_=1"
414
+ :Skip_BORLAND
415
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_como_" goto Skip_COMO
416
+ set "BOOST_JAM_CC=como -DNT"
417
+ set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
418
+ set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
419
+ set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
420
+ set "_known_=1"
421
+ :Skip_COMO
422
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc_" goto Skip_GCC
423
+ set "BOOST_JAM_CC=gcc -DNT"
424
+ set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
425
+ set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
426
+ set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
427
+ set "_known_=1"
428
+ :Skip_GCC
429
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc-nocygwin_" goto Skip_GCC_NOCYGWIN
430
+ set "BOOST_JAM_CC=gcc -DNT -mno-cygwin"
431
+ set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
432
+ set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
433
+ set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
434
+ set "_known_=1"
435
+ :Skip_GCC_NOCYGWIN
436
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_intel-win32_" goto Skip_INTEL_WIN32
437
+ set "BOOST_JAM_CC=icl -DNT /nologo kernel32.lib advapi32.lib user32.lib"
438
+ set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
439
+ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
440
+ set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
441
+ set "_known_=1"
442
+ :Skip_INTEL_WIN32
443
+ if NOT "_%BOOST_JAM_TOOLSET%_" == "_mingw_" goto Skip_MINGW
444
+ if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
445
+ set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
446
+ )
447
+ set "BOOST_JAM_CC=gcc -DNT"
448
+ set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
449
+ set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
450
+ set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
451
+ set "_known_=1"
452
+ :Skip_MINGW
453
+ call :Clear_Error
454
+ if "_%_known_%_" == "__" (
455
+ call :Error_Print "Unknown toolset: %BOOST_JAM_TOOLSET%"
456
+ )
457
+ if errorlevel 1 goto Finish
458
+
459
+ echo ###
460
+ echo ### Using '%BOOST_JAM_TOOLSET%' toolset.
461
+ echo ###
462
+
463
+ set YYACC_SOURCES=yyacc.c
464
+ set MKJAMBASE_SOURCES=mkjambase.c
465
+ set BJAM_SOURCES=
466
+ set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c constants.c debug.c
467
+ set BJAM_SOURCES=%BJAM_SOURCES% execcmd.c execnt.c filent.c frames.c function.c
468
+ set BJAM_SOURCES=%BJAM_SOURCES% glob.c hash.c hdrmacro.c headers.c jam.c
469
+ set BJAM_SOURCES=%BJAM_SOURCES% jambase.c jamgram.c lists.c make.c make1.c
470
+ set BJAM_SOURCES=%BJAM_SOURCES% object.c option.c output.c parse.c pathnt.c
471
+ set BJAM_SOURCES=%BJAM_SOURCES% pathsys.c regexp.c rules.c scan.c search.c
472
+ set BJAM_SOURCES=%BJAM_SOURCES% subst.c timestamp.c variable.c modules.c
473
+ set BJAM_SOURCES=%BJAM_SOURCES% strings.c filesys.c builtins.c md5.c class.c
474
+ set BJAM_SOURCES=%BJAM_SOURCES% cwd.c w32_getreg.c native.c modules/set.c
475
+ set BJAM_SOURCES=%BJAM_SOURCES% modules/path.c modules/regex.c
476
+ set BJAM_SOURCES=%BJAM_SOURCES% modules/property-set.c modules/sequence.c
477
+ set BJAM_SOURCES=%BJAM_SOURCES% modules/order.c
478
+
479
+ set BJAM_UPDATE=
480
+ :Check_Update
481
+ call :Test_Empty %1
482
+ if not errorlevel 1 goto Check_Update_End
483
+ call :Clear_Error
484
+ setlocal
485
+ set test=%1
486
+ set test=###%test%###
487
+ set test=%test:"###=%
488
+ set test=%test:###"=%
489
+ set test=%test:###=%
490
+ if "%test%" == "--update" goto Found_Update
491
+ endlocal
492
+ shift
493
+ if not "_%BJAM_UPDATE%_" == "_update_" goto Check_Update
494
+ :Found_Update
495
+ endlocal
496
+ set BJAM_UPDATE=update
497
+ :Check_Update_End
498
+ if "_%BJAM_UPDATE%_" == "_update_" (
499
+ if not exist ".\bootstrap\jam0.exe" (
500
+ set BJAM_UPDATE=
501
+ )
502
+ )
503
+
504
+ @echo ON
505
+ @if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Bootstrap
506
+ if exist bootstrap rd /S /Q bootstrap
507
+ md bootstrap
508
+ @if not exist jamgram.y goto Bootstrap_GrammarPrep
509
+ @if not exist jamgramtab.h goto Bootstrap_GrammarPrep
510
+ @goto Skip_GrammarPrep
511
+ :Bootstrap_GrammarPrep
512
+ %BOOST_JAM_CC% %BOOST_JAM_OPT_YYACC% %YYACC_SOURCES%
513
+ @if not exist ".\bootstrap\yyacc0.exe" goto Skip_GrammarPrep
514
+ .\bootstrap\yyacc0 jamgram.y jamgramtab.h jamgram.yy
515
+ :Skip_GrammarPrep
516
+ @if not exist jamgram.c goto Bootstrap_GrammarBuild
517
+ @if not exist jamgram.h goto Bootstrap_GrammarBuild
518
+ @goto Skip_GrammarBuild
519
+ :Bootstrap_GrammarBuild
520
+ @echo OFF
521
+ if "_%YACC%_" == "__" (
522
+ call :Guess_Yacc
523
+ )
524
+ if errorlevel 1 goto Finish
525
+ @echo ON
526
+ %YACC% jamgram.y
527
+ @if errorlevel 1 goto Finish
528
+ del /f jamgram.c
529
+ rename y.tab.c jamgram.c
530
+ del /f jamgram.h
531
+ rename y.tab.h jamgram.h
532
+ :Skip_GrammarBuild
533
+ @echo ON
534
+ @if exist jambase.c goto Skip_Jambase
535
+ %BOOST_JAM_CC% %BOOST_JAM_OPT_MKJAMBASE% %MKJAMBASE_SOURCES%
536
+ @if not exist ".\bootstrap\mkjambase0.exe" goto Skip_Jambase
537
+ .\bootstrap\mkjambase0 jambase.c Jambase
538
+ :Skip_Jambase
539
+ %BOOST_JAM_CC% %BOOST_JAM_OPT_JAM% %BJAM_SOURCES%
540
+ :Skip_Bootstrap
541
+ @if not exist ".\bootstrap\jam0.exe" goto Skip_Jam
542
+ @set args=%*
543
+ @echo OFF
544
+ :Set_Args
545
+ setlocal
546
+ call :Test_Empty %args%
547
+ if not errorlevel 1 goto Set_Args_End
548
+ set test=###%args:~0,2%###
549
+ set test=%test:"###=%
550
+ set test=%test:###"=%
551
+ set test=%test:###=%
552
+ set test=%test:~0,1%
553
+ if "-" == "%test%" goto Set_Args_End
554
+ endlocal
555
+ set args=%args:~1%
556
+ goto Set_Args
557
+ :Set_Args_End
558
+ @echo ON
559
+ @if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Clean
560
+ .\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %args% clean
561
+ :Skip_Clean
562
+ .\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %args%
563
+ :Skip_Jam
564
+
565
+ :Finish
mosesdecoder/jam-files/engine/builtins.c ADDED
@@ -0,0 +1,2354 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ #include "jam.h"
8
+ #include "builtins.h"
9
+
10
+ #include "compile.h"
11
+ #include "constants.h"
12
+ #include "cwd.h"
13
+ #include "filesys.h"
14
+ #include "frames.h"
15
+ #include "hash.h"
16
+ #include "hdrmacro.h"
17
+ #include "lists.h"
18
+ #include "make.h"
19
+ #include "md5.h"
20
+ #include "native.h"
21
+ #include "object.h"
22
+ #include "parse.h"
23
+ #include "pathsys.h"
24
+ #include "rules.h"
25
+ #include "strings.h"
26
+ #include "subst.h"
27
+ #include "timestamp.h"
28
+ #include "variable.h"
29
+
30
+ #include <ctype.h>
31
+
32
+ #if defined(USE_EXECUNIX)
33
+ # include <sys/types.h>
34
+ # include <sys/wait.h>
35
+ #else
36
+ /*
37
+ * NT does not have wait() and associated macros and uses the system() return
38
+ * value instead. Status code group are documented at:
39
+ * http://msdn.microsoft.com/en-gb/library/ff565436.aspx
40
+ */
41
+ # define WIFEXITED(w) (((w) & 0XFFFFFF00) == 0)
42
+ # define WEXITSTATUS(w)(w)
43
+ #endif
44
+
45
+ /*
46
+ * builtins.c - builtin jam rules
47
+ *
48
+ * External routines:
49
+ * load_builtins() - define builtin rules
50
+ * unknown_rule() - reports an unknown rule occurrence to the
51
+ * user and exits
52
+ *
53
+ * Internal routines:
54
+ * append_if_exists() - if file exists, append it to the list
55
+ * builtin_calc() - CALC rule
56
+ * builtin_delete_module() - DELETE_MODULE ( MODULE ? )
57
+ * builtin_depends() - DEPENDS/INCLUDES rule
58
+ * builtin_echo() - ECHO rule
59
+ * builtin_exit() - EXIT rule
60
+ * builtin_export() - EXPORT ( MODULE ? : RULES * )
61
+ * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
62
+ * builtin_glob() - GLOB rule
63
+ * builtin_glob_recursive() - ???
64
+ * builtin_hdrmacro() - ???
65
+ * builtin_import() - IMPORT rule
66
+ * builtin_match() - MATCH rule, regexp matching
67
+ * builtin_rebuilds() - REBUILDS rule
68
+ * builtin_rulenames() - RULENAMES ( MODULE ? )
69
+ * builtin_split_by_characters() - splits the given string into tokens
70
+ * builtin_varnames() - VARNAMES ( MODULE ? )
71
+ * get_source_line() - get a frame's file and line number
72
+ * information
73
+ */
74
+
75
+
76
+ /*
77
+ * compile_builtin() - define builtin rules
78
+ */
79
+
80
+ #define P0 (PARSE *)0
81
+ #define C0 (OBJECT *)0
82
+
83
+ #if defined( OS_NT ) || defined( OS_CYGWIN )
84
+ LIST * builtin_system_registry ( FRAME *, int );
85
+ LIST * builtin_system_registry_names( FRAME *, int );
86
+ #endif
87
+
88
+ int glob( char const * s, char const * c );
89
+
90
+ void backtrace ( FRAME * );
91
+ void backtrace_line ( FRAME * );
92
+ void print_source_line( FRAME * );
93
+
94
+
95
+ RULE * bind_builtin( char const * name_, LIST * (* f)( FRAME *, int flags ),
96
+ int flags, char const * * args )
97
+ {
98
+ FUNCTION * func;
99
+ RULE * result;
100
+ OBJECT * name = object_new( name_ );
101
+
102
+ func = function_builtin( f, flags, args );
103
+
104
+ result = new_rule_body( root_module(), name, func, 1 );
105
+
106
+ function_free( func );
107
+
108
+ object_free( name );
109
+
110
+ return result;
111
+ }
112
+
113
+
114
+ RULE * duplicate_rule( char const * name_, RULE * other )
115
+ {
116
+ OBJECT * name = object_new( name_ );
117
+ RULE * result = import_rule( other, root_module(), name );
118
+ object_free( name );
119
+ return result;
120
+ }
121
+
122
+
123
+ /*
124
+ * load_builtins() - define builtin rules
125
+ */
126
+
127
+ void load_builtins()
128
+ {
129
+ duplicate_rule( "Always",
130
+ bind_builtin( "ALWAYS",
131
+ builtin_flags, T_FLAG_TOUCHED, 0 ) );
132
+
133
+ duplicate_rule( "Depends",
134
+ bind_builtin( "DEPENDS",
135
+ builtin_depends, 0, 0 ) );
136
+
137
+ duplicate_rule( "echo",
138
+ duplicate_rule( "Echo",
139
+ bind_builtin( "ECHO",
140
+ builtin_echo, 0, 0 ) ) );
141
+
142
+ {
143
+ char const * args[] = { "message", "*", ":", "result-value", "?", 0 };
144
+ duplicate_rule( "exit",
145
+ duplicate_rule( "Exit",
146
+ bind_builtin( "EXIT",
147
+ builtin_exit, 0, args ) ) );
148
+ }
149
+
150
+ {
151
+ char const * args[] = { "directories", "*", ":", "patterns", "*", ":",
152
+ "case-insensitive", "?", 0 };
153
+ duplicate_rule( "Glob",
154
+ bind_builtin( "GLOB", builtin_glob, 0, args ) );
155
+ }
156
+
157
+ {
158
+ char const * args[] = { "patterns", "*", 0 };
159
+ bind_builtin( "GLOB-RECURSIVELY",
160
+ builtin_glob_recursive, 0, args );
161
+ }
162
+
163
+ duplicate_rule( "Includes",
164
+ bind_builtin( "INCLUDES",
165
+ builtin_depends, 1, 0 ) );
166
+
167
+ {
168
+ char const * args[] = { "targets", "*", ":", "targets-to-rebuild", "*",
169
+ 0 };
170
+ bind_builtin( "REBUILDS",
171
+ builtin_rebuilds, 0, args );
172
+ }
173
+
174
+ duplicate_rule( "Leaves",
175
+ bind_builtin( "LEAVES",
176
+ builtin_flags, T_FLAG_LEAVES, 0 ) );
177
+
178
+ duplicate_rule( "Match",
179
+ bind_builtin( "MATCH",
180
+ builtin_match, 0, 0 ) );
181
+
182
+ {
183
+ char const * args[] = { "string", ":", "delimiters", 0 };
184
+ bind_builtin( "SPLIT_BY_CHARACTERS",
185
+ builtin_split_by_characters, 0, args );
186
+ }
187
+
188
+ duplicate_rule( "NoCare",
189
+ bind_builtin( "NOCARE",
190
+ builtin_flags, T_FLAG_NOCARE, 0 ) );
191
+
192
+ duplicate_rule( "NOTIME",
193
+ duplicate_rule( "NotFile",
194
+ bind_builtin( "NOTFILE",
195
+ builtin_flags, T_FLAG_NOTFILE, 0 ) ) );
196
+
197
+ duplicate_rule( "NoUpdate",
198
+ bind_builtin( "NOUPDATE",
199
+ builtin_flags, T_FLAG_NOUPDATE, 0 ) );
200
+
201
+ duplicate_rule( "Temporary",
202
+ bind_builtin( "TEMPORARY",
203
+ builtin_flags, T_FLAG_TEMP, 0 ) );
204
+
205
+ bind_builtin( "ISFILE",
206
+ builtin_flags, T_FLAG_ISFILE, 0 );
207
+
208
+ duplicate_rule( "HdrMacro",
209
+ bind_builtin( "HDRMACRO",
210
+ builtin_hdrmacro, 0, 0 ) );
211
+
212
+ /* FAIL_EXPECTED is used to indicate that the result of a target build
213
+ * action should be inverted (ok <=> fail) this can be useful when
214
+ * performing test runs from Jamfiles.
215
+ */
216
+ bind_builtin( "FAIL_EXPECTED",
217
+ builtin_flags, T_FLAG_FAIL_EXPECTED, 0 );
218
+
219
+ bind_builtin( "RMOLD",
220
+ builtin_flags, T_FLAG_RMOLD, 0 );
221
+
222
+ {
223
+ char const * args[] = { "targets", "*", 0 };
224
+ bind_builtin( "UPDATE",
225
+ builtin_update, 0, args );
226
+ }
227
+
228
+ {
229
+ char const * args[] = { "targets", "*",
230
+ ":", "log", "?",
231
+ ":", "ignore-minus-n", "?",
232
+ ":", "ignore-minus-q", "?", 0 };
233
+ bind_builtin( "UPDATE_NOW",
234
+ builtin_update_now, 0, args );
235
+ }
236
+
237
+ {
238
+ char const * args[] = { "string", "pattern", "replacements", "+", 0 };
239
+ duplicate_rule( "subst",
240
+ bind_builtin( "SUBST",
241
+ builtin_subst, 0, args ) );
242
+ }
243
+
244
+ {
245
+ char const * args[] = { "module", "?", 0 };
246
+ bind_builtin( "RULENAMES",
247
+ builtin_rulenames, 0, args );
248
+ }
249
+
250
+ {
251
+ char const * args[] = { "module", "?", 0 };
252
+ bind_builtin( "VARNAMES",
253
+ builtin_varnames, 0, args );
254
+ }
255
+
256
+ {
257
+ char const * args[] = { "module", "?", 0 };
258
+ bind_builtin( "DELETE_MODULE",
259
+ builtin_delete_module, 0, args );
260
+ }
261
+
262
+ {
263
+ char const * args[] = { "source_module", "?",
264
+ ":", "source_rules", "*",
265
+ ":", "target_module", "?",
266
+ ":", "target_rules", "*",
267
+ ":", "localize", "?", 0 };
268
+ bind_builtin( "IMPORT",
269
+ builtin_import, 0, args );
270
+ }
271
+
272
+ {
273
+ char const * args[] = { "module", "?", ":", "rules", "*", 0 };
274
+ bind_builtin( "EXPORT",
275
+ builtin_export, 0, args );
276
+ }
277
+
278
+ {
279
+ char const * args[] = { "levels", "?", 0 };
280
+ bind_builtin( "CALLER_MODULE",
281
+ builtin_caller_module, 0, args );
282
+ }
283
+
284
+ {
285
+ char const * args[] = { "levels", "?", 0 };
286
+ bind_builtin( "BACKTRACE",
287
+ builtin_backtrace, 0, args );
288
+ }
289
+
290
+ {
291
+ char const * args[] = { 0 };
292
+ bind_builtin( "PWD",
293
+ builtin_pwd, 0, args );
294
+ }
295
+
296
+ {
297
+ char const * args[] = { "modules_to_import", "+",
298
+ ":", "target_module", "?", 0 };
299
+ bind_builtin( "IMPORT_MODULE",
300
+ builtin_import_module, 0, args );
301
+ }
302
+
303
+ {
304
+ char const * args[] = { "module", "?", 0 };
305
+ bind_builtin( "IMPORTED_MODULES",
306
+ builtin_imported_modules, 0, args );
307
+ }
308
+
309
+ {
310
+ char const * args[] = { "instance_module", ":", "class_module", 0 };
311
+ bind_builtin( "INSTANCE",
312
+ builtin_instance, 0, args );
313
+ }
314
+
315
+ {
316
+ char const * args[] = { "sequence", "*", 0 };
317
+ bind_builtin( "SORT",
318
+ builtin_sort, 0, args );
319
+ }
320
+
321
+ {
322
+ char const * args[] = { "path_parts", "*", 0 };
323
+ bind_builtin( "NORMALIZE_PATH",
324
+ builtin_normalize_path, 0, args );
325
+ }
326
+
327
+ {
328
+ char const * args[] = { "args", "*", 0 };
329
+ bind_builtin( "CALC",
330
+ builtin_calc, 0, args );
331
+ }
332
+
333
+ {
334
+ char const * args[] = { "module", ":", "rule", 0 };
335
+ bind_builtin( "NATIVE_RULE",
336
+ builtin_native_rule, 0, args );
337
+ }
338
+
339
+ {
340
+ char const * args[] = { "module", ":", "rule", ":", "version", 0 };
341
+ bind_builtin( "HAS_NATIVE_RULE",
342
+ builtin_has_native_rule, 0, args );
343
+ }
344
+
345
+ {
346
+ char const * args[] = { "module", "*", 0 };
347
+ bind_builtin( "USER_MODULE",
348
+ builtin_user_module, 0, args );
349
+ }
350
+
351
+ {
352
+ char const * args[] = { 0 };
353
+ bind_builtin( "NEAREST_USER_LOCATION",
354
+ builtin_nearest_user_location, 0, args );
355
+ }
356
+
357
+ {
358
+ char const * args[] = { "file", 0 };
359
+ bind_builtin( "CHECK_IF_FILE",
360
+ builtin_check_if_file, 0, args );
361
+ }
362
+
363
+ #ifdef HAVE_PYTHON
364
+ {
365
+ char const * args[] = { "python-module",
366
+ ":", "function",
367
+ ":", "jam-module",
368
+ ":", "rule-name", 0 };
369
+ bind_builtin( "PYTHON_IMPORT_RULE",
370
+ builtin_python_import_rule, 0, args );
371
+ }
372
+ #endif
373
+
374
+ # if defined( OS_NT ) || defined( OS_CYGWIN )
375
+ {
376
+ char const * args[] = { "key_path", ":", "data", "?", 0 };
377
+ bind_builtin( "W32_GETREG",
378
+ builtin_system_registry, 0, args );
379
+ }
380
+
381
+ {
382
+ char const * args[] = { "key_path", ":", "result-type", 0 };
383
+ bind_builtin( "W32_GETREGNAMES",
384
+ builtin_system_registry_names, 0, args );
385
+ }
386
+ # endif
387
+
388
+ {
389
+ char const * args[] = { "command", ":", "*", 0 };
390
+ duplicate_rule( "SHELL",
391
+ bind_builtin( "COMMAND",
392
+ builtin_shell, 0, args ) );
393
+ }
394
+
395
+ {
396
+ char const * args[] = { "string", 0 };
397
+ bind_builtin( "MD5",
398
+ builtin_md5, 0, args );
399
+ }
400
+
401
+ {
402
+ char const * args[] = { "name", ":", "mode", 0 };
403
+ bind_builtin( "FILE_OPEN",
404
+ builtin_file_open, 0, args );
405
+ }
406
+
407
+ {
408
+ char const * args[] = { "string", ":", "width", 0 };
409
+ bind_builtin( "PAD",
410
+ builtin_pad, 0, args );
411
+ }
412
+
413
+ {
414
+ char const * args[] = { "targets", "*", 0 };
415
+ bind_builtin( "PRECIOUS",
416
+ builtin_precious, 0, args );
417
+ }
418
+
419
+ {
420
+ char const * args [] = { 0 };
421
+ bind_builtin( "SELF_PATH", builtin_self_path, 0, args );
422
+ }
423
+
424
+ {
425
+ char const * args [] = { "path", 0 };
426
+ bind_builtin( "MAKEDIR", builtin_makedir, 0, args );
427
+ }
428
+
429
+ /* Initialize builtin modules. */
430
+ init_set();
431
+ init_path();
432
+ init_regex();
433
+ init_property_set();
434
+ init_sequence();
435
+ init_order();
436
+ }
437
+
438
+
439
+ /*
440
+ * builtin_calc() - CALC rule
441
+ *
442
+ * Performs simple mathematical operations on two arguments.
443
+ */
444
+
445
+ LIST * builtin_calc( FRAME * frame, int flags )
446
+ {
447
+ LIST * arg = lol_get( frame->args, 0 );
448
+
449
+ LIST * result = L0;
450
+ long lhs_value;
451
+ long rhs_value;
452
+ long result_value;
453
+ char buffer[ 16 ];
454
+ char const * lhs;
455
+ char const * op;
456
+ char const * rhs;
457
+ LISTITER iter = list_begin( arg );
458
+ LISTITER const end = list_end( arg );
459
+
460
+ if ( iter == end ) return L0;
461
+ lhs = object_str( list_item( iter ) );
462
+
463
+ iter = list_next( iter );
464
+ if ( iter == end ) return L0;
465
+ op = object_str( list_item( iter ) );
466
+
467
+ iter = list_next( iter );
468
+ if ( iter == end ) return L0;
469
+ rhs = object_str( list_item( iter ) );
470
+
471
+ lhs_value = atoi( lhs );
472
+ rhs_value = atoi( rhs );
473
+
474
+ if ( !strcmp( "+", op ) )
475
+ result_value = lhs_value + rhs_value;
476
+ else if ( !strcmp( "-", op ) )
477
+ result_value = lhs_value - rhs_value;
478
+ else
479
+ return L0;
480
+
481
+ sprintf( buffer, "%ld", result_value );
482
+ result = list_push_back( result, object_new( buffer ) );
483
+ return result;
484
+ }
485
+
486
+
487
+ /*
488
+ * builtin_depends() - DEPENDS/INCLUDES rule
489
+ *
490
+ * The DEPENDS/INCLUDES builtin rule appends each of the listed sources on the
491
+ * dependency/includes list of each of the listed targets. It binds both the
492
+ * targets and sources as TARGETs.
493
+ */
494
+
495
+ LIST * builtin_depends( FRAME * frame, int flags )
496
+ {
497
+ LIST * const targets = lol_get( frame->args, 0 );
498
+ LIST * const sources = lol_get( frame->args, 1 );
499
+
500
+ LISTITER iter = list_begin( targets );
501
+ LISTITER end = list_end( targets );
502
+ for ( ; iter != end; iter = list_next( iter ) )
503
+ {
504
+ TARGET * const t = bindtarget( list_item( iter ) );
505
+
506
+ if ( flags )
507
+ target_include_many( t, sources );
508
+ else
509
+ t->depends = targetlist( t->depends, sources );
510
+ }
511
+
512
+ /* Enter reverse links */
513
+ iter = list_begin( sources );
514
+ end = list_end( sources );
515
+ for ( ; iter != end; iter = list_next( iter ) )
516
+ {
517
+ TARGET * const s = bindtarget( list_item( iter ) );
518
+ if ( flags )
519
+ {
520
+ LISTITER t_iter = list_begin( targets );
521
+ LISTITER const t_end = list_end( targets );
522
+ for ( ; t_iter != t_end; t_iter = list_next( t_iter ) )
523
+ s->dependants = targetentry( s->dependants, bindtarget(
524
+ list_item( t_iter ) )->includes );
525
+ }
526
+ else
527
+ s->dependants = targetlist( s->dependants, targets );
528
+ }
529
+
530
+ return L0;
531
+ }
532
+
533
+
534
+ /*
535
+ * builtin_rebuilds() - REBUILDS rule
536
+ *
537
+ * Appends each of the rebuild-targets listed in its second argument to the
538
+ * rebuilds list for each of the targets listed in its first argument.
539
+ */
540
+
541
+ LIST * builtin_rebuilds( FRAME * frame, int flags )
542
+ {
543
+ LIST * targets = lol_get( frame->args, 0 );
544
+ LIST * rebuilds = lol_get( frame->args, 1 );
545
+ LISTITER iter = list_begin( targets );
546
+ LISTITER const end = list_end( targets );
547
+ for ( ; iter != end; iter = list_next( iter ) )
548
+ {
549
+ TARGET * const t = bindtarget( list_item( iter ) );
550
+ t->rebuilds = targetlist( t->rebuilds, rebuilds );
551
+ }
552
+ return L0;
553
+ }
554
+
555
+
556
+ /*
557
+ * builtin_echo() - ECHO rule
558
+ *
559
+ * Echoes the targets to the user. No other actions are taken.
560
+ */
561
+
562
+ LIST * builtin_echo( FRAME * frame, int flags )
563
+ {
564
+ list_print( lol_get( frame->args, 0 ) );
565
+ printf( "\n" );
566
+ fflush( stdout );
567
+ return L0;
568
+ }
569
+
570
+
571
+ /*
572
+ * builtin_exit() - EXIT rule
573
+ *
574
+ * Echoes the targets to the user and exits the program with a failure status.
575
+ */
576
+
577
+ LIST * builtin_exit( FRAME * frame, int flags )
578
+ {
579
+ LIST * const code = lol_get( frame->args, 1 );
580
+ list_print( lol_get( frame->args, 0 ) );
581
+ printf( "\n" );
582
+ if ( !list_empty( code ) )
583
+ exit( atoi( object_str( list_front( code ) ) ) );
584
+ else
585
+ exit( EXITBAD ); /* yeech */
586
+ return L0;
587
+ }
588
+
589
+
590
+ /*
591
+ * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule
592
+ *
593
+ * Marks the target with the appropriate flag, for use by make0(). It binds each
594
+ * target as a TARGET.
595
+ */
596
+
597
+ LIST * builtin_flags( FRAME * frame, int flags )
598
+ {
599
+ LIST * const targets = lol_get( frame->args, 0 );
600
+ LISTITER iter = list_begin( targets );
601
+ LISTITER const end = list_end( targets );
602
+ for ( ; iter != end; iter = list_next( iter ) )
603
+ bindtarget( list_item( iter ) )->flags |= flags;
604
+ return L0;
605
+ }
606
+
607
+
608
+ /*
609
+ * builtin_glob() - GLOB rule
610
+ */
611
+
612
+ struct globbing
613
+ {
614
+ LIST * patterns;
615
+ LIST * results;
616
+ LIST * case_insensitive;
617
+ };
618
+
619
+
620
+ static void downcase_inplace( char * p )
621
+ {
622
+ for ( ; *p; ++p )
623
+ *p = tolower( *p );
624
+ }
625
+
626
+
627
+ static void builtin_glob_back( void * closure, OBJECT * file, int status,
628
+ timestamp const * const time )
629
+ {
630
+ PROFILE_ENTER( BUILTIN_GLOB_BACK );
631
+
632
+ struct globbing * const globbing = (struct globbing *)closure;
633
+ PATHNAME f;
634
+ string buf[ 1 ];
635
+ LISTITER iter;
636
+ LISTITER end;
637
+
638
+ /* Null out directory for matching. We wish we had file_dirscan() pass up a
639
+ * PATHNAME.
640
+ */
641
+ path_parse( object_str( file ), &f );
642
+ f.f_dir.len = 0;
643
+
644
+ /* For globbing, we unconditionally ignore current and parent directory
645
+ * items. Since these items always exist, there is no reason why caller of
646
+ * GLOB would want to see them. We could also change file_dirscan(), but
647
+ * then paths with embedded "." and ".." would not work anywhere.
648
+ */
649
+ if ( !strcmp( f.f_base.ptr, "." ) || !strcmp( f.f_base.ptr, ".." ) )
650
+ {
651
+ PROFILE_EXIT( BUILTIN_GLOB_BACK );
652
+ return;
653
+ }
654
+
655
+ string_new( buf );
656
+ path_build( &f, buf );
657
+
658
+ if ( globbing->case_insensitive )
659
+ downcase_inplace( buf->value );
660
+
661
+ iter = list_begin( globbing->patterns );
662
+ end = list_end( globbing->patterns );
663
+ for ( ; iter != end; iter = list_next( iter ) )
664
+ {
665
+ if ( !glob( object_str( list_item( iter ) ), buf->value ) )
666
+ {
667
+ globbing->results = list_push_back( globbing->results, object_copy(
668
+ file ) );
669
+ break;
670
+ }
671
+ }
672
+
673
+ string_free( buf );
674
+
675
+ PROFILE_EXIT( BUILTIN_GLOB_BACK );
676
+ }
677
+
678
+
679
+ static LIST * downcase_list( LIST * in )
680
+ {
681
+ LIST * result = L0;
682
+ LISTITER iter = list_begin( in );
683
+ LISTITER const end = list_end( in );
684
+
685
+ string s[ 1 ];
686
+ string_new( s );
687
+
688
+ for ( ; iter != end; iter = list_next( iter ) )
689
+ {
690
+ string_append( s, object_str( list_item( iter ) ) );
691
+ downcase_inplace( s->value );
692
+ result = list_push_back( result, object_new( s->value ) );
693
+ string_truncate( s, 0 );
694
+ }
695
+
696
+ string_free( s );
697
+ return result;
698
+ }
699
+
700
+
701
+ LIST * builtin_glob( FRAME * frame, int flags )
702
+ {
703
+ LIST * const l = lol_get( frame->args, 0 );
704
+ LIST * const r = lol_get( frame->args, 1 );
705
+
706
+ LISTITER iter;
707
+ LISTITER end;
708
+ struct globbing globbing;
709
+
710
+ globbing.results = L0;
711
+ globbing.patterns = r;
712
+
713
+ globbing.case_insensitive =
714
+ # if defined( OS_NT ) || defined( OS_CYGWIN )
715
+ l; /* Always case-insensitive if any files can be found. */
716
+ # else
717
+ lol_get( frame->args, 2 );
718
+ # endif
719
+
720
+ if ( globbing.case_insensitive )
721
+ globbing.patterns = downcase_list( r );
722
+
723
+ iter = list_begin( l );
724
+ end = list_end( l );
725
+ for ( ; iter != end; iter = list_next( iter ) )
726
+ file_dirscan( list_item( iter ), builtin_glob_back, &globbing );
727
+
728
+ if ( globbing.case_insensitive )
729
+ list_free( globbing.patterns );
730
+
731
+ return globbing.results;
732
+ }
733
+
734
+
735
+ static int has_wildcards( char const * const str )
736
+ {
737
+ return str[ strcspn( str, "[]*?" ) ] ? 1 : 0;
738
+ }
739
+
740
+
741
+ /*
742
+ * append_if_exists() - if file exists, append it to the list
743
+ */
744
+
745
+ static LIST * append_if_exists( LIST * list, OBJECT * file )
746
+ {
747
+ return file_query( file )
748
+ ? list_push_back( list, object_copy( file ) )
749
+ : list ;
750
+ }
751
+
752
+
753
+ LIST * glob1( OBJECT * dirname, OBJECT * pattern )
754
+ {
755
+ LIST * const plist = list_new( object_copy( pattern ) );
756
+ struct globbing globbing;
757
+
758
+ globbing.results = L0;
759
+ globbing.patterns = plist;
760
+
761
+ globbing.case_insensitive
762
+ # if defined( OS_NT ) || defined( OS_CYGWIN )
763
+ = plist; /* always case-insensitive if any files can be found */
764
+ # else
765
+ = L0;
766
+ # endif
767
+
768
+ if ( globbing.case_insensitive )
769
+ globbing.patterns = downcase_list( plist );
770
+
771
+ file_dirscan( dirname, builtin_glob_back, &globbing );
772
+
773
+ if ( globbing.case_insensitive )
774
+ list_free( globbing.patterns );
775
+
776
+ list_free( plist );
777
+
778
+ return globbing.results;
779
+ }
780
+
781
+
782
+ LIST * glob_recursive( char const * pattern )
783
+ {
784
+ LIST * result = L0;
785
+
786
+ /* Check if there's metacharacters in pattern */
787
+ if ( !has_wildcards( pattern ) )
788
+ {
789
+ /* No metacharacters. Check if the path exists. */
790
+ OBJECT * const p = object_new( pattern );
791
+ result = append_if_exists( result, p );
792
+ object_free( p );
793
+ }
794
+ else
795
+ {
796
+ /* Have metacharacters in the pattern. Split into dir/name. */
797
+ PATHNAME path[ 1 ];
798
+ path_parse( pattern, path );
799
+
800
+ if ( path->f_dir.ptr )
801
+ {
802
+ LIST * dirs = L0;
803
+ string dirname[ 1 ];
804
+ string basename[ 1 ];
805
+ string_new( dirname );
806
+ string_new( basename );
807
+
808
+ string_append_range( dirname, path->f_dir.ptr,
809
+ path->f_dir.ptr + path->f_dir.len );
810
+
811
+ path->f_grist.ptr = 0;
812
+ path->f_grist.len = 0;
813
+ path->f_dir.ptr = 0;
814
+ path->f_dir.len = 0;
815
+ path_build( path, basename );
816
+
817
+ dirs = has_wildcards( dirname->value )
818
+ ? glob_recursive( dirname->value )
819
+ : list_push_back( dirs, object_new( dirname->value ) );
820
+
821
+ if ( has_wildcards( basename->value ) )
822
+ {
823
+ OBJECT * const b = object_new( basename->value );
824
+ LISTITER iter = list_begin( dirs );
825
+ LISTITER const end = list_end( dirs );
826
+ for ( ; iter != end; iter = list_next( iter ) )
827
+ result = list_append( result, glob1( list_item( iter ), b )
828
+ );
829
+ object_free( b );
830
+ }
831
+ else
832
+ {
833
+ LISTITER iter = list_begin( dirs );
834
+ LISTITER const end = list_end( dirs );
835
+ string file_string[ 1 ];
836
+ string_new( file_string );
837
+
838
+ /* No wildcard in basename. */
839
+ for ( ; iter != end; iter = list_next( iter ) )
840
+ {
841
+ OBJECT * p;
842
+ path->f_dir.ptr = object_str( list_item( iter ) );
843
+ path->f_dir.len = strlen( object_str( list_item( iter ) ) );
844
+ path_build( path, file_string );
845
+
846
+ p = object_new( file_string->value );
847
+
848
+ result = append_if_exists( result, p );
849
+
850
+ object_free( p );
851
+
852
+ string_truncate( file_string, 0 );
853
+ }
854
+
855
+ string_free( file_string );
856
+ }
857
+
858
+ string_free( dirname );
859
+ string_free( basename );
860
+
861
+ list_free( dirs );
862
+ }
863
+ else
864
+ {
865
+ /* No directory, just a pattern. */
866
+ OBJECT * const p = object_new( pattern );
867
+ result = list_append( result, glob1( constant_dot, p ) );
868
+ object_free( p );
869
+ }
870
+ }
871
+
872
+ return result;
873
+ }
874
+
875
+
876
+ /*
877
+ * builtin_glob_recursive() - ???
878
+ */
879
+
880
+ LIST * builtin_glob_recursive( FRAME * frame, int flags )
881
+ {
882
+ LIST * result = L0;
883
+ LIST * const l = lol_get( frame->args, 0 );
884
+ LISTITER iter = list_begin( l );
885
+ LISTITER const end = list_end( l );
886
+ for ( ; iter != end; iter = list_next( iter ) )
887
+ result = list_append( result, glob_recursive( object_str( list_item(
888
+ iter ) ) ) );
889
+ return result;
890
+ }
891
+
892
+
893
+ /*
894
+ * builtin_match() - MATCH rule, regexp matching
895
+ */
896
+
897
+ LIST * builtin_match( FRAME * frame, int flags )
898
+ {
899
+ LIST * l;
900
+ LIST * r;
901
+ LIST * result = L0;
902
+ LISTITER l_iter;
903
+ LISTITER l_end;
904
+ LISTITER r_iter;
905
+ LISTITER r_end;
906
+
907
+ string buf[ 1 ];
908
+ string_new( buf );
909
+
910
+ /* For each pattern */
911
+
912
+ l = lol_get( frame->args, 0 );
913
+ l_iter = list_begin( l );
914
+ l_end = list_end( l );
915
+ for ( ; l_iter != l_end; l_iter = list_next( l_iter ) )
916
+ {
917
+ /* Result is cached and intentionally never freed. */
918
+ regexp * re = regex_compile( list_item( l_iter ) );
919
+
920
+ /* For each string to match against. */
921
+ r = lol_get( frame->args, 1 );
922
+ r_iter = list_begin( r );
923
+ r_end = list_end( r );
924
+ for ( ; r_iter != r_end; r_iter = list_next( r_iter ) )
925
+ {
926
+ if ( regexec( re, object_str( list_item( r_iter ) ) ) )
927
+ {
928
+ int i;
929
+ int top;
930
+
931
+ /* Find highest parameter */
932
+
933
+ for ( top = NSUBEXP; top-- > 1; )
934
+ if ( re->startp[ top ] )
935
+ break;
936
+
937
+ /* And add all parameters up to highest onto list. */
938
+ /* Must have parameters to have results! */
939
+ for ( i = 1; i <= top; ++i )
940
+ {
941
+ string_append_range( buf, re->startp[ i ], re->endp[ i ] );
942
+ result = list_push_back( result, object_new( buf->value ) );
943
+ string_truncate( buf, 0 );
944
+ }
945
+ }
946
+ }
947
+ }
948
+
949
+ string_free( buf );
950
+ return result;
951
+ }
952
+
953
+
954
+ /*
955
+ * builtin_split_by_characters() - splits the given string into tokens
956
+ */
957
+
958
+ LIST * builtin_split_by_characters( FRAME * frame, int flags )
959
+ {
960
+ LIST * l1 = lol_get( frame->args, 0 );
961
+ LIST * l2 = lol_get( frame->args, 1 );
962
+
963
+ LIST * result = L0;
964
+
965
+ string buf[ 1 ];
966
+
967
+ char const * delimiters = object_str( list_front( l2 ) );
968
+ char * t;
969
+
970
+ string_copy( buf, object_str( list_front( l1 ) ) );
971
+
972
+ t = strtok( buf->value, delimiters );
973
+ while ( t )
974
+ {
975
+ result = list_push_back( result, object_new( t ) );
976
+ t = strtok( NULL, delimiters );
977
+ }
978
+
979
+ string_free( buf );
980
+
981
+ return result;
982
+ }
983
+
984
+
985
+ /*
986
+ * builtin_hdrmacro() - ???
987
+ */
988
+
989
+ LIST * builtin_hdrmacro( FRAME * frame, int flags )
990
+ {
991
+ LIST * const l = lol_get( frame->args, 0 );
992
+ LISTITER iter = list_begin( l );
993
+ LISTITER const end = list_end( l );
994
+
995
+ for ( ; iter != end; iter = list_next( iter ) )
996
+ {
997
+ TARGET * const t = bindtarget( list_item( iter ) );
998
+
999
+ /* Scan file for header filename macro definitions. */
1000
+ if ( DEBUG_HEADER )
1001
+ printf( "scanning '%s' for header file macro definitions\n",
1002
+ object_str( list_item( iter ) ) );
1003
+
1004
+ macro_headers( t );
1005
+ }
1006
+
1007
+ return L0;
1008
+ }
1009
+
1010
+
1011
+ /*
1012
+ * builtin_rulenames() - RULENAMES ( MODULE ? )
1013
+ *
1014
+ * Returns a list of the non-local rule names in the given MODULE. If MODULE is
1015
+ * not supplied, returns the list of rule names in the global module.
1016
+ */
1017
+
1018
+ static void add_rule_name( void * r_, void * result_ )
1019
+ {
1020
+ RULE * const r = (RULE *)r_;
1021
+ LIST * * const result = (LIST * *)result_;
1022
+ if ( r->exported )
1023
+ *result = list_push_back( *result, object_copy( r->name ) );
1024
+ }
1025
+
1026
+
1027
+ LIST * builtin_rulenames( FRAME * frame, int flags )
1028
+ {
1029
+ LIST * arg0 = lol_get( frame->args, 0 );
1030
+ LIST * result = L0;
1031
+ module_t * const source_module = bindmodule( list_empty( arg0 )
1032
+ ? 0
1033
+ : list_front( arg0 ) );
1034
+
1035
+ if ( source_module->rules )
1036
+ hashenumerate( source_module->rules, add_rule_name, &result );
1037
+ return result;
1038
+ }
1039
+
1040
+
1041
+ /*
1042
+ * builtin_varnames() - VARNAMES ( MODULE ? )
1043
+ *
1044
+ * Returns a list of the variable names in the given MODULE. If MODULE is not
1045
+ * supplied, returns the list of variable names in the global module.
1046
+ */
1047
+
1048
+ /* helper function for builtin_varnames(), below. Used with hashenumerate, will
1049
+ * prepend the key of each element to the list
1050
+ */
1051
+ static void add_hash_key( void * np, void * result_ )
1052
+ {
1053
+ LIST * * result = (LIST * *)result_;
1054
+ *result = list_push_back( *result, object_copy( *(OBJECT * *)np ) );
1055
+ }
1056
+
1057
+
1058
+ LIST * builtin_varnames( FRAME * frame, int flags )
1059
+ {
1060
+ LIST * arg0 = lol_get( frame->args, 0 );
1061
+ LIST * result = L0;
1062
+ module_t * source_module = bindmodule( list_empty( arg0 )
1063
+ ? 0
1064
+ : list_front( arg0 ) );
1065
+
1066
+ struct hash * const vars = source_module->variables;
1067
+ if ( vars )
1068
+ hashenumerate( vars, add_hash_key, &result );
1069
+ return result;
1070
+ }
1071
+
1072
+
1073
+ /*
1074
+ * builtin_delete_module() - DELETE_MODULE ( MODULE ? )
1075
+ *
1076
+ * Clears all rules and variables from the given module.
1077
+ */
1078
+
1079
+ LIST * builtin_delete_module( FRAME * frame, int flags )
1080
+ {
1081
+ LIST * const arg0 = lol_get( frame->args, 0 );
1082
+ module_t * const source_module = bindmodule( list_empty( arg0 ) ? 0 :
1083
+ list_front( arg0 ) );
1084
+ delete_module( source_module );
1085
+ return L0;
1086
+ }
1087
+
1088
+
1089
+ /*
1090
+ * unknown_rule() - reports an unknown rule occurrence to the user and exits
1091
+ */
1092
+
1093
+ void unknown_rule( FRAME * frame, char const * key, module_t * module,
1094
+ OBJECT * rule_name )
1095
+ {
1096
+ backtrace_line( frame->prev );
1097
+ if ( key )
1098
+ printf("%s error", key);
1099
+ else
1100
+ printf("ERROR");
1101
+ printf( ": rule \"%s\" unknown in ", object_str( rule_name ) );
1102
+ if ( module->name )
1103
+ printf( "module \"%s\".\n", object_str( module->name ) );
1104
+ else
1105
+ printf( "root module.\n" );
1106
+ backtrace( frame->prev );
1107
+ exit( 1 );
1108
+ }
1109
+
1110
+
1111
+ /*
1112
+ * builtin_import() - IMPORT rule
1113
+ *
1114
+ * IMPORT
1115
+ * (
1116
+ * SOURCE_MODULE ? :
1117
+ * SOURCE_RULES * :
1118
+ * TARGET_MODULE ? :
1119
+ * TARGET_RULES * :
1120
+ * LOCALIZE ?
1121
+ * )
1122
+ *
1123
+ * Imports rules from the SOURCE_MODULE into the TARGET_MODULE as local rules.
1124
+ * If either SOURCE_MODULE or TARGET_MODULE is not supplied, it refers to the
1125
+ * global module. SOURCE_RULES specifies which rules from the SOURCE_MODULE to
1126
+ * import; TARGET_RULES specifies the names to give those rules in
1127
+ * TARGET_MODULE. If SOURCE_RULES contains a name that does not correspond to
1128
+ * a rule in SOURCE_MODULE, or if it contains a different number of items than
1129
+ * TARGET_RULES, an error is issued. If LOCALIZE is specified, the rules will be
1130
+ * executed in TARGET_MODULE, with corresponding access to its module local
1131
+ * variables.
1132
+ */
1133
+
1134
+ LIST * builtin_import( FRAME * frame, int flags )
1135
+ {
1136
+ LIST * source_module_list = lol_get( frame->args, 0 );
1137
+ LIST * source_rules = lol_get( frame->args, 1 );
1138
+ LIST * target_module_list = lol_get( frame->args, 2 );
1139
+ LIST * target_rules = lol_get( frame->args, 3 );
1140
+ LIST * localize = lol_get( frame->args, 4 );
1141
+
1142
+ module_t * target_module = bindmodule( list_empty( target_module_list )
1143
+ ? 0
1144
+ : list_front( target_module_list ) );
1145
+ module_t * source_module = bindmodule( list_empty( source_module_list )
1146
+ ? 0
1147
+ : list_front( source_module_list ) );
1148
+
1149
+ LISTITER source_iter = list_begin( source_rules );
1150
+ LISTITER const source_end = list_end( source_rules );
1151
+ LISTITER target_iter = list_begin( target_rules );
1152
+ LISTITER const target_end = list_end( target_rules );
1153
+
1154
+ for ( ;
1155
+ source_iter != source_end && target_iter != target_end;
1156
+ source_iter = list_next( source_iter ),
1157
+ target_iter = list_next( target_iter ) )
1158
+ {
1159
+ RULE * r;
1160
+ RULE * imported;
1161
+
1162
+ if ( !source_module->rules || !(r = (RULE *)hash_find(
1163
+ source_module->rules, list_item( source_iter ) ) ) )
1164
+ unknown_rule( frame, "IMPORT", source_module, list_item( source_iter
1165
+ ) );
1166
+
1167
+ imported = import_rule( r, target_module, list_item( target_iter ) );
1168
+ if ( !list_empty( localize ) )
1169
+ rule_localize( imported, target_module );
1170
+ /* This rule is really part of some other module. Just refer to it here,
1171
+ * but do not let it out.
1172
+ */
1173
+ imported->exported = 0;
1174
+ }
1175
+
1176
+ if ( source_iter != source_end || target_iter != target_end )
1177
+ {
1178
+ backtrace_line( frame->prev );
1179
+ printf( "import error: length of source and target rule name lists "
1180
+ "don't match!\n" );
1181
+ printf( " source: " );
1182
+ list_print( source_rules );
1183
+ printf( "\n target: " );
1184
+ list_print( target_rules );
1185
+ printf( "\n" );
1186
+ backtrace( frame->prev );
1187
+ exit( 1 );
1188
+ }
1189
+
1190
+ return L0;
1191
+ }
1192
+
1193
+
1194
+ /*
1195
+ * builtin_export() - EXPORT ( MODULE ? : RULES * )
1196
+ *
1197
+ * The EXPORT rule marks RULES from the SOURCE_MODULE as non-local (and thus
1198
+ * exportable). If an element of RULES does not name a rule in MODULE, an error
1199
+ * is issued.
1200
+ */
1201
+
1202
+ LIST * builtin_export( FRAME * frame, int flags )
1203
+ {
1204
+ LIST * const module_list = lol_get( frame->args, 0 );
1205
+ LIST * const rules = lol_get( frame->args, 1 );
1206
+ module_t * const m = bindmodule( list_empty( module_list ) ? 0 : list_front(
1207
+ module_list ) );
1208
+
1209
+ LISTITER iter = list_begin( rules );
1210
+ LISTITER const end = list_end( rules );
1211
+ for ( ; iter != end; iter = list_next( iter ) )
1212
+ {
1213
+ RULE * r;
1214
+ if ( !m->rules || !( r = (RULE *)hash_find( m->rules, list_item( iter )
1215
+ ) ) )
1216
+ unknown_rule( frame, "EXPORT", m, list_item( iter ) );
1217
+ r->exported = 1;
1218
+ }
1219
+ return L0;
1220
+ }
1221
+
1222
+
1223
+ /*
1224
+ * get_source_line() - get a frame's file and line number information
1225
+ *
1226
+ * This is the execution traceback information to be indicated for in debug
1227
+ * output or an error backtrace.
1228
+ */
1229
+
1230
+ static void get_source_line( FRAME * frame, char const * * file, int * line )
1231
+ {
1232
+ if ( frame->file )
1233
+ {
1234
+ char const * f = object_str( frame->file );
1235
+ int l = frame->line;
1236
+ if ( !strcmp( f, "+" ) )
1237
+ {
1238
+ f = "jambase.c";
1239
+ l += 3;
1240
+ }
1241
+ *file = f;
1242
+ *line = l;
1243
+ }
1244
+ else
1245
+ {
1246
+ *file = "(builtin)";
1247
+ *line = -1;
1248
+ }
1249
+ }
1250
+
1251
+
1252
+ void print_source_line( FRAME * frame )
1253
+ {
1254
+ char const * file;
1255
+ int line;
1256
+ get_source_line( frame, &file, &line );
1257
+ if ( line < 0 )
1258
+ printf( "(builtin):" );
1259
+ else
1260
+ printf( "%s:%d:", file, line );
1261
+ }
1262
+
1263
+
1264
+ /*
1265
+ * backtrace_line() - print a single line of error backtrace for the given
1266
+ * frame.
1267
+ */
1268
+
1269
+ void backtrace_line( FRAME * frame )
1270
+ {
1271
+ if ( frame == 0 )
1272
+ {
1273
+ printf( "(no frame):" );
1274
+ }
1275
+ else
1276
+ {
1277
+ print_source_line( frame );
1278
+ printf( " in %s\n", frame->rulename );
1279
+ }
1280
+ }
1281
+
1282
+
1283
+ /*
1284
+ * backtrace() - Print the entire backtrace from the given frame to the Jambase
1285
+ * which invoked it.
1286
+ */
1287
+
1288
+ void backtrace( FRAME * frame )
1289
+ {
1290
+ if ( !frame ) return;
1291
+ while ( ( frame = frame->prev ) )
1292
+ backtrace_line( frame );
1293
+ }
1294
+
1295
+
1296
+ /*
1297
+ * builtin_backtrace() - A Jam version of the backtrace function, taking no
1298
+ * arguments and returning a list of quadruples: FILENAME LINE MODULE. RULENAME
1299
+ * describing each frame. Note that the module-name is always followed by a
1300
+ * period.
1301
+ */
1302
+
1303
+ LIST * builtin_backtrace( FRAME * frame, int flags )
1304
+ {
1305
+ LIST * const levels_arg = lol_get( frame->args, 0 );
1306
+ int levels = list_empty( levels_arg )
1307
+ ? (int)( (unsigned int)(-1) >> 1 )
1308
+ : atoi( object_str( list_front( levels_arg ) ) );
1309
+
1310
+ LIST * result = L0;
1311
+ for ( ; ( frame = frame->prev ) && levels; --levels )
1312
+ {
1313
+ char const * file;
1314
+ int line;
1315
+ char buf[ 32 ];
1316
+ string module_name[ 1 ];
1317
+ get_source_line( frame, &file, &line );
1318
+ sprintf( buf, "%d", line );
1319
+ string_new( module_name );
1320
+ if ( frame->module->name )
1321
+ {
1322
+ string_append( module_name, object_str( frame->module->name ) );
1323
+ string_append( module_name, "." );
1324
+ }
1325
+ result = list_push_back( result, object_new( file ) );
1326
+ result = list_push_back( result, object_new( buf ) );
1327
+ result = list_push_back( result, object_new( module_name->value ) );
1328
+ result = list_push_back( result, object_new( frame->rulename ) );
1329
+ string_free( module_name );
1330
+ }
1331
+ return result;
1332
+ }
1333
+
1334
+
1335
+ /*
1336
+ * builtin_caller_module() - CALLER_MODULE ( levels ? )
1337
+ *
1338
+ * If levels is not supplied, returns the name of the module of the rule which
1339
+ * called the one calling this one. If levels is supplied, it is interpreted as
1340
+ * an integer specifying a number of additional levels of call stack to traverse
1341
+ * in order to locate the module in question. If no such module exists, returns
1342
+ * the empty list. Also returns the empty list when the module in question is
1343
+ * the global module. This rule is needed for implementing module import
1344
+ * behavior.
1345
+ */
1346
+
1347
+ LIST * builtin_caller_module( FRAME * frame, int flags )
1348
+ {
1349
+ LIST * const levels_arg = lol_get( frame->args, 0 );
1350
+ int const levels = list_empty( levels_arg )
1351
+ ? 0
1352
+ : atoi( object_str( list_front( levels_arg ) ) );
1353
+
1354
+ int i;
1355
+ for ( i = 0; ( i < levels + 2 ) && frame->prev; ++i )
1356
+ frame = frame->prev;
1357
+
1358
+ return frame->module == root_module()
1359
+ ? L0
1360
+ : list_new( object_copy( frame->module->name ) );
1361
+ }
1362
+
1363
+
1364
+ /*
1365
+ * Return the current working directory.
1366
+ *
1367
+ * Usage: pwd = [ PWD ] ;
1368
+ */
1369
+
1370
+ LIST * builtin_pwd( FRAME * frame, int flags )
1371
+ {
1372
+ return list_new( object_copy( cwd() ) );
1373
+ }
1374
+
1375
+
1376
+ /*
1377
+ * Adds targets to the list of target that jam will attempt to update.
1378
+ */
1379
+
1380
+ LIST * builtin_update( FRAME * frame, int flags )
1381
+ {
1382
+ LIST * result = list_copy( targets_to_update() );
1383
+ LIST * arg1 = lol_get( frame->args, 0 );
1384
+ LISTITER iter = list_begin( arg1 ), end = list_end( arg1 );
1385
+ clear_targets_to_update();
1386
+ for ( ; iter != end; iter = list_next( iter ) )
1387
+ mark_target_for_updating( object_copy( list_item( iter ) ) );
1388
+ return result;
1389
+ }
1390
+
1391
+ extern int anyhow;
1392
+ int last_update_now_status;
1393
+
1394
+ /* Takes a list of target names and immediately updates them.
1395
+ *
1396
+ * Parameters:
1397
+ * 1. Target list.
1398
+ * 2. Optional file descriptor (converted to a string) for a log file where all
1399
+ * the related build output should be redirected.
1400
+ * 3. If specified, makes the build temporarily disable the -n option, i.e.
1401
+ * forces all needed out-of-date targets to be rebuilt.
1402
+ * 4. If specified, makes the build temporarily disable the -q option, i.e.
1403
+ * forces the build to continue even if one of the targets fails to build.
1404
+ */
1405
+ LIST * builtin_update_now( FRAME * frame, int flags )
1406
+ {
1407
+ LIST * targets = lol_get( frame->args, 0 );
1408
+ LIST * log = lol_get( frame->args, 1 );
1409
+ LIST * force = lol_get( frame->args, 2 );
1410
+ LIST * continue_ = lol_get( frame->args, 3 );
1411
+ int status;
1412
+ int original_stdout = 0;
1413
+ int original_stderr = 0;
1414
+ int original_noexec = 0;
1415
+ int original_quitquick = 0;
1416
+
1417
+ if ( !list_empty( log ) )
1418
+ {
1419
+ /* Temporarily redirect stdout and stderr to the given log file. */
1420
+ int const fd = atoi( object_str( list_front( log ) ) );
1421
+ original_stdout = dup( 0 );
1422
+ original_stderr = dup( 1 );
1423
+ dup2( fd, 0 );
1424
+ dup2( fd, 1 );
1425
+ }
1426
+
1427
+ if ( !list_empty( force ) )
1428
+ {
1429
+ original_noexec = globs.noexec;
1430
+ globs.noexec = 0;
1431
+ }
1432
+
1433
+ if ( !list_empty( continue_ ) )
1434
+ {
1435
+ original_quitquick = globs.quitquick;
1436
+ globs.quitquick = 0;
1437
+ }
1438
+
1439
+ status = make( targets, anyhow );
1440
+
1441
+ if ( !list_empty( force ) )
1442
+ {
1443
+ globs.noexec = original_noexec;
1444
+ }
1445
+
1446
+ if ( !list_empty( continue_ ) )
1447
+ {
1448
+ globs.quitquick = original_quitquick;
1449
+ }
1450
+
1451
+ if ( !list_empty( log ) )
1452
+ {
1453
+ /* Flush whatever stdio might have buffered, while descriptions 0 and 1
1454
+ * still refer to the log file.
1455
+ */
1456
+ fflush( stdout );
1457
+ fflush( stderr );
1458
+ dup2( original_stdout, 0 );
1459
+ dup2( original_stderr, 1 );
1460
+ close( original_stdout );
1461
+ close( original_stderr );
1462
+ }
1463
+
1464
+ last_update_now_status = status;
1465
+
1466
+ return status ? L0 : list_new( object_copy( constant_ok ) );
1467
+ }
1468
+
1469
+
1470
+ LIST * builtin_import_module( FRAME * frame, int flags )
1471
+ {
1472
+ LIST * const arg1 = lol_get( frame->args, 0 );
1473
+ LIST * const arg2 = lol_get( frame->args, 1 );
1474
+ module_t * const m = list_empty( arg2 )
1475
+ ? root_module()
1476
+ : bindmodule( list_front( arg2 ) );
1477
+ import_module( arg1, m );
1478
+ return L0;
1479
+ }
1480
+
1481
+
1482
+ LIST * builtin_imported_modules( FRAME * frame, int flags )
1483
+ {
1484
+ LIST * const arg0 = lol_get( frame->args, 0 );
1485
+ OBJECT * const module = list_empty( arg0 ) ? 0 : list_front( arg0 );
1486
+ return imported_modules( bindmodule( module ) );
1487
+ }
1488
+
1489
+
1490
+ LIST * builtin_instance( FRAME * frame, int flags )
1491
+ {
1492
+ LIST * arg1 = lol_get( frame->args, 0 );
1493
+ LIST * arg2 = lol_get( frame->args, 1 );
1494
+ module_t * const instance = bindmodule( list_front( arg1 ) );
1495
+ module_t * const class_module = bindmodule( list_front( arg2 ) );
1496
+ instance->class_module = class_module;
1497
+ module_set_fixed_variables( instance, class_module->num_fixed_variables );
1498
+ return L0;
1499
+ }
1500
+
1501
+
1502
+ LIST * builtin_sort( FRAME * frame, int flags )
1503
+ {
1504
+ return list_sort( lol_get( frame->args, 0 ) );
1505
+ }
1506
+
1507
+
1508
+ LIST * builtin_normalize_path( FRAME * frame, int flags )
1509
+ {
1510
+ LIST * arg = lol_get( frame->args, 0 );
1511
+
1512
+ /* First, we iterate over all '/'-separated elements, starting from the end
1513
+ * of string. If we see a '..', we remove a preceeding path element. If we
1514
+ * see '.', we remove it. Removal is done by overwriting data using '\1'
1515
+ * characters. After the whole string has been processed, we do a second
1516
+ * pass, removing any entered '\1' characters.
1517
+ */
1518
+
1519
+ string in[ 1 ];
1520
+ string out[ 1 ];
1521
+ /* Last character of the part of string still to be processed. */
1522
+ char * end;
1523
+ /* Working pointer. */
1524
+ char * current;
1525
+ /* Number of '..' elements seen and not processed yet. */
1526
+ int dotdots = 0;
1527
+ int rooted = 0;
1528
+ OBJECT * result = 0;
1529
+ LISTITER arg_iter = list_begin( arg );
1530
+ LISTITER arg_end = list_end( arg );
1531
+
1532
+ /* Make a copy of input: we should not change it. Prepend a '/' before it as
1533
+ * a guard for the algorithm later on and remember whether it was originally
1534
+ * rooted or not.
1535
+ */
1536
+ string_new( in );
1537
+ string_push_back( in, '/' );
1538
+ for ( ; arg_iter != arg_end; arg_iter = list_next( arg_iter ) )
1539
+ {
1540
+ if ( object_str( list_item( arg_iter ) )[ 0 ] != '\0' )
1541
+ {
1542
+ if ( in->size == 1 )
1543
+ rooted = ( object_str( list_item( arg_iter ) )[ 0 ] == '/' ) ||
1544
+ ( object_str( list_item( arg_iter ) )[ 0 ] == '\\' );
1545
+ else
1546
+ string_append( in, "/" );
1547
+ string_append( in, object_str( list_item( arg_iter ) ) );
1548
+ }
1549
+ }
1550
+
1551
+ /* Convert \ into /. On Windows, paths using / and \ are equivalent, and we
1552
+ * want this function to obtain a canonic representation.
1553
+ */
1554
+ for ( current = in->value, end = in->value + in->size;
1555
+ current < end; ++current )
1556
+ if ( *current == '\\' )
1557
+ *current = '/';
1558
+
1559
+ /* Now we remove any extra path elements by overwriting them with '\1'
1560
+ * characters and cound how many more unused '..' path elements there are
1561
+ * remaining. Note that each remaining path element with always starts with
1562
+ * a '/' character.
1563
+ */
1564
+ for ( end = in->value + in->size - 1; end >= in->value; )
1565
+ {
1566
+ /* Set 'current' to the next occurence of '/', which always exists. */
1567
+ for ( current = end; *current != '/'; --current );
1568
+
1569
+ if ( current == end )
1570
+ {
1571
+ /* Found a trailing or duplicate '/'. Remove it. */
1572
+ *current = '\1';
1573
+ }
1574
+ else if ( ( end - current == 1 ) && ( *( current + 1 ) == '.' ) )
1575
+ {
1576
+ /* Found '/.'. Remove them all. */
1577
+ *current = '\1';
1578
+ *(current + 1) = '\1';
1579
+ }
1580
+ else if ( ( end - current == 2 ) && ( *( current + 1 ) == '.' ) &&
1581
+ ( *( current + 2 ) == '.' ) )
1582
+ {
1583
+ /* Found '/..'. Remove them all. */
1584
+ *current = '\1';
1585
+ *(current + 1) = '\1';
1586
+ *(current + 2) = '\1';
1587
+ ++dotdots;
1588
+ }
1589
+ else if ( dotdots )
1590
+ {
1591
+ memset( current, '\1', end - current + 1 );
1592
+ --dotdots;
1593
+ }
1594
+ end = current - 1;
1595
+ }
1596
+
1597
+ string_new( out );
1598
+
1599
+ /* Now we know that we need to add exactly dotdots '..' path elements to the
1600
+ * front and that our string is either empty or has a '/' as its first
1601
+ * significant character. If we have any dotdots remaining then the passed
1602
+ * path must not have been rooted or else it is invalid we return an empty
1603
+ * list.
1604
+ */
1605
+ if ( dotdots )
1606
+ {
1607
+ if ( rooted )
1608
+ {
1609
+ string_free( out );
1610
+ string_free( in );
1611
+ return L0;
1612
+ }
1613
+ do
1614
+ string_append( out, "/.." );
1615
+ while ( --dotdots );
1616
+ }
1617
+
1618
+ /* Now we actually remove all the path characters marked for removal. */
1619
+ for ( current = in->value; *current; ++current )
1620
+ if ( *current != '\1' )
1621
+ string_push_back( out, *current );
1622
+
1623
+ /* Here we know that our string contains no '\1' characters and is either
1624
+ * empty or has a '/' as its initial character. If the original path was not
1625
+ * rooted and we have a non-empty path we need to drop the initial '/'. If
1626
+ * the original path was rooted and we have an empty path we need to add
1627
+ * back the '/'.
1628
+ */
1629
+ result = object_new( out->size
1630
+ ? out->value + !rooted
1631
+ : ( rooted ? "/" : "." ) );
1632
+
1633
+ string_free( out );
1634
+ string_free( in );
1635
+
1636
+ return list_new( result );
1637
+ }
1638
+
1639
+
1640
+ LIST * builtin_native_rule( FRAME * frame, int flags )
1641
+ {
1642
+ LIST * module_name = lol_get( frame->args, 0 );
1643
+ LIST * rule_name = lol_get( frame->args, 1 );
1644
+
1645
+ module_t * module = bindmodule( list_front( module_name ) );
1646
+
1647
+ native_rule_t * np;
1648
+ if ( module->native_rules && (np = (native_rule_t *)hash_find(
1649
+ module->native_rules, list_front( rule_name ) ) ) )
1650
+ {
1651
+ new_rule_body( module, np->name, np->procedure, 1 );
1652
+ }
1653
+ else
1654
+ {
1655
+ backtrace_line( frame->prev );
1656
+ printf( "error: no native rule \"%s\" defined in module \"%s.\"\n",
1657
+ object_str( list_front( rule_name ) ), object_str( module->name ) );
1658
+ backtrace( frame->prev );
1659
+ exit( 1 );
1660
+ }
1661
+ return L0;
1662
+ }
1663
+
1664
+
1665
+ LIST * builtin_has_native_rule( FRAME * frame, int flags )
1666
+ {
1667
+ LIST * module_name = lol_get( frame->args, 0 );
1668
+ LIST * rule_name = lol_get( frame->args, 1 );
1669
+ LIST * version = lol_get( frame->args, 2 );
1670
+
1671
+ module_t * module = bindmodule( list_front( module_name ) );
1672
+
1673
+ native_rule_t * np;
1674
+ if ( module->native_rules && (np = (native_rule_t *)hash_find(
1675
+ module->native_rules, list_front( rule_name ) ) ) )
1676
+ {
1677
+ int expected_version = atoi( object_str( list_front( version ) ) );
1678
+ if ( np->version == expected_version )
1679
+ return list_new( object_copy( constant_true ) );
1680
+ }
1681
+ return L0;
1682
+ }
1683
+
1684
+
1685
+ LIST * builtin_user_module( FRAME * frame, int flags )
1686
+ {
1687
+ LIST * const module_name = lol_get( frame->args, 0 );
1688
+ LISTITER iter = list_begin( module_name );
1689
+ LISTITER const end = list_end( module_name );
1690
+ for ( ; iter != end; iter = list_next( iter ) )
1691
+ bindmodule( list_item( iter ) )->user_module = 1;
1692
+ return L0;
1693
+ }
1694
+
1695
+
1696
+ LIST * builtin_nearest_user_location( FRAME * frame, int flags )
1697
+ {
1698
+ FRAME * const nearest_user_frame = frame->module->user_module
1699
+ ? frame
1700
+ : frame->prev_user;
1701
+ if ( !nearest_user_frame )
1702
+ return L0;
1703
+
1704
+ {
1705
+ LIST * result = L0;
1706
+ char const * file;
1707
+ int line;
1708
+ char buf[ 32 ];
1709
+
1710
+ get_source_line( nearest_user_frame, &file, &line );
1711
+ sprintf( buf, "%d", line );
1712
+ result = list_push_back( result, object_new( file ) );
1713
+ result = list_push_back( result, object_new( buf ) );
1714
+ return result;
1715
+ }
1716
+ }
1717
+
1718
+
1719
+ LIST * builtin_check_if_file( FRAME * frame, int flags )
1720
+ {
1721
+ LIST * const name = lol_get( frame->args, 0 );
1722
+ return file_is_file( list_front( name ) ) == 1
1723
+ ? list_new( object_copy( constant_true ) )
1724
+ : L0;
1725
+ }
1726
+
1727
+
1728
+ LIST * builtin_md5( FRAME * frame, int flags )
1729
+ {
1730
+ LIST * l = lol_get( frame->args, 0 );
1731
+ char const * s = object_str( list_front( l ) );
1732
+
1733
+ md5_state_t state;
1734
+ md5_byte_t digest[ 16 ];
1735
+ char hex_output[ 16 * 2 + 1 ];
1736
+
1737
+ int di;
1738
+
1739
+ md5_init( &state );
1740
+ md5_append( &state, (md5_byte_t const *)s, strlen( s ) );
1741
+ md5_finish( &state, digest );
1742
+
1743
+ for ( di = 0; di < 16; ++di )
1744
+ sprintf( hex_output + di * 2, "%02x", digest[ di ] );
1745
+
1746
+ return list_new( object_new( hex_output ) );
1747
+ }
1748
+
1749
+
1750
+ LIST * builtin_file_open( FRAME * frame, int flags )
1751
+ {
1752
+ char const * name = object_str( list_front( lol_get( frame->args, 0 ) ) );
1753
+ char const * mode = object_str( list_front( lol_get( frame->args, 1 ) ) );
1754
+ int fd;
1755
+ char buffer[ sizeof( "4294967295" ) ];
1756
+
1757
+ if ( strcmp(mode, "w") == 0 )
1758
+ fd = open( name, O_WRONLY|O_CREAT|O_TRUNC, 0666 );
1759
+ else
1760
+ fd = open( name, O_RDONLY );
1761
+
1762
+ if ( fd != -1 )
1763
+ {
1764
+ sprintf( buffer, "%d", fd );
1765
+ return list_new( object_new( buffer ) );
1766
+ }
1767
+ return L0;
1768
+ }
1769
+
1770
+
1771
+ LIST * builtin_pad( FRAME * frame, int flags )
1772
+ {
1773
+ OBJECT * string = list_front( lol_get( frame->args, 0 ) );
1774
+ char const * width_s = object_str( list_front( lol_get( frame->args, 1 ) ) );
1775
+
1776
+ int current = strlen( object_str( string ) );
1777
+ int desired = atoi( width_s );
1778
+ if ( current >= desired )
1779
+ return list_new( object_copy( string ) );
1780
+ else
1781
+ {
1782
+ char * buffer = BJAM_MALLOC( desired + 1 );
1783
+ int i;
1784
+ LIST * result;
1785
+
1786
+ strcpy( buffer, object_str( string ) );
1787
+ for ( i = current; i < desired; ++i )
1788
+ buffer[ i ] = ' ';
1789
+ buffer[ desired ] = '\0';
1790
+ result = list_new( object_new( buffer ) );
1791
+ BJAM_FREE( buffer );
1792
+ return result;
1793
+ }
1794
+ }
1795
+
1796
+
1797
+ LIST * builtin_precious( FRAME * frame, int flags )
1798
+ {
1799
+ LIST * targets = lol_get( frame->args, 0 );
1800
+ LISTITER iter = list_begin( targets );
1801
+ LISTITER const end = list_end( targets );
1802
+ for ( ; iter != end; iter = list_next( iter ) )
1803
+ bindtarget( list_item( iter ) )->flags |= T_FLAG_PRECIOUS;
1804
+ return L0;
1805
+ }
1806
+
1807
+
1808
+ LIST * builtin_self_path( FRAME * frame, int flags )
1809
+ {
1810
+ extern char const * saved_argv0;
1811
+ char * p = executable_path( saved_argv0 );
1812
+ if ( p )
1813
+ {
1814
+ LIST * const result = list_new( object_new( p ) );
1815
+ free( p );
1816
+ return result;
1817
+ }
1818
+ return L0;
1819
+ }
1820
+
1821
+
1822
+ LIST * builtin_makedir( FRAME * frame, int flags )
1823
+ {
1824
+ LIST * const path = lol_get( frame->args, 0 );
1825
+ return file_mkdir( object_str( list_front( path ) ) )
1826
+ ? L0
1827
+ : list_new( object_copy( list_front( path ) ) );
1828
+ }
1829
+
1830
+
1831
+ #ifdef HAVE_PYTHON
1832
+
1833
+ LIST * builtin_python_import_rule( FRAME * frame, int flags )
1834
+ {
1835
+ static int first_time = 1;
1836
+ char const * python_module = object_str( list_front( lol_get( frame->args,
1837
+ 0 ) ) );
1838
+ char const * python_function = object_str( list_front( lol_get( frame->args,
1839
+ 1 ) ) );
1840
+ OBJECT * jam_module = list_front( lol_get( frame->args, 2 ) );
1841
+ OBJECT * jam_rule = list_front( lol_get( frame->args, 3 ) );
1842
+
1843
+ PyObject * pName;
1844
+ PyObject * pModule;
1845
+ PyObject * pDict;
1846
+ PyObject * pFunc;
1847
+
1848
+ if ( first_time )
1849
+ {
1850
+ /* At the first invocation, we add the value of the global
1851
+ * EXTRA_PYTHONPATH to the sys.path Python variable.
1852
+ */
1853
+ LIST * extra = 0;
1854
+ module_t * outer_module = frame->module;
1855
+ LISTITER iter, end;
1856
+
1857
+ first_time = 0;
1858
+
1859
+ extra = var_get( root_module(), constant_extra_pythonpath );
1860
+
1861
+ iter = list_begin( extra ), end = list_end( extra );
1862
+ for ( ; iter != end; iter = list_next( iter ) )
1863
+ {
1864
+ string buf[ 1 ];
1865
+ string_new( buf );
1866
+ string_append( buf, "import sys\nsys.path.append(\"" );
1867
+ string_append( buf, object_str( list_item( iter ) ) );
1868
+ string_append( buf, "\")\n" );
1869
+ PyRun_SimpleString( buf->value );
1870
+ string_free( buf );
1871
+ }
1872
+ }
1873
+
1874
+ pName = PyString_FromString( python_module );
1875
+ pModule = PyImport_Import( pName );
1876
+ Py_DECREF( pName );
1877
+
1878
+ if ( pModule != NULL )
1879
+ {
1880
+ pDict = PyModule_GetDict( pModule );
1881
+ pFunc = PyDict_GetItemString( pDict, python_function );
1882
+
1883
+ if ( pFunc && PyCallable_Check( pFunc ) )
1884
+ {
1885
+ module_t * m = bindmodule( jam_module );
1886
+ new_rule_body( m, jam_rule, function_python( pFunc, 0 ), 0 );
1887
+ }
1888
+ else
1889
+ {
1890
+ if ( PyErr_Occurred() )
1891
+ PyErr_Print();
1892
+ fprintf( stderr, "Cannot find function \"%s\"\n", python_function );
1893
+ }
1894
+ Py_DECREF( pModule );
1895
+ }
1896
+ else
1897
+ {
1898
+ PyErr_Print();
1899
+ fprintf( stderr, "Failed to load \"%s\"\n", python_module );
1900
+ }
1901
+ return L0;
1902
+
1903
+ }
1904
+
1905
+ #endif /* #ifdef HAVE_PYTHON */
1906
+
1907
+
1908
+ void lol_build( LOL * lol, char const * * elements )
1909
+ {
1910
+ LIST * l = L0;
1911
+ lol_init( lol );
1912
+
1913
+ while ( elements && *elements )
1914
+ {
1915
+ if ( !strcmp( *elements, ":" ) )
1916
+ {
1917
+ lol_add( lol, l );
1918
+ l = L0;
1919
+ }
1920
+ else
1921
+ {
1922
+ l = list_push_back( l, object_new( *elements ) );
1923
+ }
1924
+ ++elements;
1925
+ }
1926
+
1927
+ if ( l != L0 )
1928
+ lol_add( lol, l );
1929
+ }
1930
+
1931
+
1932
+ #ifdef HAVE_PYTHON
1933
+
1934
+ /*
1935
+ * Calls the bjam rule specified by name passed in 'args'. The name is looked up
1936
+ * in the context of bjam's 'python_interface' module. Returns the list of
1937
+ * strings returned by the rule.
1938
+ */
1939
+
1940
+ PyObject * bjam_call( PyObject * self, PyObject * args )
1941
+ {
1942
+ FRAME inner[ 1 ];
1943
+ LIST * result;
1944
+ PARSE * p;
1945
+ OBJECT * rulename;
1946
+
1947
+ /* Build up the list of arg lists. */
1948
+ frame_init( inner );
1949
+ inner->prev = 0;
1950
+ inner->prev_user = 0;
1951
+ inner->module = bindmodule( constant_python_interface );
1952
+
1953
+ /* Extract the rule name and arguments from 'args'. */
1954
+
1955
+ /* PyTuple_GetItem returns borrowed reference. */
1956
+ rulename = object_new( PyString_AsString( PyTuple_GetItem( args, 0 ) ) );
1957
+ {
1958
+ int i = 1;
1959
+ int size = PyTuple_Size( args );
1960
+ for ( ; i < size; ++i )
1961
+ {
1962
+ PyObject * a = PyTuple_GetItem( args, i );
1963
+ if ( PyString_Check( a ) )
1964
+ {
1965
+ lol_add( inner->args, list_new( object_new(
1966
+ PyString_AsString( a ) ) ) );
1967
+ }
1968
+ else if ( PySequence_Check( a ) )
1969
+ {
1970
+ LIST * l = 0;
1971
+ int s = PySequence_Size( a );
1972
+ int i = 0;
1973
+ for ( ; i < s; ++i )
1974
+ {
1975
+ /* PySequence_GetItem returns new reference. */
1976
+ PyObject * e = PySequence_GetItem( a, i );
1977
+ char * s = PyString_AsString( e );
1978
+ if ( !s )
1979
+ {
1980
+ printf( "Invalid parameter type passed from Python\n" );
1981
+ exit( 1 );
1982
+ }
1983
+ l = list_push_back( l, object_new( s ) );
1984
+ Py_DECREF( e );
1985
+ }
1986
+ lol_add( inner->args, l );
1987
+ }
1988
+ }
1989
+ }
1990
+
1991
+ result = evaluate_rule( bindrule( rulename, inner->module), rulename, inner );
1992
+ object_free( rulename );
1993
+
1994
+ frame_free( inner );
1995
+
1996
+ /* Convert the bjam list into a Python list result. */
1997
+ {
1998
+ PyObject * const pyResult = PyList_New( list_length( result ) );
1999
+ int i = 0;
2000
+ LISTITER iter = list_begin( result );
2001
+ LISTITER const end = list_end( result );
2002
+ for ( ; iter != end; iter = list_next( iter ) )
2003
+ {
2004
+ PyList_SetItem( pyResult, i, PyString_FromString( object_str(
2005
+ list_item( iter ) ) ) );
2006
+ i += 1;
2007
+ }
2008
+ list_free( result );
2009
+ return pyResult;
2010
+ }
2011
+ }
2012
+
2013
+
2014
+ /*
2015
+ * Accepts four arguments:
2016
+ * - module name
2017
+ * - rule name,
2018
+ * - Python callable.
2019
+ * - (optional) bjam language function signature.
2020
+ * Creates a bjam rule with the specified name in the specified module, which
2021
+ * will invoke the Python callable.
2022
+ */
2023
+
2024
+ PyObject * bjam_import_rule( PyObject * self, PyObject * args )
2025
+ {
2026
+ char * module;
2027
+ char * rule;
2028
+ PyObject * func;
2029
+ PyObject * bjam_signature = NULL;
2030
+ module_t * m;
2031
+ RULE * r;
2032
+ OBJECT * module_name;
2033
+ OBJECT * rule_name;
2034
+
2035
+ if ( !PyArg_ParseTuple( args, "ssO|O:import_rule",
2036
+ &module, &rule, &func, &bjam_signature ) )
2037
+ return NULL;
2038
+
2039
+ if ( !PyCallable_Check( func ) )
2040
+ {
2041
+ PyErr_SetString( PyExc_RuntimeError, "Non-callable object passed to "
2042
+ "bjam.import_rule" );
2043
+ return NULL;
2044
+ }
2045
+
2046
+ module_name = *module ? object_new( module ) : 0;
2047
+ m = bindmodule( module_name );
2048
+ if ( module_name )
2049
+ object_free( module_name );
2050
+ rule_name = object_new( rule );
2051
+ new_rule_body( m, rule_name, function_python( func, bjam_signature ), 0 );
2052
+ object_free( rule_name );
2053
+
2054
+ Py_INCREF( Py_None );
2055
+ return Py_None;
2056
+ }
2057
+
2058
+
2059
+ /*
2060
+ * Accepts four arguments:
2061
+ * - an action name
2062
+ * - an action body
2063
+ * - a list of variable that will be bound inside the action
2064
+ * - integer flags.
2065
+ * Defines an action on bjam side.
2066
+ */
2067
+
2068
+ PyObject * bjam_define_action( PyObject * self, PyObject * args )
2069
+ {
2070
+ char * name;
2071
+ char * body;
2072
+ module_t * m;
2073
+ PyObject * bindlist_python;
2074
+ int flags;
2075
+ LIST * bindlist = L0;
2076
+ int n;
2077
+ int i;
2078
+ OBJECT * name_str;
2079
+ FUNCTION * body_func;
2080
+
2081
+ if ( !PyArg_ParseTuple( args, "ssO!i:define_action", &name, &body,
2082
+ &PyList_Type, &bindlist_python, &flags ) )
2083
+ return NULL;
2084
+
2085
+ n = PyList_Size( bindlist_python );
2086
+ for ( i = 0; i < n; ++i )
2087
+ {
2088
+ PyObject * next = PyList_GetItem( bindlist_python, i );
2089
+ if ( !PyString_Check( next ) )
2090
+ {
2091
+ PyErr_SetString( PyExc_RuntimeError, "bind list has non-string "
2092
+ "type" );
2093
+ return NULL;
2094
+ }
2095
+ bindlist = list_push_back( bindlist, object_new( PyString_AsString( next
2096
+ ) ) );
2097
+ }
2098
+
2099
+ name_str = object_new( name );
2100
+ body_func = function_compile_actions( body, constant_builtin, -1 );
2101
+ new_rule_actions( root_module(), name_str, body_func, bindlist, flags );
2102
+ function_free( body_func );
2103
+ object_free( name_str );
2104
+
2105
+ Py_INCREF( Py_None );
2106
+ return Py_None;
2107
+ }
2108
+
2109
+
2110
+ /*
2111
+ * Returns the value of a variable in root Jam module.
2112
+ */
2113
+
2114
+ PyObject * bjam_variable( PyObject * self, PyObject * args )
2115
+ {
2116
+ char * name;
2117
+ LIST * value;
2118
+ PyObject * result;
2119
+ int i;
2120
+ OBJECT * varname;
2121
+ LISTITER iter;
2122
+ LISTITER end;
2123
+
2124
+ if ( !PyArg_ParseTuple( args, "s", &name ) )
2125
+ return NULL;
2126
+
2127
+ varname = object_new( name );
2128
+ value = var_get( root_module(), varname );
2129
+ object_free( varname );
2130
+ iter = list_begin( value );
2131
+ end = list_end( value );
2132
+
2133
+ result = PyList_New( list_length( value ) );
2134
+ for ( i = 0; iter != end; iter = list_next( iter ), ++i )
2135
+ PyList_SetItem( result, i, PyString_FromString( object_str( list_item(
2136
+ iter ) ) ) );
2137
+
2138
+ return result;
2139
+ }
2140
+
2141
+
2142
+ PyObject * bjam_backtrace( PyObject * self, PyObject * args )
2143
+ {
2144
+ PyObject * result = PyList_New( 0 );
2145
+ struct frame * f = frame_before_python_call;
2146
+
2147
+ for ( ; f = f->prev; )
2148
+ {
2149
+ PyObject * tuple = PyTuple_New( 4 );
2150
+ char const * file;
2151
+ int line;
2152
+ char buf[ 32 ];
2153
+ string module_name[ 1 ];
2154
+
2155
+ get_source_line( f, &file, &line );
2156
+ sprintf( buf, "%d", line );
2157
+ string_new( module_name );
2158
+ if ( f->module->name )
2159
+ {
2160
+ string_append( module_name, object_str( f->module->name ) );
2161
+ string_append( module_name, "." );
2162
+ }
2163
+
2164
+ /* PyTuple_SetItem steals reference. */
2165
+ PyTuple_SetItem( tuple, 0, PyString_FromString( file ) );
2166
+ PyTuple_SetItem( tuple, 1, PyString_FromString( buf ) );
2167
+ PyTuple_SetItem( tuple, 2, PyString_FromString( module_name->value ) );
2168
+ PyTuple_SetItem( tuple, 3, PyString_FromString( f->rulename ) );
2169
+
2170
+ string_free( module_name );
2171
+
2172
+ PyList_Append( result, tuple );
2173
+ Py_DECREF( tuple );
2174
+ }
2175
+ return result;
2176
+ }
2177
+
2178
+ PyObject * bjam_caller( PyObject * self, PyObject * args )
2179
+ {
2180
+ return PyString_FromString( frame_before_python_call->prev->module->name ?
2181
+ object_str( frame_before_python_call->prev->module->name ) : "" );
2182
+ }
2183
+
2184
+ #endif /* #ifdef HAVE_PYTHON */
2185
+
2186
+
2187
+ #ifdef HAVE_POPEN
2188
+
2189
+ #if defined(_MSC_VER) || defined(__BORLANDC__)
2190
+ #define popen windows_popen_wrapper
2191
+ #define pclose _pclose
2192
+
2193
+ /*
2194
+ * This wrapper is a workaround for a funny _popen() feature on Windows
2195
+ * where it eats external quotes in some cases. The bug seems to be related
2196
+ * to the quote stripping functionality used by the Windows cmd.exe
2197
+ * interpreter when its /S is not specified.
2198
+ *
2199
+ * Cleaned up quote from the cmd.exe help screen as displayed on Windows XP
2200
+ * SP3:
2201
+ *
2202
+ * 1. If all of the following conditions are met, then quote characters on
2203
+ * the command line are preserved:
2204
+ *
2205
+ * - no /S switch
2206
+ * - exactly two quote characters
2207
+ * - no special characters between the two quote characters, where
2208
+ * special is one of: &<>()@^|
2209
+ * - there are one or more whitespace characters between the two quote
2210
+ * characters
2211
+ * - the string between the two quote characters is the name of an
2212
+ * executable file.
2213
+ *
2214
+ * 2. Otherwise, old behavior is to see if the first character is a quote
2215
+ * character and if so, strip the leading character and remove the last
2216
+ * quote character on the command line, preserving any text after the
2217
+ * last quote character.
2218
+ *
2219
+ * This causes some commands containing quotes not to be executed correctly.
2220
+ * For example:
2221
+ *
2222
+ * "\Long folder name\aaa.exe" --name="Jurko" --no-surname
2223
+ *
2224
+ * would get its outermost quotes stripped and would be executed as:
2225
+ *
2226
+ * \Long folder name\aaa.exe" --name="Jurko --no-surname
2227
+ *
2228
+ * which would report an error about '\Long' not being a valid command.
2229
+ *
2230
+ * cmd.exe help seems to indicate it would be enough to add an extra space
2231
+ * character in front of the command to avoid this but this does not work,
2232
+ * most likely due to the shell first stripping all leading whitespace
2233
+ * characters from the command.
2234
+ *
2235
+ * Solution implemented here is to quote the whole command in case it
2236
+ * contains any quote characters. Note thought this will not work correctly
2237
+ * should Windows ever 'fix' this feature.
2238
+ * (03.06.2008.) (Jurko)
2239
+ */
2240
+ static FILE * windows_popen_wrapper( char const * command,
2241
+ char const * mode )
2242
+ {
2243
+ int const extra_command_quotes_needed = !!strchr( command, '"' );
2244
+ string quoted_command;
2245
+ FILE * result;
2246
+
2247
+ if ( extra_command_quotes_needed )
2248
+ {
2249
+ string_new( &quoted_command );
2250
+ string_append( &quoted_command, "\"" );
2251
+ string_append( &quoted_command, command );
2252
+ string_append( &quoted_command, "\"" );
2253
+ command = quoted_command.value;
2254
+ }
2255
+
2256
+ result = _popen( command, "r" );
2257
+
2258
+ if ( extra_command_quotes_needed )
2259
+ string_free( &quoted_command );
2260
+
2261
+ return result;
2262
+ }
2263
+ #endif /* defined(_MSC_VER) || defined(__BORLANDC__) */
2264
+
2265
+
2266
+ static char * rtrim( char * const s )
2267
+ {
2268
+ char * p = s;
2269
+ while ( *p ) ++p;
2270
+ for ( --p; p >= s && isspace( *p ); *p-- = 0 );
2271
+ return s;
2272
+ }
2273
+
2274
+
2275
+ LIST * builtin_shell( FRAME * frame, int flags )
2276
+ {
2277
+ LIST * command = lol_get( frame->args, 0 );
2278
+ LIST * result = L0;
2279
+ string s;
2280
+ int ret;
2281
+ char buffer[ 1024 ];
2282
+ FILE * p = NULL;
2283
+ int exit_status = -1;
2284
+ int exit_status_opt = 0;
2285
+ int no_output_opt = 0;
2286
+ int strip_eol_opt = 0;
2287
+
2288
+ /* Process the variable args options. */
2289
+ {
2290
+ int a = 1;
2291
+ LIST * arg = lol_get( frame->args, a );
2292
+ for ( ; !list_empty( arg ); arg = lol_get( frame->args, ++a ) )
2293
+ {
2294
+ if ( !strcmp( "exit-status", object_str( list_front( arg ) ) ) )
2295
+ exit_status_opt = 1;
2296
+ else if ( !strcmp( "no-output", object_str( list_front( arg ) ) ) )
2297
+ no_output_opt = 1;
2298
+ else if ( !strcmp("strip-eol", object_str( list_front( arg ) ) ) )
2299
+ strip_eol_opt = 1;
2300
+ }
2301
+ }
2302
+
2303
+ /* The following fflush() call seems to be indicated as a workaround for a
2304
+ * popen() bug on POSIX implementations related to synhronizing input
2305
+ * stream positions for the called and the calling process.
2306
+ */
2307
+ fflush( NULL );
2308
+
2309
+ p = popen( object_str( list_front( command ) ), "r" );
2310
+ if ( p == NULL )
2311
+ return L0;
2312
+
2313
+ string_new( &s );
2314
+
2315
+ while ( ( ret = fread( buffer, sizeof( char ), sizeof( buffer ) - 1, p ) ) >
2316
+ 0 )
2317
+ {
2318
+ buffer[ ret ] = 0;
2319
+ if ( !no_output_opt )
2320
+ {
2321
+ if ( strip_eol_opt )
2322
+ rtrim( buffer );
2323
+ string_append( &s, buffer );
2324
+ }
2325
+ }
2326
+
2327
+ exit_status = pclose( p );
2328
+
2329
+ /* The command output is returned first. */
2330
+ result = list_new( object_new( s.value ) );
2331
+ string_free( &s );
2332
+
2333
+ /* The command exit result next. */
2334
+ if ( exit_status_opt )
2335
+ {
2336
+ if ( WIFEXITED( exit_status ) )
2337
+ exit_status = WEXITSTATUS( exit_status );
2338
+ else
2339
+ exit_status = -1;
2340
+ sprintf( buffer, "%d", exit_status );
2341
+ result = list_push_back( result, object_new( buffer ) );
2342
+ }
2343
+
2344
+ return result;
2345
+ }
2346
+
2347
+ #else /* #ifdef HAVE_POPEN */
2348
+
2349
+ LIST * builtin_shell( FRAME * frame, int flags )
2350
+ {
2351
+ return L0;
2352
+ }
2353
+
2354
+ #endif /* #ifdef HAVE_POPEN */
mosesdecoder/jam-files/engine/builtins.h ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ #ifndef JAM_BUILTINS_H
8
+ # define JAM_BUILTINS_H
9
+
10
+ # include "frames.h"
11
+
12
+ /*
13
+ * builtins.h - compile parsed jam statements
14
+ */
15
+
16
+ void load_builtins();
17
+ void init_set();
18
+ void init_path();
19
+ void init_regex();
20
+ void init_property_set();
21
+ void init_sequence();
22
+ void init_order();
23
+
24
+ void property_set_done();
25
+
26
+ LIST *builtin_calc( FRAME * frame, int flags );
27
+ LIST *builtin_depends( FRAME * frame, int flags );
28
+ LIST *builtin_rebuilds( FRAME * frame, int flags );
29
+ LIST *builtin_echo( FRAME * frame, int flags );
30
+ LIST *builtin_exit( FRAME * frame, int flags );
31
+ LIST *builtin_flags( FRAME * frame, int flags );
32
+ LIST *builtin_glob( FRAME * frame, int flags );
33
+ LIST *builtin_glob_recursive( FRAME * frame, int flags );
34
+ LIST *builtin_subst( FRAME * frame, int flags );
35
+ LIST *builtin_match( FRAME * frame, int flags );
36
+ LIST *builtin_split_by_characters( FRAME * frame, int flags );
37
+ LIST *builtin_hdrmacro( FRAME * frame, int flags );
38
+ LIST *builtin_rulenames( FRAME * frame, int flags );
39
+ LIST *builtin_varnames( FRAME * frame, int flags );
40
+ LIST *builtin_delete_module( FRAME * frame, int flags );
41
+ LIST *builtin_import( FRAME * frame, int flags );
42
+ LIST *builtin_export( FRAME * frame, int flags );
43
+ LIST *builtin_caller_module( FRAME * frame, int flags );
44
+ LIST *builtin_backtrace( FRAME * frame, int flags );
45
+ LIST *builtin_pwd( FRAME * frame, int flags );
46
+ LIST *builtin_update( FRAME * frame, int flags );
47
+ LIST *builtin_update_now( FRAME * frame, int flags );
48
+ LIST *builtin_import_module( FRAME * frame, int flags );
49
+ LIST *builtin_imported_modules( FRAME * frame, int flags );
50
+ LIST *builtin_instance( FRAME * frame, int flags );
51
+ LIST *builtin_sort( FRAME * frame, int flags );
52
+ LIST *builtin_normalize_path( FRAME * frame, int flags );
53
+ LIST *builtin_native_rule( FRAME * frame, int flags );
54
+ LIST *builtin_has_native_rule( FRAME * frame, int flags );
55
+ LIST *builtin_user_module( FRAME * frame, int flags );
56
+ LIST *builtin_nearest_user_location( FRAME * frame, int flags );
57
+ LIST *builtin_check_if_file( FRAME * frame, int flags );
58
+ LIST *builtin_python_import_rule( FRAME * frame, int flags );
59
+ LIST *builtin_shell( FRAME * frame, int flags );
60
+ LIST *builtin_md5( FRAME * frame, int flags );
61
+ LIST *builtin_file_open( FRAME * frame, int flags );
62
+ LIST *builtin_pad( FRAME * frame, int flags );
63
+ LIST *builtin_precious( FRAME * frame, int flags );
64
+ LIST *builtin_self_path( FRAME * frame, int flags );
65
+ LIST *builtin_makedir( FRAME * frame, int flags );
66
+
67
+ void backtrace( FRAME *frame );
68
+ extern int last_update_now_status;
69
+
70
+ #endif
mosesdecoder/jam-files/engine/bump_version.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/python
2
+
3
+ # This script is used to bump the bjam version. It takes a single argument, e.g
4
+ #
5
+ # ./bump_version.py 3.1.9
6
+ #
7
+ # and updates all the necessary files.
8
+ #
9
+ # Copyright 2006 Rene Rivera.
10
+ # Copyright 2005-2006 Vladimir Prus.
11
+ # Distributed under the Boost Software License, Version 1.0.
12
+ # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
13
+
14
+
15
+ import os
16
+ import os.path
17
+ import re
18
+ import string
19
+ import sys
20
+
21
+ srcdir = os.path.abspath(os.path.dirname(__file__))
22
+ docdir = os.path.abspath(os.path.join(srcdir, "..", "doc"))
23
+
24
+
25
+ def edit(file, *replacements):
26
+ print(" '%s'..." % file)
27
+ f = open(file, 'r')
28
+ text = f.read()
29
+ f.close()
30
+ for (source, target) in replacements:
31
+ text, n = re.compile(source, re.MULTILINE).subn(target, text)
32
+ assert n > 0
33
+ f = open(file, 'w')
34
+ f.write(text)
35
+ f.close()
36
+
37
+
38
+ def make_edits(ver):
39
+ ver03 = (list(ver) + [0] * 3)[0:3]
40
+ ver02 = ver03[0:2]
41
+
42
+ join = lambda v, s : s.join(str(x) for x in v)
43
+ dotJoin = lambda v : join(v, ".")
44
+
45
+ print("Setting version to %s" % str(ver03))
46
+
47
+ edit(os.path.join(srcdir, "boost-jam.spec"),
48
+ ('^(Version:) .*$', '\\1 %s' % dotJoin(ver03)))
49
+
50
+ edit(os.path.join(srcdir, "build.jam"),
51
+ ('^(_VERSION_ =).* ;$', '\\1 %s ;' % join(ver03, " ")))
52
+
53
+ edit(os.path.join(docdir, "bjam.qbk"),
54
+ ('(\[version).*(\])', '\\1: %s\\2' % dotJoin(ver03)),
55
+ ('(\[def :version:).*(\])', '\\1 %s\\2' % dotJoin(ver03)))
56
+
57
+ edit(os.path.join(srcdir, "patchlevel.h"),
58
+ ('^(#define VERSION_MAJOR) .*$', '\\1 %s' % ver03[0]),
59
+ ('^(#define VERSION_MINOR) .*$', '\\1 %s' % ver03[1]),
60
+ ('^(#define VERSION_PATCH) .*$', '\\1 %s' % ver03[2]),
61
+ ('^(#define VERSION_MAJOR_SYM) .*$', '\\1 "%02d"' % ver03[0]),
62
+ ('^(#define VERSION_MINOR_SYM) .*$', '\\1 "%02d"' % ver03[1]),
63
+ ('^(#define VERSION_PATCH_SYM) .*$', '\\1 "%02d"' % ver03[2]),
64
+ ('^(#define VERSION) .*$', '\\1 "%s"' % dotJoin(ver)),
65
+ ('^(#define JAMVERSYM) .*$', '\\1 "JAMVERSION=%s"' % dotJoin(ver02)))
66
+
67
+
68
+ def main():
69
+ if len(sys.argv) < 2:
70
+ print("Expect new version as argument.")
71
+ sys.exit(1)
72
+ if len(sys.argv) > 3:
73
+ print("Too many arguments.")
74
+ sys.exit(1)
75
+
76
+ version = sys.argv[1].split(".")
77
+ if len(version) > 3:
78
+ print("Expect version argument in the format: <MAJOR>.<MINOR>.<PATCH>")
79
+ sys.exit(1)
80
+
81
+ try:
82
+ version = list(int(x) for x in version)
83
+ except ValueError:
84
+ print("Version values must be valid integers.")
85
+ sys.exit(1)
86
+
87
+ while version and version[-1] == 0:
88
+ version.pop()
89
+
90
+ if not version:
91
+ print("At least one of the version values must be positive.")
92
+ sys.exit()
93
+
94
+ make_edits(version)
95
+
96
+
97
+ if __name__ == '__main__':
98
+ main()
mosesdecoder/jam-files/engine/class.c ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright Vladimir Prus 2003.
3
+ * Distributed under the Boost Software License, Version 1.0.
4
+ * (See accompanying file LICENSE_1_0.txt or copy at
5
+ * http://www.boost.org/LICENSE_1_0.txt)
6
+ */
7
+
8
+ #include "class.h"
9
+
10
+ #include "constants.h"
11
+ #include "frames.h"
12
+ #include "hash.h"
13
+ #include "lists.h"
14
+ #include "object.h"
15
+ #include "rules.h"
16
+ #include "strings.h"
17
+ #include "variable.h"
18
+
19
+ #include <stdio.h>
20
+ #include <stdlib.h>
21
+
22
+
23
+ static struct hash * classes = 0;
24
+
25
+
26
+ static void check_defined( LIST * class_names )
27
+ {
28
+ LISTITER iter = list_begin( class_names );
29
+ LISTITER const end = list_end( class_names );
30
+ for ( ; iter != end; iter = list_next( iter ) )
31
+ {
32
+ if ( !hash_find( classes, list_item( iter ) ) )
33
+ {
34
+ printf( "Class %s is not defined\n", object_str( list_item( iter ) )
35
+ );
36
+ abort();
37
+ }
38
+ }
39
+ }
40
+
41
+
42
+ static OBJECT * class_module_name( OBJECT * declared_name )
43
+ {
44
+ string name[ 1 ];
45
+ OBJECT * result;
46
+
47
+ string_new( name );
48
+ string_append( name, "class@" );
49
+ string_append( name, object_str( declared_name ) );
50
+
51
+ result = object_new( name->value );
52
+ string_free( name );
53
+
54
+ return result;
55
+ }
56
+
57
+
58
+ struct import_base_data
59
+ {
60
+ OBJECT * base_name;
61
+ module_t * base_module;
62
+ module_t * class_module;
63
+ };
64
+
65
+
66
+ static void import_base_rule( void * r_, void * d_ )
67
+ {
68
+ RULE * r = (RULE *)r_;
69
+ RULE * ir1;
70
+ RULE * ir2;
71
+ struct import_base_data * d = (struct import_base_data *)d_;
72
+ OBJECT * qname;
73
+
74
+ string qualified_name[ 1 ];
75
+ string_new ( qualified_name );
76
+ string_append ( qualified_name, object_str( d->base_name ) );
77
+ string_push_back( qualified_name, '.' );
78
+ string_append ( qualified_name, object_str( r->name ) );
79
+ qname = object_new( qualified_name->value );
80
+ string_free( qualified_name );
81
+
82
+ ir1 = import_rule( r, d->class_module, r->name );
83
+ ir2 = import_rule( r, d->class_module, qname );
84
+
85
+ object_free( qname );
86
+
87
+ /* Copy 'exported' flag. */
88
+ ir1->exported = ir2->exported = r->exported;
89
+
90
+ /* If we are importing a class method, localize it. */
91
+ if ( ( r->module == d->base_module ) || ( r->module->class_module &&
92
+ ( r->module->class_module == d->base_module ) ) )
93
+ {
94
+ rule_localize( ir1, d->class_module );
95
+ rule_localize( ir2, d->class_module );
96
+ }
97
+ }
98
+
99
+
100
+ /*
101
+ * For each exported rule 'n', declared in class module for base, imports that
102
+ * rule in 'class' as 'n' and as 'base.n'. Imported rules are localized and
103
+ * marked as exported.
104
+ */
105
+
106
+ static void import_base_rules( module_t * class_, OBJECT * base )
107
+ {
108
+ OBJECT * module_name = class_module_name( base );
109
+ module_t * base_module = bindmodule( module_name );
110
+ LIST * imported;
111
+ struct import_base_data d;
112
+ d.base_name = base;
113
+ d.base_module = base_module;
114
+ d.class_module = class_;
115
+ object_free( module_name );
116
+
117
+ if ( base_module->rules )
118
+ hashenumerate( base_module->rules, import_base_rule, &d );
119
+
120
+ imported = imported_modules( base_module );
121
+ import_module( imported, class_ );
122
+ list_free( imported );
123
+ }
124
+
125
+
126
+ OBJECT * make_class_module( LIST * xname, LIST * bases, FRAME * frame )
127
+ {
128
+ OBJECT * name = class_module_name( list_front( xname ) );
129
+ OBJECT * * pp;
130
+ module_t * class_module = 0;
131
+ module_t * outer_module = frame->module;
132
+ int found;
133
+
134
+ if ( !classes )
135
+ classes = hashinit( sizeof( OBJECT * ), "classes" );
136
+
137
+ pp = (OBJECT * *)hash_insert( classes, list_front( xname ), &found );
138
+ if ( !found )
139
+ {
140
+ *pp = object_copy( list_front( xname ) );
141
+ }
142
+ else
143
+ {
144
+ printf( "Class %s already defined\n", object_str( list_front( xname ) )
145
+ );
146
+ abort();
147
+ }
148
+ check_defined( bases );
149
+
150
+ class_module = bindmodule( name );
151
+
152
+ {
153
+ /*
154
+ Initialize variables that Boost.Build inserts in every object.
155
+ We want to avoid creating the object's hash if it isn't needed.
156
+ */
157
+ int num = class_module->num_fixed_variables;
158
+ module_add_fixed_var( class_module, constant_name, &num );
159
+ module_add_fixed_var( class_module, constant_class, &num );
160
+ module_set_fixed_variables( class_module, num );
161
+ }
162
+
163
+ var_set( class_module, constant_name, xname, VAR_SET );
164
+ var_set( class_module, constant_bases, bases, VAR_SET );
165
+
166
+ {
167
+ LISTITER iter = list_begin( bases );
168
+ LISTITER const end = list_end( bases );
169
+ for ( ; iter != end; iter = list_next( iter ) )
170
+ import_base_rules( class_module, list_item( iter ) );
171
+ }
172
+
173
+ return name;
174
+ }
175
+
176
+
177
+ static void free_class( void * xclass, void * data )
178
+ {
179
+ object_free( *(OBJECT * *)xclass );
180
+ }
181
+
182
+
183
+ void class_done( void )
184
+ {
185
+ if ( classes )
186
+ {
187
+ hashenumerate( classes, free_class, (void *)0 );
188
+ hashdone( classes );
189
+ classes = 0;
190
+ }
191
+ }
mosesdecoder/jam-files/engine/command.h ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1994 Christopher Seiwald.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ /*
8
+ * command.h - the CMD structure and routines to manipulate them
9
+ *
10
+ * Both ACTION and CMD contain a rule, targets, and sources. An
11
+ * ACTION describes a rule to be applied to the given targets and
12
+ * sources; a CMD is what actually gets executed by the shell. The
13
+ * differences are due to:
14
+ *
15
+ * ACTIONS must be combined if 'actions together' is given.
16
+ * ACTIONS must be split if 'actions piecemeal' is given.
17
+ * ACTIONS must have current sources omitted for 'actions updated'.
18
+ *
19
+ * The CMD datatype holds a single command that is to be executed
20
+ * against a target, and they can chain together to represent the
21
+ * full collection of commands used to update a target.
22
+ *
23
+ * Structures:
24
+ *
25
+ * CMD - an action, ready to be formatted into a buffer and executed.
26
+ *
27
+ * External routines:
28
+ *
29
+ * cmd_new() - return a new CMD or 0 if too many args.
30
+ * cmd_free() - delete CMD and its parts.
31
+ * cmd_next() - walk the CMD chain.
32
+ * cmd_release_targets_and_shell() - CMD forgets about its targets & shell.
33
+ */
34
+
35
+
36
+ /*
37
+ * CMD - an action, ready to be formatted into a buffer and executed.
38
+ */
39
+
40
+ #ifndef COMMAND_SW20111118_H
41
+ #define COMMAND_SW20111118_H
42
+
43
+ #include "lists.h"
44
+ #include "rules.h"
45
+ #include "strings.h"
46
+
47
+
48
+ typedef struct _cmd CMD;
49
+ struct _cmd
50
+ {
51
+ CMD * next;
52
+ RULE * rule; /* rule->actions contains shell script */
53
+ LIST * shell; /* $(JAMSHELL) value */
54
+ LOL args; /* LISTs for $(<), $(>) */
55
+ string buf[ 1 ]; /* actual commands */
56
+ int noop; /* no-op commands should be faked instead of executed */
57
+ };
58
+
59
+ CMD * cmd_new
60
+ (
61
+ RULE * rule, /* rule (referenced) */
62
+ LIST * targets, /* $(<) (ownership transferred) */
63
+ LIST * sources, /* $(>) (ownership transferred) */
64
+ LIST * shell /* $(JAMSHELL) (ownership transferred) */
65
+ );
66
+
67
+ void cmd_release_targets_and_shell( CMD * );
68
+
69
+ void cmd_free( CMD * );
70
+
71
+ #define cmd_next( c ) ((c)->next)
72
+
73
+ #endif
mosesdecoder/jam-files/engine/compile.h ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993, 2000 Christopher Seiwald.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ /* This file is ALSO:
8
+ * Copyright 2001-2004 David Abrahams.
9
+ * Distributed under the Boost Software License, Version 1.0.
10
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
11
+ */
12
+
13
+ /*
14
+ * compile.h - compile parsed jam statements
15
+ */
16
+
17
+ #ifndef COMPILE_DWA20011022_H
18
+ #define COMPILE_DWA20011022_H
19
+
20
+ #include "frames.h"
21
+ #include "lists.h"
22
+ #include "object.h"
23
+ #include "rules.h"
24
+
25
+ void compile_builtins();
26
+
27
+ LIST * evaluate_rule( RULE * rule, OBJECT * rulename, FRAME * );
28
+ LIST * call_rule( OBJECT * rulename, FRAME * caller_frame, ... );
29
+
30
+ /* Flags for compile_set(), etc */
31
+
32
+ #define ASSIGN_SET 0x00 /* = assign variable */
33
+ #define ASSIGN_APPEND 0x01 /* += append variable */
34
+ #define ASSIGN_DEFAULT 0x02 /* set only if unset */
35
+
36
+ /* Flags for compile_setexec() */
37
+
38
+ #define EXEC_UPDATED 0x01 /* executes updated */
39
+ #define EXEC_TOGETHER 0x02 /* executes together */
40
+ #define EXEC_IGNORE 0x04 /* executes ignore */
41
+ #define EXEC_QUIETLY 0x08 /* executes quietly */
42
+ #define EXEC_PIECEMEAL 0x10 /* executes piecemeal */
43
+ #define EXEC_EXISTING 0x20 /* executes existing */
44
+
45
+ /* Conditions for compile_if() */
46
+
47
+ #define EXPR_NOT 0 /* ! cond */
48
+ #define EXPR_AND 1 /* cond && cond */
49
+ #define EXPR_OR 2 /* cond || cond */
50
+ #define EXPR_EXISTS 3 /* arg */
51
+ #define EXPR_EQUALS 4 /* arg = arg */
52
+ #define EXPR_NOTEQ 5 /* arg != arg */
53
+ #define EXPR_LESS 6 /* arg < arg */
54
+ #define EXPR_LESSEQ 7 /* arg <= arg */
55
+ #define EXPR_MORE 8 /* arg > arg */
56
+ #define EXPR_MOREEQ 9 /* arg >= arg */
57
+ #define EXPR_IN 10 /* arg in arg */
58
+
59
+ #endif
mosesdecoder/jam-files/engine/cwd.c ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 2002. Vladimir Prus
3
+ * Copyright 2005. Rene Rivera
4
+ * Distributed under the Boost Software License, Version 1.0.
5
+ * (See accompanying file LICENSE_1_0.txt or copy at
6
+ * http://www.boost.org/LICENSE_1_0.txt)
7
+ */
8
+
9
+ #include "cwd.h"
10
+
11
+ #include "jam.h"
12
+ #include "mem.h"
13
+ #include "pathsys.h"
14
+
15
+ #include <assert.h>
16
+ #include <errno.h>
17
+ #include <limits.h>
18
+
19
+ /* MinGW on Windows declares PATH_MAX in limits.h */
20
+ #if defined( NT ) && !defined( __GNUC__ )
21
+ # include <direct.h>
22
+ # define PATH_MAX _MAX_PATH
23
+ #else
24
+ # include <unistd.h>
25
+ # if defined( __COMO__ )
26
+ # include <linux/limits.h>
27
+ # endif
28
+ #endif
29
+
30
+ #ifndef PATH_MAX
31
+ # define PATH_MAX 1024
32
+ #endif
33
+
34
+
35
+ static OBJECT * cwd_;
36
+
37
+
38
+ void cwd_init( void )
39
+ {
40
+ int buffer_size = PATH_MAX;
41
+ char * cwd_buffer = 0;
42
+ int error;
43
+
44
+ assert( !cwd_ );
45
+
46
+ do
47
+ {
48
+ char * const buffer = BJAM_MALLOC_RAW( buffer_size );
49
+ cwd_buffer = getcwd( buffer, buffer_size );
50
+ error = errno;
51
+ if ( cwd_buffer )
52
+ {
53
+ /* We store the path using its canonical/long/key format. */
54
+ OBJECT * const cwd = object_new( cwd_buffer );
55
+ cwd_ = path_as_key( cwd );
56
+ object_free( cwd );
57
+ }
58
+ buffer_size *= 2;
59
+ BJAM_FREE_RAW( buffer );
60
+ }
61
+ while ( !cwd_ && error == ERANGE );
62
+
63
+ if ( !cwd_ )
64
+ {
65
+ perror( "can not get current working directory" );
66
+ exit( EXITBAD );
67
+ }
68
+ }
69
+
70
+
71
+ OBJECT * cwd( void )
72
+ {
73
+ assert( cwd_ );
74
+ return cwd_;
75
+ }
76
+
77
+
78
+ void cwd_done( void )
79
+ {
80
+ assert( cwd_ );
81
+ object_free( cwd_ );
82
+ cwd_ = NULL;
83
+ }
mosesdecoder/jam-files/engine/filent.c ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993, 1995 Christopher Seiwald.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ /* This file is ALSO:
8
+ * Copyright 2001-2004 David Abrahams.
9
+ * Copyright 2005 Rene Rivera.
10
+ * Distributed under the Boost Software License, Version 1.0.
11
+ * (See accompanying file LICENSE_1_0.txt or copy at
12
+ * http://www.boost.org/LICENSE_1_0.txt)
13
+ */
14
+
15
+ /*
16
+ * filent.c - scan directories and archives on NT
17
+ *
18
+ * External routines:
19
+ * file_mkdir() - create a directory
20
+ * file_supported_fmt_resolution() - file modification timestamp resolution
21
+ *
22
+ * External routines called only via routines in filesys.c:
23
+ * file_collect_dir_content_() - collects directory content information
24
+ * file_dirscan_() - OS specific file_dirscan() implementation
25
+ * file_query_() - query information about a path from the OS
26
+ */
27
+
28
+ #include "jam.h"
29
+ #ifdef OS_NT
30
+ #include "filesys.h"
31
+
32
+ #include "object.h"
33
+ #include "pathsys.h"
34
+ #include "strings.h"
35
+
36
+ #ifdef __BORLANDC__
37
+ # undef FILENAME /* cpp namespace collision */
38
+ #endif
39
+
40
+ #define WIN32_LEAN_AND_MEAN
41
+ #include <windows.h>
42
+
43
+ #include <assert.h>
44
+ #include <ctype.h>
45
+ #include <direct.h>
46
+ #include <io.h>
47
+
48
+
49
+ /*
50
+ * file_collect_dir_content_() - collects directory content information
51
+ */
52
+
53
+ int file_collect_dir_content_( file_info_t * const d )
54
+ {
55
+ PATHNAME f;
56
+ string pathspec[ 1 ];
57
+ string pathname[ 1 ];
58
+ LIST * files = L0;
59
+ int d_length;
60
+
61
+ assert( d );
62
+ assert( d->is_dir );
63
+ assert( list_empty( d->files ) );
64
+
65
+ d_length = strlen( object_str( d->name ) );
66
+
67
+ memset( (char *)&f, '\0', sizeof( f ) );
68
+ f.f_dir.ptr = object_str( d->name );
69
+ f.f_dir.len = d_length;
70
+
71
+ /* Prepare file search specification for the FindXXX() Windows API. */
72
+ if ( !d_length )
73
+ string_copy( pathspec, ".\\*" );
74
+ else
75
+ {
76
+ /* We can not simply assume the given folder name will never include its
77
+ * trailing path separator or otherwise we would not support the Windows
78
+ * root folder specified without its drive letter, i.e. '\'.
79
+ */
80
+ char const trailingChar = object_str( d->name )[ d_length - 1 ] ;
81
+ string_copy( pathspec, object_str( d->name ) );
82
+ if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) )
83
+ string_append( pathspec, "\\" );
84
+ string_append( pathspec, "*" );
85
+ }
86
+
87
+ /* The following code for collecting information about all files in a folder
88
+ * needs to be kept synchronized with how the file_query() operation is
89
+ * implemented (collects information about a single file).
90
+ */
91
+ {
92
+ /* FIXME: Avoid duplicate FindXXX Windows API calls here and in the code
93
+ * determining a normalized path.
94
+ */
95
+ WIN32_FIND_DATA finfo;
96
+ HANDLE const findHandle = FindFirstFileA( pathspec->value, &finfo );
97
+ if ( findHandle == INVALID_HANDLE_VALUE )
98
+ {
99
+ string_free( pathspec );
100
+ return -1;
101
+ }
102
+
103
+ string_new( pathname );
104
+ do
105
+ {
106
+ OBJECT * pathname_obj;
107
+
108
+ f.f_base.ptr = finfo.cFileName;
109
+ f.f_base.len = strlen( finfo.cFileName );
110
+
111
+ string_truncate( pathname, 0 );
112
+ path_build( &f, pathname );
113
+
114
+ pathname_obj = object_new( pathname->value );
115
+ path_register_key( pathname_obj );
116
+ files = list_push_back( files, pathname_obj );
117
+ {
118
+ int found;
119
+ file_info_t * const ff = file_info( pathname_obj, &found );
120
+ ff->is_dir = finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
121
+ ff->is_file = !ff->is_dir;
122
+ ff->exists = 1;
123
+ timestamp_from_filetime( &ff->time, &finfo.ftLastWriteTime );
124
+ }
125
+ }
126
+ while ( FindNextFile( findHandle, &finfo ) );
127
+
128
+ FindClose( findHandle );
129
+ }
130
+
131
+ string_free( pathname );
132
+ string_free( pathspec );
133
+
134
+ d->files = files;
135
+ return 0;
136
+ }
137
+
138
+
139
+ /*
140
+ * file_dirscan_() - OS specific file_dirscan() implementation
141
+ */
142
+
143
+ void file_dirscan_( file_info_t * const d, scanback func, void * closure )
144
+ {
145
+ assert( d );
146
+ assert( d->is_dir );
147
+
148
+ /* Special case \ or d:\ : enter it */
149
+ {
150
+ char const * const name = object_str( d->name );
151
+ if ( name[ 0 ] == '\\' && !name[ 1 ] )
152
+ {
153
+ (*func)( closure, d->name, 1 /* stat()'ed */, &d->time );
154
+ }
155
+ else if ( name[ 0 ] && name[ 1 ] == ':' && name[ 2 ] && !name[ 3 ] )
156
+ {
157
+ /* We have just entered a 3-letter drive name spelling (with a
158
+ * trailing slash), into the hash table. Now enter its two-letter
159
+ * variant, without the trailing slash, so that if we try to check
160
+ * whether "c:" exists, we hit it.
161
+ *
162
+ * Jam core has workarounds for that. Given:
163
+ * x = c:\whatever\foo ;
164
+ * p = $(x:D) ;
165
+ * p2 = $(p:D) ;
166
+ * There will be no trailing slash in $(p), but there will be one in
167
+ * $(p2). But, that seems rather fragile.
168
+ */
169
+ OBJECT * const dir_no_slash = object_new_range( name, 2 );
170
+ (*func)( closure, d->name, 1 /* stat()'ed */, &d->time );
171
+ (*func)( closure, dir_no_slash, 1 /* stat()'ed */, &d->time );
172
+ object_free( dir_no_slash );
173
+ }
174
+ }
175
+ }
176
+
177
+
178
+ /*
179
+ * file_mkdir() - create a directory
180
+ */
181
+
182
+ int file_mkdir( char const * const path )
183
+ {
184
+ return _mkdir( path );
185
+ }
186
+
187
+
188
+ /*
189
+ * file_query_() - query information about a path from the OS
190
+ *
191
+ * The following code for collecting information about a single file needs to be
192
+ * kept synchronized with how the file_collect_dir_content_() operation is
193
+ * implemented (collects information about all files in a folder).
194
+ */
195
+
196
+ int try_file_query_root( file_info_t * const info )
197
+ {
198
+ WIN32_FILE_ATTRIBUTE_DATA fileData;
199
+ char buf[ 4 ];
200
+ char const * const pathstr = object_str( info->name );
201
+ if ( !pathstr[ 0 ] )
202
+ {
203
+ buf[ 0 ] = '.';
204
+ buf[ 1 ] = 0;
205
+ }
206
+ else if ( pathstr[ 0 ] == '\\' && ! pathstr[ 1 ] )
207
+ {
208
+ buf[ 0 ] = '\\';
209
+ buf[ 1 ] = '\0';
210
+ }
211
+ else if ( pathstr[ 1 ] == ':' )
212
+ {
213
+ if ( !pathstr[ 2 ] )
214
+ {
215
+ }
216
+ else if ( !pathstr[ 2 ] || ( pathstr[ 2 ] == '\\' && !pathstr[ 3 ] ) )
217
+ {
218
+ buf[ 0 ] = pathstr[ 0 ];
219
+ buf[ 1 ] = ':';
220
+ buf[ 2 ] = '\\';
221
+ buf[ 3 ] = '\0';
222
+ }
223
+ else
224
+ {
225
+ return 0;
226
+ }
227
+ }
228
+ else
229
+ {
230
+ return 0;
231
+ }
232
+
233
+ /* We have a root path */
234
+ if ( !GetFileAttributesExA( buf, GetFileExInfoStandard, &fileData ) )
235
+ {
236
+ info->is_dir = 0;
237
+ info->is_file = 0;
238
+ info->exists = 0;
239
+ timestamp_clear( &info->time );
240
+ }
241
+ else
242
+ {
243
+ info->is_dir = fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
244
+ info->is_file = !info->is_dir;
245
+ info->exists = 1;
246
+ timestamp_from_filetime( &info->time, &fileData.ftLastWriteTime );
247
+ }
248
+ return 1;
249
+ }
250
+
251
+ void file_query_( file_info_t * const info )
252
+ {
253
+ char const * const pathstr = object_str( info->name );
254
+ const char * dir;
255
+ OBJECT * parent;
256
+ file_info_t * parent_info;
257
+
258
+ if ( try_file_query_root( info ) )
259
+ return;
260
+
261
+ if ( ( dir = strrchr( pathstr, '\\' ) ) )
262
+ {
263
+ parent = object_new_range( pathstr, dir - pathstr );
264
+ }
265
+ else
266
+ {
267
+ parent = object_copy( constant_empty );
268
+ }
269
+ parent_info = file_query( parent );
270
+ object_free( parent );
271
+ if ( !parent_info || !parent_info->is_dir )
272
+ {
273
+ info->is_dir = 0;
274
+ info->is_file = 0;
275
+ info->exists = 0;
276
+ timestamp_clear( &info->time );
277
+ }
278
+ else
279
+ {
280
+ info->is_dir = 0;
281
+ info->is_file = 0;
282
+ info->exists = 0;
283
+ timestamp_clear( &info->time );
284
+ if ( list_empty( parent_info->files ) )
285
+ file_collect_dir_content_( parent_info );
286
+ }
287
+ }
288
+
289
+
290
+ /*
291
+ * file_supported_fmt_resolution() - file modification timestamp resolution
292
+ *
293
+ * Returns the minimum file modification timestamp resolution supported by this
294
+ * Boost Jam implementation. File modification timestamp changes of less than
295
+ * the returned value might not be recognized.
296
+ *
297
+ * Does not take into consideration any OS or file system related restrictions.
298
+ *
299
+ * Return value 0 indicates that any value supported by the OS is also supported
300
+ * here.
301
+ */
302
+
303
+ void file_supported_fmt_resolution( timestamp * const t )
304
+ {
305
+ /* On Windows we support nano-second file modification timestamp resolution,
306
+ * just the same as the Windows OS itself.
307
+ */
308
+ timestamp_init( t, 0, 0 );
309
+ }
310
+
311
+ #endif /* OS_NT */
mosesdecoder/jam-files/engine/fileunix.c ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ /* This file is ALSO:
8
+ * Copyright 2001-2004 David Abrahams.
9
+ * Copyright 2005 Rene Rivera.
10
+ * Distributed under the Boost Software License, Version 1.0.
11
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
12
+ */
13
+
14
+ /*
15
+ * fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
16
+ *
17
+ * External routines:
18
+ * file_mkdir() - create a directory
19
+ * file_supported_fmt_resolution() - file modification timestamp resolution
20
+ *
21
+ * External routines called only via routines in filesys.c:
22
+ * file_collect_dir_content_() - collects directory content information
23
+ * file_dirscan_() - OS specific file_dirscan() implementation
24
+ * file_query_() - query information about a path from the OS
25
+ */
26
+
27
+ #include "jam.h"
28
+ #ifdef USE_FILEUNIX
29
+ #include "filesys.h"
30
+
31
+ #include "object.h"
32
+ #include "pathsys.h"
33
+ #include "strings.h"
34
+
35
+ #include <assert.h>
36
+ #include <stdio.h>
37
+ #include <sys/stat.h> /* needed for mkdir() */
38
+
39
+ #if defined( sun ) || defined( __sun ) || defined( linux )
40
+ # include <unistd.h> /* needed for read and close prototype */
41
+ #endif
42
+
43
+ #if defined( OS_SEQUENT ) || \
44
+ defined( OS_DGUX ) || \
45
+ defined( OS_SCO ) || \
46
+ defined( OS_ISC )
47
+ # define PORTAR 1
48
+ #endif
49
+
50
+ #if defined( OS_RHAPSODY ) || defined( OS_MACOSX ) || defined( OS_NEXT )
51
+ # include <sys/dir.h>
52
+ # include <unistd.h> /* need unistd for rhapsody's proper lseek */
53
+ # define STRUCT_DIRENT struct direct
54
+ #else
55
+ # include <dirent.h>
56
+ # define STRUCT_DIRENT struct dirent
57
+ #endif
58
+
59
+ /*
60
+ * file_collect_dir_content_() - collects directory content information
61
+ */
62
+
63
+ int file_collect_dir_content_( file_info_t * const d )
64
+ {
65
+ LIST * files = L0;
66
+ PATHNAME f;
67
+ DIR * dd;
68
+ STRUCT_DIRENT * dirent;
69
+ string path[ 1 ];
70
+ char const * dirstr;
71
+
72
+ assert( d );
73
+ assert( d->is_dir );
74
+ assert( list_empty( d->files ) );
75
+
76
+ dirstr = object_str( d->name );
77
+
78
+ memset( (char *)&f, '\0', sizeof( f ) );
79
+ f.f_dir.ptr = dirstr;
80
+ f.f_dir.len = strlen( dirstr );
81
+
82
+ if ( !*dirstr ) dirstr = ".";
83
+
84
+ if ( !( dd = opendir( dirstr ) ) )
85
+ return -1;
86
+
87
+ string_new( path );
88
+ while ( ( dirent = readdir( dd ) ) )
89
+ {
90
+ OBJECT * name;
91
+ f.f_base.ptr = dirent->d_name
92
+ #ifdef old_sinix
93
+ - 2 /* Broken structure definition on sinix. */
94
+ #endif
95
+ ;
96
+ f.f_base.len = strlen( f.f_base.ptr );
97
+
98
+ string_truncate( path, 0 );
99
+ path_build( &f, path );
100
+ name = object_new( path->value );
101
+ /* Immediately stat the file to preserve invariants. */
102
+ if ( file_query( name ) )
103
+ files = list_push_back( files, name );
104
+ else
105
+ object_free( name );
106
+ }
107
+ string_free( path );
108
+
109
+ closedir( dd );
110
+
111
+ d->files = files;
112
+ return 0;
113
+ }
114
+
115
+
116
+ /*
117
+ * file_dirscan_() - OS specific file_dirscan() implementation
118
+ */
119
+
120
+ void file_dirscan_( file_info_t * const d, scanback func, void * closure )
121
+ {
122
+ assert( d );
123
+ assert( d->is_dir );
124
+
125
+ /* Special case / : enter it */
126
+ if ( !strcmp( object_str( d->name ), "/" ) )
127
+ (*func)( closure, d->name, 1 /* stat()'ed */, &d->time );
128
+ }
129
+
130
+
131
+ /*
132
+ * file_mkdir() - create a directory
133
+ */
134
+
135
+ int file_mkdir( char const * const path )
136
+ {
137
+ #if defined(__MINGW32__)
138
+ /* MinGW's mkdir() takes only one argument: the path. */
139
+ mkdir(path);
140
+ #else
141
+ /* Explicit cast to remove const modifiers and avoid related compiler
142
+ * warnings displayed when using the intel compiler.
143
+ */
144
+ return mkdir( (char *)path, 0777 );
145
+ #endif
146
+ }
147
+
148
+
149
+ /*
150
+ * file_query_() - query information about a path from the OS
151
+ */
152
+
153
+ void file_query_( file_info_t * const info )
154
+ {
155
+ file_query_posix_( info );
156
+ }
157
+
158
+
159
+ /*
160
+ * file_supported_fmt_resolution() - file modification timestamp resolution
161
+ *
162
+ * Returns the minimum file modification timestamp resolution supported by this
163
+ * Boost Jam implementation. File modification timestamp changes of less than
164
+ * the returned value might not be recognized.
165
+ *
166
+ * Does not take into consideration any OS or file system related restrictions.
167
+ *
168
+ * Return value 0 indicates that any value supported by the OS is also supported
169
+ * here.
170
+ */
171
+
172
+ void file_supported_fmt_resolution( timestamp * const t )
173
+ {
174
+ /* The current implementation does not support file modification timestamp
175
+ * resolution of less than one second.
176
+ */
177
+ timestamp_init( t, 1, 0 );
178
+ }
179
+
180
+ #endif /* USE_FILEUNIX */
mosesdecoder/jam-files/engine/frames.c ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 2001-2004 David Abrahams.
3
+ * Distributed under the Boost Software License, Version 1.0.
4
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
+ */
6
+
7
+ #include "jam.h"
8
+ #include "frames.h"
9
+
10
+
11
+ FRAME * frame_before_python_call;
12
+
13
+
14
+ void frame_init( FRAME * frame )
15
+ {
16
+ frame->prev = 0;
17
+ frame->prev_user = 0;
18
+ lol_init( frame->args );
19
+ frame->module = root_module();
20
+ frame->rulename = "module scope";
21
+ frame->file = 0;
22
+ frame->line = -1;
23
+ }
24
+
25
+
26
+ void frame_free( FRAME * frame )
27
+ {
28
+ lol_free( frame->args );
29
+ }
mosesdecoder/jam-files/engine/function.c ADDED
The diff for this file is too large to render. See raw diff
 
mosesdecoder/jam-files/engine/function.h ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 2011 Steven Watanabe
3
+ * Distributed under the Boost Software License, Version 1.0.
4
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
+ */
6
+
7
+ #ifndef FUNCTION_SW20111123_H
8
+ #define FUNCTION_SW20111123_H
9
+
10
+ #include "object.h"
11
+ #include "frames.h"
12
+ #include "lists.h"
13
+ #include "parse.h"
14
+ #include "strings.h"
15
+
16
+ typedef struct _function FUNCTION;
17
+ typedef struct _stack STACK;
18
+
19
+ STACK * stack_global( void );
20
+ void stack_push( STACK * s, LIST * l );
21
+ LIST * stack_pop( STACK * s );
22
+
23
+ FUNCTION * function_compile( PARSE * parse );
24
+ FUNCTION * function_builtin( LIST * ( * func )( FRAME * frame, int flags ), int flags, const char * * args );
25
+ void function_refer( FUNCTION * );
26
+ void function_free( FUNCTION * );
27
+ OBJECT * function_rulename( FUNCTION * );
28
+ void function_set_rulename( FUNCTION *, OBJECT * );
29
+ void function_location( FUNCTION *, OBJECT * *, int * );
30
+ LIST * function_run( FUNCTION * function, FRAME * frame, STACK * s );
31
+
32
+ FUNCTION * function_compile_actions( const char * actions, OBJECT * file, int line );
33
+ void function_run_actions( FUNCTION * function, FRAME * frame, STACK * s, string * out );
34
+
35
+ FUNCTION * function_bind_variables( FUNCTION * f, module_t * module, int * counter );
36
+ FUNCTION * function_unbind_variables( FUNCTION * f );
37
+
38
+ void function_done( void );
39
+
40
+ #ifdef HAVE_PYTHON
41
+
42
+ FUNCTION * function_python( PyObject * function, PyObject * bjam_signature );
43
+
44
+ #endif
45
+
46
+ #endif
mosesdecoder/jam-files/engine/hash.h ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993, 1995 Christopher Seiwald.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ /*
8
+ * hash.h - simple in-memory hashing routines
9
+ */
10
+
11
+ #ifndef BOOST_JAM_HASH_H
12
+ #define BOOST_JAM_HASH_H
13
+
14
+ #include "object.h"
15
+
16
+ /*
17
+ * An opaque struct representing an item in the hash table. The first element of
18
+ * every struct stored in the table must be an OBJECT * which is treated as the
19
+ * key.
20
+ */
21
+ typedef struct hashdata HASHDATA;
22
+
23
+ /*
24
+ * hashinit() - initialize a hash table, returning a handle.
25
+ *
26
+ * Parameters:
27
+ * datalen - item size
28
+ * name - used for debugging
29
+ */
30
+ struct hash * hashinit( int datalen, char const * name );
31
+
32
+ /*
33
+ * hash_free() - free a hash table, given its handle
34
+ */
35
+ void hash_free( struct hash * );
36
+ void hashdone( struct hash * );
37
+
38
+ /*
39
+ * hashenumerate() - call f(i, data) on each item, i in the hash table. The
40
+ * enumeration order is unspecified.
41
+ */
42
+ void hashenumerate( struct hash *, void (* f)( void *, void * ), void * data );
43
+
44
+ /*
45
+ * hash_insert() - insert a new item in a hash table, or return an existing one.
46
+ *
47
+ * Preconditions:
48
+ * - hp must be a hash table created by hashinit()
49
+ * - key must be an object created by object_new()
50
+ *
51
+ * Postconditions:
52
+ * - if the key does not already exist in the hash table, *found == 0 and the
53
+ * result will be a pointer to an uninitialized item. The key of the new
54
+ * item must be set to a value equal to key before any further operations on
55
+ * the hash table except hashdone().
56
+ * - if the key is present then *found == 1 and the result is a pointer to the
57
+ * existing record.
58
+ */
59
+ HASHDATA * hash_insert( struct hash *, OBJECT * key, int * found );
60
+
61
+ /*
62
+ * hash_find() - find a record in the table or NULL if none exists
63
+ */
64
+ HASHDATA * hash_find( struct hash *, OBJECT * key );
65
+
66
+ struct hashstats {
67
+ int count;
68
+ int num_items;
69
+ int tab_size;
70
+ int item_size;
71
+ int sets;
72
+ int num_hashes;
73
+ };
74
+
75
+ void hashstats_init( struct hashstats * stats );
76
+ void hashstats_add( struct hashstats * stats, struct hash * );
77
+ void hashstats_print( struct hashstats * stats, char const * name );
78
+
79
+ #endif
mosesdecoder/jam-files/engine/hcache.c ADDED
@@ -0,0 +1,519 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * This file has been donated to Jam.
3
+ */
4
+
5
+ /*
6
+ * Craig W. McPheeters, Alias|Wavefront.
7
+ *
8
+ * hcache.c hcache.h - handle cacheing of #includes in source files.
9
+ *
10
+ * Create a cache of files scanned for headers. When starting jam, look for the
11
+ * cache file and load it if present. When finished the binding phase, create a
12
+ * new header cache. The cache contains files, their timestamps and the header
13
+ * files found in their scan. During the binding phase of jam, look in the
14
+ * header cache first for the headers contained in a file. If the cache is
15
+ * present and valid, use its contents. This results in dramatic speedups with
16
+ * large projects (e.g. 3min -> 1min startup for one project.)
17
+ *
18
+ * External routines:
19
+ * hcache_init() - read and parse the local .jamdeps file.
20
+ * hcache_done() - write a new .jamdeps file.
21
+ * hcache() - return list of headers on target. Use cache or do a scan.
22
+ *
23
+ * The dependency file format is an ASCII file with 1 line per target. Each line
24
+ * has the following fields:
25
+ * @boundname@ timestamp_sec timestamp_nsec @file@ @file@ @file@ ...
26
+ */
27
+
28
+ #ifdef OPT_HEADER_CACHE_EXT
29
+
30
+ #include "jam.h"
31
+ #include "hcache.h"
32
+
33
+ #include "hash.h"
34
+ #include "headers.h"
35
+ #include "lists.h"
36
+ #include "modules.h"
37
+ #include "object.h"
38
+ #include "parse.h"
39
+ #include "regexp.h"
40
+ #include "rules.h"
41
+ #include "search.h"
42
+ #include "timestamp.h"
43
+ #include "variable.h"
44
+
45
+ typedef struct hcachedata HCACHEDATA ;
46
+
47
+ struct hcachedata
48
+ {
49
+ OBJECT * boundname;
50
+ timestamp time;
51
+ LIST * includes;
52
+ LIST * hdrscan; /* the HDRSCAN value for this target */
53
+ int age; /* if too old, we will remove it from cache */
54
+ HCACHEDATA * next;
55
+ };
56
+
57
+
58
+ static struct hash * hcachehash = 0;
59
+ static HCACHEDATA * hcachelist = 0;
60
+
61
+ static int queries = 0;
62
+ static int hits = 0;
63
+
64
+ #define CACHE_FILE_VERSION "version 5"
65
+ #define CACHE_RECORD_HEADER "header"
66
+ #define CACHE_RECORD_END "end"
67
+
68
+
69
+ /*
70
+ * Return the name of the header cache file. May return NULL.
71
+ *
72
+ * The user sets this by setting the HCACHEFILE variable in a Jamfile. We cache
73
+ * the result so the user can not change the cache file during header scanning.
74
+ */
75
+
76
+ static const char * cache_name( void )
77
+ {
78
+ static OBJECT * name = 0;
79
+ if ( !name )
80
+ {
81
+ LIST * const hcachevar = var_get( root_module(), constant_HCACHEFILE );
82
+
83
+ if ( !list_empty( hcachevar ) )
84
+ {
85
+ TARGET * const t = bindtarget( list_front( hcachevar ) );
86
+
87
+ pushsettings( root_module(), t->settings );
88
+ /* Do not expect the cache file to be generated, so pass 0 as the
89
+ * third argument to search. Expect the location to be specified via
90
+ * LOCATE, so pass 0 as the fourth arugment.
91
+ */
92
+ object_free( t->boundname );
93
+ t->boundname = search( t->name, &t->time, 0, 0 );
94
+ popsettings( root_module(), t->settings );
95
+
96
+ name = object_copy( t->boundname );
97
+ }
98
+ }
99
+ return name ? object_str( name ) : 0;
100
+ }
101
+
102
+
103
+ /*
104
+ * Return the maximum age a cache entry can have before it is purged from the
105
+ * cache.
106
+ */
107
+
108
+ static int cache_maxage( void )
109
+ {
110
+ int age = 100;
111
+ LIST * const var = var_get( root_module(), constant_HCACHEMAXAGE );
112
+ if ( !list_empty( var ) )
113
+ {
114
+ age = atoi( object_str( list_front( var ) ) );
115
+ if ( age < 0 )
116
+ age = 0;
117
+ }
118
+ return age;
119
+ }
120
+
121
+
122
+ /*
123
+ * Read a netstring. The caveat is that the string can not contain ASCII 0. The
124
+ * returned value is as returned by object_new().
125
+ */
126
+
127
+ OBJECT * read_netstring( FILE * f )
128
+ {
129
+ unsigned long len;
130
+ static char * buf = NULL;
131
+ static unsigned long buf_len = 0;
132
+
133
+ if ( fscanf( f, " %9lu", &len ) != 1 )
134
+ return NULL;
135
+ if ( fgetc( f ) != (int)'\t' )
136
+ return NULL;
137
+
138
+ if ( len > 1024 * 64 )
139
+ return NULL; /* sanity check */
140
+
141
+ if ( len > buf_len )
142
+ {
143
+ unsigned long new_len = buf_len * 2;
144
+ if ( new_len < len )
145
+ new_len = len;
146
+ buf = (char *)BJAM_REALLOC( buf, new_len + 1 );
147
+ if ( buf )
148
+ buf_len = new_len;
149
+ }
150
+
151
+ if ( !buf )
152
+ return NULL;
153
+
154
+ if ( fread( buf, 1, len, f ) != len )
155
+ return NULL;
156
+ if ( fgetc( f ) != (int)'\n' )
157
+ return NULL;
158
+
159
+ buf[ len ] = 0;
160
+ return object_new( buf );
161
+ }
162
+
163
+
164
+ /*
165
+ * Write a netstring.
166
+ */
167
+
168
+ void write_netstring( FILE * f, char const * s )
169
+ {
170
+ if ( !s )
171
+ s = "";
172
+ fprintf( f, "%lu\t%s\n", (long unsigned)strlen( s ), s );
173
+ }
174
+
175
+
176
+ void hcache_init()
177
+ {
178
+ FILE * f;
179
+ OBJECT * version = 0;
180
+ int header_count = 0;
181
+ const char * hcachename;
182
+
183
+ if ( hcachehash )
184
+ return;
185
+
186
+ hcachehash = hashinit( sizeof( HCACHEDATA ), "hcache" );
187
+
188
+ if ( !( hcachename = cache_name() ) )
189
+ return;
190
+
191
+ if ( !( f = fopen( hcachename, "rb" ) ) )
192
+ return;
193
+
194
+ version = read_netstring( f );
195
+
196
+ if ( !version || strcmp( object_str( version ), CACHE_FILE_VERSION ) )
197
+ goto bail;
198
+
199
+ while ( 1 )
200
+ {
201
+ HCACHEDATA cachedata;
202
+ HCACHEDATA * c;
203
+ OBJECT * record_type = 0;
204
+ OBJECT * time_secs_str = 0;
205
+ OBJECT * time_nsecs_str = 0;
206
+ OBJECT * age_str = 0;
207
+ OBJECT * includes_count_str = 0;
208
+ OBJECT * hdrscan_count_str = 0;
209
+ int i;
210
+ int count;
211
+ LIST * l;
212
+ int found;
213
+
214
+ cachedata.boundname = 0;
215
+ cachedata.includes = 0;
216
+ cachedata.hdrscan = 0;
217
+
218
+ record_type = read_netstring( f );
219
+ if ( !record_type )
220
+ {
221
+ fprintf( stderr, "invalid %s\n", hcachename );
222
+ goto cleanup;
223
+ }
224
+ if ( !strcmp( object_str( record_type ), CACHE_RECORD_END ) )
225
+ {
226
+ object_free( record_type );
227
+ break;
228
+ }
229
+ if ( strcmp( object_str( record_type ), CACHE_RECORD_HEADER ) )
230
+ {
231
+ fprintf( stderr, "invalid %s with record separator <%s>\n",
232
+ hcachename, record_type ? object_str( record_type ) : "<null>" );
233
+ goto cleanup;
234
+ }
235
+
236
+ cachedata.boundname = read_netstring( f );
237
+ time_secs_str = read_netstring( f );
238
+ time_nsecs_str = read_netstring( f );
239
+ age_str = read_netstring( f );
240
+ includes_count_str = read_netstring( f );
241
+
242
+ if ( !cachedata.boundname || !time_secs_str || !time_nsecs_str ||
243
+ !age_str || !includes_count_str )
244
+ {
245
+ fprintf( stderr, "invalid %s\n", hcachename );
246
+ goto cleanup;
247
+ }
248
+
249
+ timestamp_init( &cachedata.time, atoi( object_str( time_secs_str ) ),
250
+ atoi( object_str( time_nsecs_str ) ) );
251
+ cachedata.age = atoi( object_str( age_str ) ) + 1;
252
+
253
+ count = atoi( object_str( includes_count_str ) );
254
+ for ( l = L0, i = 0; i < count; ++i )
255
+ {
256
+ OBJECT * const s = read_netstring( f );
257
+ if ( !s )
258
+ {
259
+ fprintf( stderr, "invalid %s\n", hcachename );
260
+ list_free( l );
261
+ goto cleanup;
262
+ }
263
+ l = list_push_back( l, s );
264
+ }
265
+ cachedata.includes = l;
266
+
267
+ hdrscan_count_str = read_netstring( f );
268
+ if ( !hdrscan_count_str )
269
+ {
270
+ fprintf( stderr, "invalid %s\n", hcachename );
271
+ goto cleanup;
272
+ }
273
+
274
+ count = atoi( object_str( hdrscan_count_str ) );
275
+ for ( l = L0, i = 0; i < count; ++i )
276
+ {
277
+ OBJECT * const s = read_netstring( f );
278
+ if ( !s )
279
+ {
280
+ fprintf( stderr, "invalid %s\n", hcachename );
281
+ list_free( l );
282
+ goto cleanup;
283
+ }
284
+ l = list_push_back( l, s );
285
+ }
286
+ cachedata.hdrscan = l;
287
+
288
+ c = (HCACHEDATA *)hash_insert( hcachehash, cachedata.boundname, &found )
289
+ ;
290
+ if ( !found )
291
+ {
292
+ c->boundname = cachedata.boundname;
293
+ c->includes = cachedata.includes;
294
+ c->hdrscan = cachedata.hdrscan;
295
+ c->age = cachedata.age;
296
+ timestamp_copy( &c->time, &cachedata.time );
297
+ }
298
+ else
299
+ {
300
+ fprintf( stderr, "can not insert header cache item, bailing on %s"
301
+ "\n", hcachename );
302
+ goto cleanup;
303
+ }
304
+
305
+ c->next = hcachelist;
306
+ hcachelist = c;
307
+
308
+ ++header_count;
309
+
310
+ object_free( record_type );
311
+ object_free( time_secs_str );
312
+ object_free( time_nsecs_str );
313
+ object_free( age_str );
314
+ object_free( includes_count_str );
315
+ object_free( hdrscan_count_str );
316
+ continue;
317
+
318
+ cleanup:
319
+
320
+ if ( record_type ) object_free( record_type );
321
+ if ( time_secs_str ) object_free( time_secs_str );
322
+ if ( time_nsecs_str ) object_free( time_nsecs_str );
323
+ if ( age_str ) object_free( age_str );
324
+ if ( includes_count_str ) object_free( includes_count_str );
325
+ if ( hdrscan_count_str ) object_free( hdrscan_count_str );
326
+
327
+ if ( cachedata.boundname ) object_free( cachedata.boundname );
328
+ if ( cachedata.includes ) list_free( cachedata.includes );
329
+ if ( cachedata.hdrscan ) list_free( cachedata.hdrscan );
330
+
331
+ goto bail;
332
+ }
333
+
334
+ if ( DEBUG_HEADER )
335
+ printf( "hcache read from file %s\n", hcachename );
336
+
337
+ bail:
338
+ if ( version )
339
+ object_free( version );
340
+ fclose( f );
341
+ }
342
+
343
+
344
+ void hcache_done()
345
+ {
346
+ FILE * f;
347
+ HCACHEDATA * c;
348
+ int header_count = 0;
349
+ const char * hcachename;
350
+ int maxage;
351
+
352
+ if ( !hcachehash )
353
+ return;
354
+
355
+ if ( !( hcachename = cache_name() ) )
356
+ goto cleanup;
357
+
358
+ if ( !( f = fopen( hcachename, "wb" ) ) )
359
+ goto cleanup;
360
+
361
+ maxage = cache_maxage();
362
+
363
+ /* Print out the version. */
364
+ write_netstring( f, CACHE_FILE_VERSION );
365
+
366
+ c = hcachelist;
367
+ for ( c = hcachelist; c; c = c->next )
368
+ {
369
+ LISTITER iter;
370
+ LISTITER end;
371
+ char time_secs_str[ 30 ];
372
+ char time_nsecs_str[ 30 ];
373
+ char age_str[ 30 ];
374
+ char includes_count_str[ 30 ];
375
+ char hdrscan_count_str[ 30 ];
376
+
377
+ if ( maxage == 0 )
378
+ c->age = 0;
379
+ else if ( c->age > maxage )
380
+ continue;
381
+
382
+ sprintf( includes_count_str, "%lu", (long unsigned)list_length(
383
+ c->includes ) );
384
+ sprintf( hdrscan_count_str, "%lu", (long unsigned)list_length(
385
+ c->hdrscan ) );
386
+ sprintf( time_secs_str, "%lu", (long unsigned)c->time.secs );
387
+ sprintf( time_nsecs_str, "%lu", (long unsigned)c->time.nsecs );
388
+ sprintf( age_str, "%lu", (long unsigned)c->age );
389
+
390
+ write_netstring( f, CACHE_RECORD_HEADER );
391
+ write_netstring( f, object_str( c->boundname ) );
392
+ write_netstring( f, time_secs_str );
393
+ write_netstring( f, time_nsecs_str );
394
+ write_netstring( f, age_str );
395
+ write_netstring( f, includes_count_str );
396
+ for ( iter = list_begin( c->includes ), end = list_end( c->includes );
397
+ iter != end; iter = list_next( iter ) )
398
+ write_netstring( f, object_str( list_item( iter ) ) );
399
+ write_netstring( f, hdrscan_count_str );
400
+ for ( iter = list_begin( c->hdrscan ), end = list_end( c->hdrscan );
401
+ iter != end; iter = list_next( iter ) )
402
+ write_netstring( f, object_str( list_item( iter ) ) );
403
+ fputs( "\n", f );
404
+ ++header_count;
405
+ }
406
+ write_netstring( f, CACHE_RECORD_END );
407
+
408
+ if ( DEBUG_HEADER )
409
+ printf( "hcache written to %s. %d dependencies, %.0f%% hit rate\n",
410
+ hcachename, header_count, queries ? 100.0 * hits / queries : 0 );
411
+
412
+ fclose ( f );
413
+
414
+ cleanup:
415
+ for ( c = hcachelist; c; c = c->next )
416
+ {
417
+ list_free( c->includes );
418
+ list_free( c->hdrscan );
419
+ object_free( c->boundname );
420
+ }
421
+
422
+ hcachelist = 0;
423
+ if ( hcachehash )
424
+ hashdone( hcachehash );
425
+ hcachehash = 0;
426
+ }
427
+
428
+
429
+ LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
430
+ {
431
+ HCACHEDATA * c;
432
+
433
+ ++queries;
434
+
435
+ if ( ( c = (HCACHEDATA *)hash_find( hcachehash, t->boundname ) ) )
436
+ {
437
+ if ( !timestamp_cmp( &c->time, &t->time ) )
438
+ {
439
+ LIST * const l1 = hdrscan;
440
+ LIST * const l2 = c->hdrscan;
441
+ LISTITER iter1 = list_begin( l1 );
442
+ LISTITER const end1 = list_end( l1 );
443
+ LISTITER iter2 = list_begin( l2 );
444
+ LISTITER const end2 = list_end( l2 );
445
+ while ( iter1 != end1 && iter2 != end2 )
446
+ {
447
+ if ( !object_equal( list_item( iter1 ), list_item( iter2 ) ) )
448
+ iter1 = end1;
449
+ else
450
+ {
451
+ iter1 = list_next( iter1 );
452
+ iter2 = list_next( iter2 );
453
+ }
454
+ }
455
+ if ( iter1 != end1 || iter2 != end2 )
456
+ {
457
+ if ( DEBUG_HEADER )
458
+ {
459
+ printf( "HDRSCAN out of date in cache for %s\n",
460
+ object_str( t->boundname ) );
461
+ printf(" real : ");
462
+ list_print( hdrscan );
463
+ printf( "\n cached: " );
464
+ list_print( c->hdrscan );
465
+ printf( "\n" );
466
+ }
467
+
468
+ list_free( c->includes );
469
+ list_free( c->hdrscan );
470
+ c->includes = L0;
471
+ c->hdrscan = L0;
472
+ }
473
+ else
474
+ {
475
+ if ( DEBUG_HEADER )
476
+ printf( "using header cache for %s\n", object_str(
477
+ t->boundname ) );
478
+ c->age = 0;
479
+ ++hits;
480
+ return list_copy( c->includes );
481
+ }
482
+ }
483
+ else
484
+ {
485
+ if ( DEBUG_HEADER )
486
+ printf ("header cache out of date for %s\n", object_str(
487
+ t->boundname ) );
488
+ list_free( c->includes );
489
+ list_free( c->hdrscan );
490
+ c->includes = L0;
491
+ c->hdrscan = L0;
492
+ }
493
+ }
494
+ else
495
+ {
496
+ int found;
497
+ c = (HCACHEDATA *)hash_insert( hcachehash, t->boundname, &found );
498
+ if ( !found )
499
+ {
500
+ c->boundname = object_copy( t->boundname );
501
+ c->next = hcachelist;
502
+ hcachelist = c;
503
+ }
504
+ }
505
+
506
+ /* 'c' points at the cache entry. Its out of date. */
507
+ {
508
+ LIST * const l = headers1( L0, t->boundname, rec, re );
509
+
510
+ timestamp_copy( &c->time, &t->time );
511
+ c->age = 0;
512
+ c->includes = list_copy( l );
513
+ c->hdrscan = list_copy( hdrscan );
514
+
515
+ return l;
516
+ }
517
+ }
518
+
519
+ #endif /* OPT_HEADER_CACHE_EXT */
mosesdecoder/jam-files/engine/hdrmacro.h ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993, 1995 Christopher Seiwald.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ /*
8
+ * hdrmacro.h - parses header files for #define MACRO <filename> or
9
+ * #define MACRO "filename" definitions
10
+ */
11
+
12
+ #ifndef HDRMACRO_SW20111118_H
13
+ #define HDRMACRO_SW20111118_H
14
+
15
+ #include "object.h"
16
+ #include "rules.h"
17
+
18
+ void macro_headers( TARGET * );
19
+ OBJECT * macro_header_get( OBJECT * macro_name );
20
+
21
+ #endif
mosesdecoder/jam-files/engine/headers.c ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993, 2000 Christopher Seiwald.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+ /* This file is ALSO:
7
+ * Copyright 2001-2004 David Abrahams.
8
+ * Distributed under the Boost Software License, Version 1.0.
9
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
10
+ */
11
+
12
+ /*
13
+ * headers.c - handle #includes in source files
14
+ *
15
+ * Using regular expressions provided as the variable $(HDRSCAN), headers()
16
+ * searches a file for #include files and phonies up a rule invocation:
17
+ * $(HDRRULE) <target> : <include files> ;
18
+ *
19
+ * External routines:
20
+ * headers() - scan a target for include files and call HDRRULE
21
+ *
22
+ * Internal routines:
23
+ * headers1() - using regexp, scan a file and build include LIST
24
+ */
25
+
26
+ #include "jam.h"
27
+ #include "headers.h"
28
+
29
+ #include "compile.h"
30
+ #include "hdrmacro.h"
31
+ #include "lists.h"
32
+ #include "modules.h"
33
+ #include "object.h"
34
+ #include "parse.h"
35
+ #include "rules.h"
36
+ #include "subst.h"
37
+ #include "variable.h"
38
+
39
+ #ifdef OPT_HEADER_CACHE_EXT
40
+ # include "hcache.h"
41
+ #endif
42
+
43
+ #ifndef OPT_HEADER_CACHE_EXT
44
+ static LIST * headers1( LIST *, OBJECT * file, int rec, regexp * re[] );
45
+ #endif
46
+
47
+
48
+ /*
49
+ * headers() - scan a target for include files and call HDRRULE
50
+ */
51
+
52
+ #define MAXINC 10
53
+
54
+ void headers( TARGET * t )
55
+ {
56
+ LIST * hdrscan;
57
+ LIST * hdrrule;
58
+ #ifndef OPT_HEADER_CACHE_EXT
59
+ LIST * headlist = L0;
60
+ #endif
61
+ regexp * re[ MAXINC ];
62
+ int rec = 0;
63
+ LISTITER iter;
64
+ LISTITER end;
65
+
66
+ hdrscan = var_get( root_module(), constant_HDRSCAN );
67
+ if ( list_empty( hdrscan ) )
68
+ return;
69
+
70
+ hdrrule = var_get( root_module(), constant_HDRRULE );
71
+ if ( list_empty( hdrrule ) )
72
+ return;
73
+
74
+ if ( DEBUG_HEADER )
75
+ printf( "header scan %s\n", object_str( t->name ) );
76
+
77
+ /* Compile all regular expressions in HDRSCAN */
78
+ iter = list_begin( hdrscan );
79
+ end = list_end( hdrscan );
80
+ for ( ; ( rec < MAXINC ) && iter != end; iter = list_next( iter ) )
81
+ {
82
+ re[ rec++ ] = regex_compile( list_item( iter ) );
83
+ }
84
+
85
+ /* Doctor up call to HDRRULE rule */
86
+ /* Call headers1() to get LIST of included files. */
87
+ {
88
+ FRAME frame[ 1 ];
89
+ frame_init( frame );
90
+ lol_add( frame->args, list_new( object_copy( t->name ) ) );
91
+ #ifdef OPT_HEADER_CACHE_EXT
92
+ lol_add( frame->args, hcache( t, rec, re, hdrscan ) );
93
+ #else
94
+ lol_add( frame->args, headers1( headlist, t->boundname, rec, re ) );
95
+ #endif
96
+
97
+ if ( lol_get( frame->args, 1 ) )
98
+ {
99
+ OBJECT * rulename = list_front( hdrrule );
100
+ /* The third argument to HDRRULE is the bound name of $(<). */
101
+ lol_add( frame->args, list_new( object_copy( t->boundname ) ) );
102
+ list_free( evaluate_rule( bindrule( rulename, frame->module ), rulename, frame ) );
103
+ }
104
+
105
+ /* Clean up. */
106
+ frame_free( frame );
107
+ }
108
+ }
109
+
110
+
111
+ /*
112
+ * headers1() - using regexp, scan a file and build include LIST.
113
+ */
114
+
115
+ #ifndef OPT_HEADER_CACHE_EXT
116
+ static
117
+ #endif
118
+ LIST * headers1( LIST * l, OBJECT * file, int rec, regexp * re[] )
119
+ {
120
+ FILE * f;
121
+ char buf[ 1024 ];
122
+ int i;
123
+ static regexp * re_macros = 0;
124
+
125
+ #ifdef OPT_IMPROVED_PATIENCE_EXT
126
+ static int count = 0;
127
+ ++count;
128
+ if ( ( ( count == 100 ) || !( count % 1000 ) ) && DEBUG_MAKE )
129
+ {
130
+ printf( "...patience...\n" );
131
+ fflush( stdout );
132
+ }
133
+ #endif
134
+
135
+ /* The following regexp is used to detect cases where a file is included
136
+ * through a line like "#include MACRO".
137
+ */
138
+ if ( re_macros == 0 )
139
+ {
140
+ OBJECT * const re_str = object_new(
141
+ "#[ \t]*include[ \t]*([A-Za-z][A-Za-z0-9_]*).*$" );
142
+ re_macros = regex_compile( re_str );
143
+ object_free( re_str );
144
+ }
145
+
146
+ if ( !( f = fopen( object_str( file ), "r" ) ) )
147
+ return l;
148
+
149
+ while ( fgets( buf, sizeof( buf ), f ) )
150
+ {
151
+ for ( i = 0; i < rec; ++i )
152
+ if ( regexec( re[ i ], buf ) && re[ i ]->startp[ 1 ] )
153
+ {
154
+ ( (char *)re[ i ]->endp[ 1 ] )[ 0 ] = '\0';
155
+ if ( DEBUG_HEADER )
156
+ printf( "header found: %s\n", re[ i ]->startp[ 1 ] );
157
+ l = list_push_back( l, object_new( re[ i ]->startp[ 1 ] ) );
158
+ }
159
+
160
+ /* Special treatment for #include MACRO. */
161
+ if ( regexec( re_macros, buf ) && re_macros->startp[ 1 ] )
162
+ {
163
+ OBJECT * header_filename;
164
+ OBJECT * macro_name;
165
+
166
+ ( (char *)re_macros->endp[ 1 ] )[ 0 ] = '\0';
167
+
168
+ if ( DEBUG_HEADER )
169
+ printf( "macro header found: %s", re_macros->startp[ 1 ] );
170
+
171
+ macro_name = object_new( re_macros->startp[ 1 ] );
172
+ header_filename = macro_header_get( macro_name );
173
+ object_free( macro_name );
174
+ if ( header_filename )
175
+ {
176
+ if ( DEBUG_HEADER )
177
+ printf( " resolved to '%s'\n", object_str( header_filename )
178
+ );
179
+ l = list_push_back( l, object_copy( header_filename ) );
180
+ }
181
+ else
182
+ {
183
+ if ( DEBUG_HEADER )
184
+ printf( " ignored !!\n" );
185
+ }
186
+ }
187
+ }
188
+
189
+ fclose( f );
190
+ return l;
191
+ }
192
+
193
+
194
+ void regerror( char const * s )
195
+ {
196
+ printf( "re error %s\n", s );
197
+ }
mosesdecoder/jam-files/engine/jam.c ADDED
@@ -0,0 +1,656 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * /+\
3
+ * +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4
+ * \+/
5
+ *
6
+ * This file is part of jam.
7
+ *
8
+ * License is hereby granted to use this software and distribute it freely, as
9
+ * long as this copyright notice is retained and modifications are clearly
10
+ * marked.
11
+ *
12
+ * ALL WARRANTIES ARE HEREBY DISCLAIMED.
13
+ */
14
+
15
+ /* This file is ALSO:
16
+ * Copyright 2001-2004 David Abrahams.
17
+ * Distributed under the Boost Software License, Version 1.0.
18
+ * (See accompanying file LICENSE_1_0.txt or copy at
19
+ * http://www.boost.org/LICENSE_1_0.txt)
20
+ */
21
+
22
+ /*
23
+ * jam.c - make redux
24
+ *
25
+ * See Jam.html for usage information.
26
+ *
27
+ * These comments document the code.
28
+ *
29
+ * The top half of the code is structured such:
30
+ *
31
+ * jam
32
+ * / | \
33
+ * +---+ | \
34
+ * / | \
35
+ * jamgram option \
36
+ * / | \ \
37
+ * / | \ \
38
+ * / | \ |
39
+ * scan | compile make
40
+ * | | / | \ / | \
41
+ * | | / | \ / | \
42
+ * | | / | \ / | \
43
+ * jambase parse | rules search make1
44
+ * | | | \
45
+ * | | | \
46
+ * | | | \
47
+ * builtins timestamp command execute
48
+ * |
49
+ * |
50
+ * |
51
+ * filesys
52
+ *
53
+ *
54
+ * The support routines are called by all of the above, but themselves are
55
+ * layered thus:
56
+ *
57
+ * variable|expand
58
+ * / | |
59
+ * / | |
60
+ * / | |
61
+ * lists | pathsys
62
+ * \ |
63
+ * \ hash
64
+ * \ |
65
+ * \ |
66
+ * \ |
67
+ * \ |
68
+ * \ |
69
+ * object
70
+ *
71
+ * Roughly, the modules are:
72
+ *
73
+ * builtins.c - jam's built-in rules
74
+ * command.c - maintain lists of commands
75
+ * compile.c - compile parsed jam statements
76
+ * exec*.c - execute a shell script on a specific OS
77
+ * file*.c - scan directories and archives on a specific OS
78
+ * hash.c - simple in-memory hashing routines
79
+ * hdrmacro.c - handle header file parsing for filename macro definitions
80
+ * headers.c - handle #includes in source files
81
+ * jambase.c - compilable copy of Jambase
82
+ * jamgram.y - jam grammar
83
+ * lists.c - maintain lists of strings
84
+ * make.c - bring a target up to date, once rules are in place
85
+ * make1.c - execute command to bring targets up to date
86
+ * object.c - string manipulation routines
87
+ * option.c - command line option processing
88
+ * parse.c - make and destroy parse trees as driven by the parser
89
+ * path*.c - manipulate file names on a specific OS
90
+ * hash.c - simple in-memory hashing routines
91
+ * regexp.c - Henry Spencer's regexp
92
+ * rules.c - access to RULEs, TARGETs, and ACTIONs
93
+ * scan.c - the jam yacc scanner
94
+ * search.c - find a target along $(SEARCH) or $(LOCATE)
95
+ * timestamp.c - get the timestamp of a file or archive member
96
+ * variable.c - handle jam multi-element variables
97
+ */
98
+
99
+
100
+ #include "jam.h"
101
+ #include "patchlevel.h"
102
+
103
+ #include "builtins.h"
104
+ #include "class.h"
105
+ #include "compile.h"
106
+ #include "constants.h"
107
+ #include "filesys.h"
108
+ #include "function.h"
109
+ #include "hcache.h"
110
+ #include "lists.h"
111
+ #include "make.h"
112
+ #include "object.h"
113
+ #include "option.h"
114
+ #include "output.h"
115
+ #include "parse.h"
116
+ #include "cwd.h"
117
+ #include "rules.h"
118
+ #include "scan.h"
119
+ #include "search.h"
120
+ #include "strings.h"
121
+ #include "timestamp.h"
122
+ #include "variable.h"
123
+
124
+ /* Macintosh is "special" */
125
+ #ifdef OS_MAC
126
+ # include <QuickDraw.h>
127
+ #endif
128
+
129
+ /* And UNIX for this. */
130
+ #ifdef unix
131
+ # include <sys/utsname.h>
132
+ # include <signal.h>
133
+ #endif
134
+
135
+ struct globs globs =
136
+ {
137
+ 0, /* noexec */
138
+ 1, /* jobs */
139
+ 0, /* quitquick */
140
+ 0, /* newestfirst */
141
+ 0, /* pipes action stdout and stderr merged to action output */
142
+ #ifdef OS_MAC
143
+ { 0, 0 }, /* debug - suppress tracing output */
144
+ #else
145
+ { 0, 1 }, /* debug ... */
146
+ #endif
147
+ 0, /* output commands, not run them */
148
+ 0, /* action timeout */
149
+ 0 /* maximum buffer size zero is all output */
150
+ };
151
+
152
+ /* Symbols to be defined as true for use in Jambase. */
153
+ static char * othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 };
154
+
155
+
156
+ /* Known for sure:
157
+ * mac needs arg_enviro
158
+ * OS2 needs extern environ
159
+ */
160
+
161
+ #ifdef OS_MAC
162
+ # define use_environ arg_environ
163
+ # ifdef MPW
164
+ QDGlobals qd;
165
+ # endif
166
+ #endif
167
+
168
+ /* on Win32-LCC */
169
+ #if defined( OS_NT ) && defined( __LCC__ )
170
+ # define use_environ _environ
171
+ #endif
172
+
173
+ #if defined( __MWERKS__)
174
+ # define use_environ _environ
175
+ extern char * * _environ;
176
+ #endif
177
+
178
+ #ifndef use_environ
179
+ # define use_environ environ
180
+ # if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
181
+ extern char **environ;
182
+ # endif
183
+ #endif
184
+
185
+ #if YYDEBUG != 0
186
+ extern int yydebug;
187
+ #endif
188
+
189
+ #ifndef NDEBUG
190
+ static void run_unit_tests()
191
+ {
192
+ # if defined( USE_EXECNT )
193
+ extern void execnt_unit_test();
194
+ execnt_unit_test();
195
+ # endif
196
+ string_unit_test();
197
+ }
198
+ #endif
199
+
200
+ int anyhow = 0;
201
+
202
+ #ifdef HAVE_PYTHON
203
+ extern PyObject * bjam_call ( PyObject * self, PyObject * args );
204
+ extern PyObject * bjam_import_rule ( PyObject * self, PyObject * args );
205
+ extern PyObject * bjam_define_action( PyObject * self, PyObject * args );
206
+ extern PyObject * bjam_variable ( PyObject * self, PyObject * args );
207
+ extern PyObject * bjam_backtrace ( PyObject * self, PyObject * args );
208
+ extern PyObject * bjam_caller ( PyObject * self, PyObject * args );
209
+ #endif
210
+
211
+ void regex_done();
212
+
213
+ char const * saved_argv0;
214
+
215
+ int main( int argc, char * * argv, char * * arg_environ )
216
+ {
217
+ int n;
218
+ char * s;
219
+ struct bjam_option optv[ N_OPTS ];
220
+ char const * all = "all";
221
+ int status;
222
+ int arg_c = argc;
223
+ char * * arg_v = argv;
224
+ char const * progname = argv[ 0 ];
225
+ module_t * environ_module;
226
+
227
+ saved_argv0 = argv[ 0 ];
228
+
229
+ BJAM_MEM_INIT();
230
+
231
+ #ifdef OS_MAC
232
+ InitGraf( &qd.thePort );
233
+ #endif
234
+
235
+ --argc;
236
+ ++argv;
237
+
238
+ if ( getoptions( argc, argv, "-:l:m:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
239
+ {
240
+ printf( "\nusage: %s [ options ] targets...\n\n", progname );
241
+
242
+ printf( "-a Build all targets, even if they are current.\n" );
243
+ printf( "-dx Set the debug level to x (0-9).\n" );
244
+ printf( "-fx Read x instead of Jambase.\n" );
245
+ /* printf( "-g Build from newest sources first.\n" ); */
246
+ printf( "-jx Run up to x shell commands concurrently.\n" );
247
+ printf( "-lx Limit actions to x number of seconds after which they are stopped.\n" );
248
+ printf( "-mx Maximum target output saved (kb), default is to save all output.\n" );
249
+ printf( "-n Don't actually execute the updating actions.\n" );
250
+ printf( "-ox Write the updating actions to file x.\n" );
251
+ printf( "-px x=0, pipes action stdout and stderr merged into action output.\n" );
252
+ printf( "-q Quit quickly as soon as a target fails.\n" );
253
+ printf( "-sx=y Set variable x=y, overriding environment.\n" );
254
+ printf( "-tx Rebuild x, even if it is up-to-date.\n" );
255
+ printf( "-v Print the version of jam and exit.\n" );
256
+ printf( "--x Option is ignored.\n\n" );
257
+
258
+ exit( EXITBAD );
259
+ }
260
+
261
+ /* Version info. */
262
+ if ( ( s = getoptval( optv, 'v', 0 ) ) )
263
+ {
264
+ printf( "Boost.Jam Version %s. %s.\n", VERSION, OSMINOR );
265
+ printf( " Copyright 1993-2002 Christopher Seiwald and Perforce "
266
+ "Software, Inc.\n" );
267
+ printf( " Copyright 2001 David Turner.\n" );
268
+ printf( " Copyright 2001-2004 David Abrahams.\n" );
269
+ printf( " Copyright 2002-2008 Rene Rivera.\n" );
270
+ printf( " Copyright 2003-2008 Vladimir Prus.\n" );
271
+ return EXITOK;
272
+ }
273
+
274
+ /* Pick up interesting options. */
275
+ if ( ( s = getoptval( optv, 'n', 0 ) ) )
276
+ {
277
+ ++globs.noexec;
278
+ globs.debug[ 2 ] = 1;
279
+ }
280
+
281
+ if ( ( s = getoptval( optv, 'p', 0 ) ) )
282
+ {
283
+ /* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action
284
+ * stdout and stderr.
285
+ */
286
+ globs.pipe_action = atoi( s );
287
+ if ( globs.pipe_action < 0 || 3 < globs.pipe_action )
288
+ {
289
+ printf( "Invalid pipe descriptor '%d', valid values are -p[0..3]."
290
+ "\n", globs.pipe_action );
291
+ exit( EXITBAD );
292
+ }
293
+ }
294
+
295
+ if ( ( s = getoptval( optv, 'q', 0 ) ) )
296
+ globs.quitquick = 1;
297
+
298
+ if ( ( s = getoptval( optv, 'a', 0 ) ) )
299
+ anyhow++;
300
+
301
+ if ( ( s = getoptval( optv, 'j', 0 ) ) )
302
+ {
303
+ globs.jobs = atoi( s );
304
+ if ( globs.jobs < 1 || globs.jobs > MAXJOBS )
305
+ {
306
+ printf( "Invalid value for the '-j' option, valid values are 1 "
307
+ "through %d.\n", MAXJOBS );
308
+ exit( EXITBAD );
309
+ }
310
+ }
311
+
312
+ if ( ( s = getoptval( optv, 'g', 0 ) ) )
313
+ globs.newestfirst = 1;
314
+
315
+ if ( ( s = getoptval( optv, 'l', 0 ) ) )
316
+ globs.timeout = atoi( s );
317
+
318
+ if ( ( s = getoptval( optv, 'm', 0 ) ) )
319
+ globs.max_buf = atoi( s ) * 1024; /* convert to kb */
320
+
321
+ /* Turn on/off debugging */
322
+ for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n )
323
+ {
324
+ int i;
325
+
326
+ /* First -d, turn off defaults. */
327
+ if ( !n )
328
+ for ( i = 0; i < DEBUG_MAX; ++i )
329
+ globs.debug[i] = 0;
330
+
331
+ i = atoi( s );
332
+
333
+ if ( ( i < 0 ) || ( i >= DEBUG_MAX ) )
334
+ {
335
+ printf( "Invalid debug level '%s'.\n", s );
336
+ continue;
337
+ }
338
+
339
+ /* n turns on levels 1-n. */
340
+ /* +n turns on level n. */
341
+ if ( *s == '+' )
342
+ globs.debug[ i ] = 1;
343
+ else while ( i )
344
+ globs.debug[ i-- ] = 1;
345
+ }
346
+
347
+ constants_init();
348
+ cwd_init();
349
+
350
+ {
351
+ PROFILE_ENTER( MAIN );
352
+
353
+ #ifdef HAVE_PYTHON
354
+ {
355
+ PROFILE_ENTER( MAIN_PYTHON );
356
+ Py_Initialize();
357
+ {
358
+ static PyMethodDef BjamMethods[] = {
359
+ {"call", bjam_call, METH_VARARGS,
360
+ "Call the specified bjam rule."},
361
+ {"import_rule", bjam_import_rule, METH_VARARGS,
362
+ "Imports Python callable to bjam."},
363
+ {"define_action", bjam_define_action, METH_VARARGS,
364
+ "Defines a command line action."},
365
+ {"variable", bjam_variable, METH_VARARGS,
366
+ "Obtains a variable from bjam's global module."},
367
+ {"backtrace", bjam_backtrace, METH_VARARGS,
368
+ "Returns bjam backtrace from the last call into Python."},
369
+ {"caller", bjam_caller, METH_VARARGS,
370
+ "Returns the module from which the last call into Python is made."},
371
+ {NULL, NULL, 0, NULL}
372
+ };
373
+
374
+ Py_InitModule( "bjam", BjamMethods );
375
+ }
376
+ PROFILE_EXIT( MAIN_PYTHON );
377
+ }
378
+ #endif
379
+
380
+ #ifndef NDEBUG
381
+ run_unit_tests();
382
+ #endif
383
+ #if YYDEBUG != 0
384
+ if ( DEBUG_PARSE )
385
+ yydebug = 1;
386
+ #endif
387
+
388
+ /* Set JAMDATE. */
389
+ {
390
+ timestamp current;
391
+ timestamp_current( &current );
392
+ var_set( root_module(), constant_JAMDATE, list_new( outf_time(
393
+ &current ) ), VAR_SET );
394
+ }
395
+
396
+ /* Set JAM_VERSION. */
397
+ var_set( root_module(), constant_JAM_VERSION,
398
+ list_push_back( list_push_back( list_new(
399
+ object_new( VERSION_MAJOR_SYM ) ),
400
+ object_new( VERSION_MINOR_SYM ) ),
401
+ object_new( VERSION_PATCH_SYM ) ),
402
+ VAR_SET );
403
+
404
+ /* Set JAMUNAME. */
405
+ #ifdef unix
406
+ {
407
+ struct utsname u;
408
+
409
+ if ( uname( &u ) >= 0 )
410
+ {
411
+ var_set( root_module(), constant_JAMUNAME,
412
+ list_push_back(
413
+ list_push_back(
414
+ list_push_back(
415
+ list_push_back(
416
+ list_new(
417
+ object_new( u.sysname ) ),
418
+ object_new( u.nodename ) ),
419
+ object_new( u.release ) ),
420
+ object_new( u.version ) ),
421
+ object_new( u.machine ) ), VAR_SET );
422
+ }
423
+ }
424
+ #endif /* unix */
425
+
426
+ /* Set JAM_TIMESTAMP_RESOLUTION. */
427
+ {
428
+ timestamp fmt_resolution[ 1 ];
429
+ file_supported_fmt_resolution( fmt_resolution );
430
+ var_set( root_module(), constant_JAM_TIMESTAMP_RESOLUTION, list_new(
431
+ object_new( timestamp_timestr( fmt_resolution ) ) ), VAR_SET );
432
+ }
433
+
434
+ /* Load up environment variables. */
435
+
436
+ /* First into the global module, with splitting, for backward
437
+ * compatibility.
438
+ */
439
+ var_defines( root_module(), use_environ, 1 );
440
+
441
+ environ_module = bindmodule( constant_ENVIRON );
442
+ /* Then into .ENVIRON, without splitting. */
443
+ var_defines( environ_module, use_environ, 0 );
444
+
445
+ /*
446
+ * Jam defined variables OS & OSPLAT. We load them after environment, so
447
+ * that setting OS in environment does not change Jam's notion of the
448
+ * current platform.
449
+ */
450
+ var_defines( root_module(), othersyms, 1 );
451
+
452
+ /* Load up variables set on command line. */
453
+ for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n )
454
+ {
455
+ char * symv[ 2 ];
456
+ symv[ 0 ] = s;
457
+ symv[ 1 ] = 0;
458
+ var_defines( root_module(), symv, 1 );
459
+ var_defines( environ_module, symv, 0 );
460
+ }
461
+
462
+ /* Set the ARGV to reflect the complete list of arguments of invocation.
463
+ */
464
+ for ( n = 0; n < arg_c; ++n )
465
+ var_set( root_module(), constant_ARGV, list_new( object_new(
466
+ arg_v[ n ] ) ), VAR_APPEND );
467
+
468
+ /* Initialize built-in rules. */
469
+ load_builtins();
470
+
471
+ /* Add the targets in the command line to the update list. */
472
+ for ( n = 1; n < arg_c; ++n )
473
+ {
474
+ if ( arg_v[ n ][ 0 ] == '-' )
475
+ {
476
+ char * f = "-:l:d:j:f:gs:t:ano:qv";
477
+ for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break;
478
+ if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n;
479
+ }
480
+ else
481
+ {
482
+ OBJECT * const target = object_new( arg_v[ n ] );
483
+ mark_target_for_updating( target );
484
+ object_free( target );
485
+ }
486
+ }
487
+
488
+ if ( list_empty( targets_to_update() ) )
489
+ mark_target_for_updating( constant_all );
490
+
491
+ /* Parse ruleset. */
492
+ {
493
+ FRAME frame[ 1 ];
494
+ frame_init( frame );
495
+ for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n )
496
+ {
497
+ OBJECT * const filename = object_new( s );
498
+ parse_file( filename, frame );
499
+ object_free( filename );
500
+ }
501
+
502
+ if ( !n )
503
+ parse_file( constant_plus, frame );
504
+ }
505
+
506
+ status = yyanyerrors();
507
+
508
+ /* Manually touch -t targets. */
509
+ for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n )
510
+ {
511
+ OBJECT * const target = object_new( s );
512
+ touch_target( target );
513
+ object_free( target );
514
+ }
515
+
516
+ /* If an output file is specified, set globs.cmdout to that. */
517
+ if ( ( s = getoptval( optv, 'o', 0 ) ) )
518
+ {
519
+ if ( !( globs.cmdout = fopen( s, "w" ) ) )
520
+ {
521
+ printf( "Failed to write to '%s'\n", s );
522
+ exit( EXITBAD );
523
+ }
524
+ ++globs.noexec;
525
+ }
526
+
527
+ /* The build system may set the PARALLELISM variable to override -j
528
+ * options.
529
+ */
530
+ {
531
+ LIST * const p = var_get( root_module(), constant_PARALLELISM );
532
+ if ( !list_empty( p ) )
533
+ {
534
+ int const j = atoi( object_str( list_front( p ) ) );
535
+ if ( j < 1 || j > MAXJOBS )
536
+ printf( "Invalid value of PARALLELISM: %s. Valid values "
537
+ "are 1 through %d.\n", object_str( list_front( p ) ),
538
+ MAXJOBS );
539
+ else
540
+ globs.jobs = j;
541
+ }
542
+ }
543
+
544
+ /* KEEP_GOING overrides -q option. */
545
+ {
546
+ LIST * const p = var_get( root_module(), constant_KEEP_GOING );
547
+ if ( !list_empty( p ) )
548
+ globs.quitquick = atoi( object_str( list_front( p ) ) ) ? 0 : 1;
549
+ }
550
+
551
+ /* Now make target. */
552
+ {
553
+ PROFILE_ENTER( MAIN_MAKE );
554
+ LIST * const targets = targets_to_update();
555
+ if ( !list_empty( targets ) )
556
+ status |= make( targets, anyhow );
557
+ else
558
+ status = last_update_now_status;
559
+ PROFILE_EXIT( MAIN_MAKE );
560
+ }
561
+
562
+ PROFILE_EXIT( MAIN );
563
+ }
564
+
565
+ if ( DEBUG_PROFILE )
566
+ profile_dump();
567
+
568
+
569
+ #ifdef OPT_HEADER_CACHE_EXT
570
+ hcache_done();
571
+ #endif
572
+
573
+ clear_targets_to_update();
574
+
575
+ /* Widely scattered cleanup. */
576
+ property_set_done();
577
+ file_done();
578
+ rules_done();
579
+ timestamp_done();
580
+ search_done();
581
+ class_done();
582
+ modules_done();
583
+ regex_done();
584
+ cwd_done();
585
+ path_done();
586
+ function_done();
587
+ list_done();
588
+ constants_done();
589
+ object_done();
590
+
591
+ /* Close cmdout. */
592
+ if ( globs.cmdout )
593
+ fclose( globs.cmdout );
594
+
595
+ #ifdef HAVE_PYTHON
596
+ Py_Finalize();
597
+ #endif
598
+
599
+ BJAM_MEM_CLOSE();
600
+
601
+ return status ? EXITBAD : EXITOK;
602
+ }
603
+
604
+
605
+ /*
606
+ * executable_path()
607
+ */
608
+
609
+ #if defined(_WIN32)
610
+ # define WIN32_LEAN_AND_MEAN
611
+ # include <windows.h>
612
+ char * executable_path( char const * argv0 )
613
+ {
614
+ char buf[ 1024 ];
615
+ DWORD const ret = GetModuleFileName( NULL, buf, sizeof( buf ) );
616
+ return ( !ret || ret == sizeof( buf ) ) ? NULL : strdup( buf );
617
+ }
618
+ #elif defined(__APPLE__) /* Not tested */
619
+ # include <mach-o/dyld.h>
620
+ char *executable_path( char const * argv0 )
621
+ {
622
+ char buf[ 1024 ];
623
+ uint32_t size = sizeof( buf );
624
+ return _NSGetExecutablePath( buf, &size ) ? NULL : strdup( buf );
625
+ }
626
+ #elif defined(sun) || defined(__sun) /* Not tested */
627
+ # include <stdlib.h>
628
+ char * executable_path( char const * argv0 )
629
+ {
630
+ return strdup( getexecname() );
631
+ }
632
+ #elif defined(__FreeBSD__)
633
+ # include <sys/sysctl.h>
634
+ char * executable_path( char const * argv0 )
635
+ {
636
+ int mib[ 4 ] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
637
+ char buf[ 1024 ];
638
+ size_t size = sizeof( buf );
639
+ sysctl( mib, 4, buf, &size, NULL, 0 );
640
+ return ( !size || size == sizeof( buf ) ) ? NULL : strndup( buf, size );
641
+ }
642
+ #elif defined(__linux__)
643
+ # include <unistd.h>
644
+ char * executable_path( char const * argv0 )
645
+ {
646
+ char buf[ 1024 ];
647
+ ssize_t const ret = readlink( "/proc/self/exe", buf, sizeof( buf ) );
648
+ return ( !ret || ret == sizeof( buf ) ) ? NULL : strndup( buf, ret );
649
+ }
650
+ #else
651
+ char * executable_path( char const * argv0 )
652
+ {
653
+ /* If argv0 is an absolute path, assume it is the right absolute path. */
654
+ return argv0[ 0 ] == '/' ? strdup( argv0 ) : NULL;
655
+ }
656
+ #endif
mosesdecoder/jam-files/engine/jam.h ADDED
@@ -0,0 +1,475 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright 1993, 1995 Christopher Seiwald.
3
+ *
4
+ * This file is part of Jam - see jam.c for Copyright information.
5
+ */
6
+
7
+ /* This file is ALSO:
8
+ * Copyright 2001-2004 David Abrahams.
9
+ * Distributed under the Boost Software License, Version 1.0.
10
+ * (See accompanying file LICENSE_1_0.txt or copy at
11
+ * http://www.boost.org/LICENSE_1_0.txt)
12
+ */
13
+
14
+ /*
15
+ * jam.h - includes and globals for jam
16
+ */
17
+
18
+ #ifndef JAM_H_VP_2003_08_01
19
+ #define JAM_H_VP_2003_08_01
20
+
21
+ #ifdef HAVE_PYTHON
22
+ #include <Python.h>
23
+ #endif
24
+
25
+ /* Assume popen support is available unless known otherwise. */
26
+ #define HAVE_POPEN 1
27
+
28
+ /*
29
+ * Windows NT
30
+ */
31
+
32
+ #ifdef NT
33
+
34
+ #include <ctype.h>
35
+ #include <fcntl.h>
36
+ #include <malloc.h>
37
+ #ifndef __MWERKS__
38
+ #include <memory.h>
39
+ #endif
40
+ #include <stdio.h>
41
+ #include <stdlib.h>
42
+ #include <signal.h>
43
+ #include <string.h>
44
+ #include <time.h>
45
+
46
+ #define OSMAJOR "NT=true"
47
+ #define OSMINOR "OS=NT"
48
+ #define OS_NT
49
+ #define SPLITPATH ';'
50
+ #define MAXLINE (undefined__see_execnt_c) /* max chars per command line */
51
+ #define USE_EXECNT
52
+ #define PATH_DELIM '\\'
53
+
54
+ /* AS400 cross-compile from NT. */
55
+
56
+ #ifdef AS400
57
+ #undef OSMINOR
58
+ #undef OSMAJOR
59
+ #define OSMAJOR "AS400=true"
60
+ #define OSMINOR "OS=AS400"
61
+ #define OS_AS400
62
+ #endif
63
+
64
+ /* Metrowerks Standard Library on Windows. */
65
+
66
+ #ifdef __MSL__
67
+ #undef HAVE_POPEN
68
+ #endif
69
+
70
+ #endif /* #ifdef NT */
71
+
72
+
73
+ /*
74
+ * Windows MingW32
75
+ */
76
+
77
+ #ifdef __MINGW32__
78
+
79
+ #include <fcntl.h>
80
+ #include <stdlib.h>
81
+ #include <stdio.h>
82
+ #include <ctype.h>
83
+ #include <malloc.h>
84
+ #include <memory.h>
85
+ #include <signal.h>
86
+ #include <string.h>
87
+ #include <time.h>
88
+
89
+ #define OSMAJOR "MINGW=true"
90
+ #define OSMINOR "OS=MINGW"
91
+ #define OS_NT
92
+ #define SPLITPATH ';'
93
+ #define MAXLINE 996 /* max chars per command line */
94
+ #define USE_EXECUNIX
95
+ #define PATH_DELIM '\\'
96
+
97
+ #endif /* #ifdef MINGW */
98
+
99
+
100
+ /*
101
+ * God fearing UNIX.
102
+ */
103
+
104
+ #ifndef OSMINOR
105
+
106
+ #define OSMAJOR "UNIX=true"
107
+ #define USE_EXECUNIX
108
+ #define USE_FILEUNIX
109
+ #define PATH_DELIM '/'
110
+
111
+ #ifdef _AIX
112
+ #define unix
113
+ #define MAXLINE 23552 /* 24k - 1k, max chars per command line */
114
+ #define OSMINOR "OS=AIX"
115
+ #define OS_AIX
116
+ #define NO_VFORK
117
+ #endif
118
+ #ifdef AMIGA
119
+ #define OSMINOR "OS=AMIGA"
120
+ #define OS_AMIGA
121
+ #endif
122
+ #ifdef __BEOS__
123
+ #define unix
124
+ #define OSMINOR "OS=BEOS"
125
+ #define OS_BEOS
126
+ #define NO_VFORK
127
+ #endif
128
+ #ifdef __bsdi__
129
+ #define OSMINOR "OS=BSDI"
130
+ #define OS_BSDI
131
+ #endif
132
+ #if defined (COHERENT) && defined (_I386)
133
+ #define OSMINOR "OS=COHERENT"
134
+ #define OS_COHERENT
135
+ #define NO_VFORK
136
+ #endif
137
+ #if defined(__cygwin__) || defined(__CYGWIN__)
138
+ #define OSMINOR "OS=CYGWIN"
139
+ #define OS_CYGWIN
140
+ #endif
141
+ #if defined(__FreeBSD__) && !defined(__DragonFly__)
142
+ #define OSMINOR "OS=FREEBSD"
143
+ #define OS_FREEBSD
144
+ #endif
145
+ #ifdef __DragonFly__
146
+ #define OSMINOR "OS=DRAGONFLYBSD"
147
+ #define OS_DRAGONFLYBSD
148
+ #endif
149
+ #ifdef __DGUX__
150
+ #define OSMINOR "OS=DGUX"
151
+ #define OS_DGUX
152
+ #endif
153
+ #ifdef __hpux
154
+ #define OSMINOR "OS=HPUX"
155
+ #define OS_HPUX
156
+ #endif
157
+ #ifdef __OPENNT
158
+ #define unix
159
+ #define OSMINOR "OS=INTERIX"
160
+ #define OS_INTERIX
161
+ #define NO_VFORK
162
+ #endif
163
+ #ifdef __sgi
164
+ #define OSMINOR "OS=IRIX"
165
+ #define OS_IRIX
166
+ #define NO_VFORK
167
+ #endif
168
+ #ifdef __ISC
169
+ #define OSMINOR "OS=ISC"
170
+ #define OS_ISC
171
+ #define NO_VFORK
172
+ #endif
173
+ #ifdef linux
174
+ #define OSMINOR "OS=LINUX"
175
+ #define OS_LINUX
176
+ #endif
177
+ #ifdef __Lynx__
178
+ #define OSMINOR "OS=LYNX"
179
+ #define OS_LYNX
180
+ #define NO_VFORK
181
+ #define unix
182
+ #endif
183
+ #ifdef __MACHTEN__
184
+ #define OSMINOR "OS=MACHTEN"
185
+ #define OS_MACHTEN
186
+ #endif
187
+ #ifdef mpeix
188
+ #define unix
189
+ #define OSMINOR "OS=MPEIX"
190
+ #define OS_MPEIX
191
+ #define NO_VFORK
192
+ #endif
193
+ #ifdef __MVS__
194
+ #define unix
195
+ #define OSMINOR "OS=MVS"
196
+ #define OS_MVS
197
+ #endif
198
+ #ifdef _ATT4
199
+ #define OSMINOR "OS=NCR"
200
+ #define OS_NCR
201
+ #endif
202
+ #ifdef __NetBSD__
203
+ #define unix
204
+ #define OSMINOR "OS=NETBSD"
205
+ #define OS_NETBSD
206
+ #define NO_VFORK
207
+ #endif
208
+ #ifdef __QNX__
209
+ #define unix
210
+ #ifdef __QNXNTO__
211
+ #define OSMINOR "OS=QNXNTO"
212
+ #define OS_QNXNTO
213
+ #else
214
+ #define OSMINOR "OS=QNX"
215
+ #define OS_QNX
216
+ #define NO_VFORK
217
+ #define MAXLINE 996 /* max chars per command line */
218
+ #endif
219
+ #endif
220
+ #ifdef NeXT
221
+ #ifdef __APPLE__
222
+ #define OSMINOR "OS=RHAPSODY"
223
+ #define OS_RHAPSODY
224
+ #else
225
+ #define OSMINOR "OS=NEXT"
226
+ #define OS_NEXT
227
+ #endif
228
+ #endif
229
+ #ifdef __APPLE__
230
+ #define unix
231
+ #define OSMINOR "OS=MACOSX"
232
+ #define OS_MACOSX
233
+ #endif
234
+ #ifdef __osf__
235
+ #ifndef unix
236
+ #define unix
237
+ #endif
238
+ #define OSMINOR "OS=OSF"
239
+ #define OS_OSF
240
+ #endif
241
+ #ifdef _SEQUENT_
242
+ #define OSMINOR "OS=PTX"
243
+ #define OS_PTX
244
+ #endif
245
+ #ifdef M_XENIX
246
+ #define OSMINOR "OS=SCO"
247
+ #define OS_SCO
248
+ #define NO_VFORK
249
+ #endif
250
+ #ifdef sinix
251
+ #define unix
252
+ #define OSMINOR "OS=SINIX"
253
+ #define OS_SINIX
254
+ #endif
255
+ #ifdef sun
256
+ #if defined(__svr4__) || defined(__SVR4)
257
+ #define OSMINOR "OS=SOLARIS"
258
+ #define OS_SOLARIS
259
+ #else
260
+ #define OSMINOR "OS=SUNOS"
261
+ #define OS_SUNOS
262
+ #endif
263
+ #endif
264
+ #ifdef ultrix
265
+ #define OSMINOR "OS=ULTRIX"
266
+ #define OS_ULTRIX
267
+ #endif
268
+ #ifdef _UNICOS
269
+ #define OSMINOR "OS=UNICOS"
270
+ #define OS_UNICOS
271
+ #endif
272
+ #if defined(__USLC__) && !defined(M_XENIX)
273
+ #define OSMINOR "OS=UNIXWARE"
274
+ #define OS_UNIXWARE
275
+ #endif
276
+ #ifdef __OpenBSD__
277
+ #define OSMINOR "OS=OPENBSD"
278
+ #define OS_OPENBSD
279
+ #define unix
280
+ #endif
281
+ #if defined (__FreeBSD_kernel__) && !defined(__FreeBSD__)
282
+ #define OSMINOR "OS=KFREEBSD"
283
+ #define OS_KFREEBSD
284
+ #endif
285
+ #ifndef OSMINOR
286
+ #define OSMINOR "OS=UNKNOWN"
287
+ #endif
288
+
289
+ /* All the UNIX includes */
290
+
291
+ #include <sys/types.h>
292
+
293
+ #ifndef OS_MPEIX
294
+ #include <sys/file.h>
295
+ #endif
296
+
297
+ #include <fcntl.h>
298
+ #include <stdio.h>
299
+ #include <ctype.h>
300
+ #include <signal.h>
301
+ #include <string.h>
302
+ #include <time.h>
303
+ #include <unistd.h>
304
+
305
+ #ifndef OS_QNX
306
+ #include <memory.h>
307
+ #endif
308
+
309
+ #ifndef OS_ULTRIX
310
+ #include <stdlib.h>
311
+ #endif
312
+
313
+ #if !defined( OS_BSDI ) && \
314
+ !defined( OS_FREEBSD ) && \
315
+ !defined( OS_DRAGONFLYBSD ) && \
316
+ !defined( OS_NEXT ) && \
317
+ !defined( OS_MACHTEN ) && \
318
+ !defined( OS_MACOSX ) && \
319
+ !defined( OS_RHAPSODY ) && \
320
+ !defined( OS_MVS ) && \
321
+ !defined( OS_OPENBSD )
322
+ #include <malloc.h>
323
+ #endif
324
+
325
+ #endif /* #ifndef OSMINOR */
326
+
327
+
328
+ /*
329
+ * OSPLAT definitions - suppressed when it is a one-of-a-kind.
330
+ */
331
+
332
+ #if defined( _M_PPC ) || \
333
+ defined( PPC ) || \
334
+ defined( ppc ) || \
335
+ defined( __powerpc__ ) || \
336
+ defined( __ppc__ )
337
+ #define OSPLAT "OSPLAT=PPC"
338
+ #endif
339
+
340
+ #if defined( _ALPHA_ ) || \
341
+ defined( __alpha__ )
342
+ #define OSPLAT "OSPLAT=AXP"
343
+ #endif
344
+
345
+ #if defined( _i386_ ) || \
346
+ defined( __i386__ ) || \
347
+ defined( __i386 ) || \
348
+ defined( _M_IX86 )
349
+ #define OSPLAT "OSPLAT=X86"
350
+ #endif
351
+
352
+ #if defined( __ia64__ ) || \
353
+ defined( __IA64__ ) || \
354
+ defined( __ia64 )
355
+ #define OSPLAT "OSPLAT=IA64"
356
+ #endif
357
+
358
+ #if defined( __x86_64__ ) || \
359
+ defined( __amd64__ ) || \
360
+ defined( _M_AMD64 )
361
+ #define OSPLAT "OSPLAT=X86_64"
362
+ #endif
363
+
364
+ #if defined( __sparc__ ) || \
365
+ defined( __sparc )
366
+ #define OSPLAT "OSPLAT=SPARC"
367
+ #endif
368
+
369
+ #ifdef __mips__
370
+ #define OSPLAT "OSPLAT=MIPS"
371
+ #endif
372
+
373
+ #ifdef __arm__
374
+ #define OSPLAT "OSPLAT=ARM"
375
+ #endif
376
+
377
+ #ifdef __s390__
378
+ #define OSPLAT "OSPLAT=390"
379
+ #endif
380
+
381
+ #ifdef __hppa
382
+ #define OSPLAT "OSPLAT=PARISC"
383
+ #endif
384
+
385
+ #ifndef OSPLAT
386
+ #define OSPLAT ""
387
+ #endif
388
+
389
+
390
+ /*
391
+ * Jam implementation misc.
392
+ */
393
+
394
+ #ifndef MAXLINE
395
+ #define MAXLINE 102400 /* max chars per command line */
396
+ #endif
397
+
398
+ #ifndef EXITOK
399
+ #define EXITOK 0
400
+ #define EXITBAD 1
401
+ #endif
402
+
403
+ #ifndef SPLITPATH
404
+ #define SPLITPATH ':'
405
+ #endif
406
+
407
+ /* You probably do not need to muck with these. */
408
+
409
+ #define MAXSYM 1024 /* longest symbol in the environment */
410
+ #define MAXJPATH 1024 /* longest filename */
411
+
412
+ #define MAXJOBS 64 /* internally enforced -j limit */
413
+ #define MAXARGC 32 /* words in $(JAMSHELL) */
414
+
415
+ /* Jam private definitions below. */
416
+
417
+ #define DEBUG_MAX 14
418
+
419
+
420
+ struct globs
421
+ {
422
+ int noexec;
423
+ int jobs;
424
+ int quitquick;
425
+ int newestfirst; /* build newest sources first */
426
+ int pipe_action;
427
+ char debug[ DEBUG_MAX ];
428
+ FILE * cmdout; /* print cmds, not run them */
429
+ long timeout; /* number of seconds to limit actions to,
430
+ * default 0 for no limit.
431
+ */
432
+ int dart; /* output build and test results formatted for
433
+ * Dart
434
+ */
435
+ int max_buf; /* maximum amount of output saved from target
436
+ * (kb)
437
+ */
438
+ };
439
+
440
+ extern struct globs globs;
441
+
442
+ #define DEBUG_MAKE ( globs.debug[ 1 ] ) /* show actions when executed */
443
+ #define DEBUG_MAKEQ ( globs.debug[ 2 ] ) /* show even quiet actions */
444
+ #define DEBUG_EXEC ( globs.debug[ 2 ] ) /* show text of actons */
445
+ #define DEBUG_MAKEPROG ( globs.debug[ 3 ] ) /* show make0 progress */
446
+ #define DEBUG_BIND ( globs.debug[ 3 ] ) /* show when files bound */
447
+
448
+ #define DEBUG_EXECCMD ( globs.debug[ 4 ] ) /* show execcmds()'s work */
449
+
450
+ #define DEBUG_COMPILE ( globs.debug[ 5 ] ) /* show rule invocations */
451
+
452
+ #define DEBUG_HEADER ( globs.debug[ 6 ] ) /* show result of header scan */
453
+ #define DEBUG_BINDSCAN ( globs.debug[ 6 ] ) /* show result of dir scan */
454
+ #define DEBUG_SEARCH ( globs.debug[ 6 ] ) /* show binding attempts */
455
+
456
+ #define DEBUG_VARSET ( globs.debug[ 7 ] ) /* show variable settings */
457
+ #define DEBUG_VARGET ( globs.debug[ 8 ] ) /* show variable fetches */
458
+ #define DEBUG_VAREXP ( globs.debug[ 8 ] ) /* show variable expansions */
459
+ #define DEBUG_IF ( globs.debug[ 8 ] ) /* show 'if' calculations */
460
+ #define DEBUG_LISTS ( globs.debug[ 9 ] ) /* show list manipulation */
461
+ #define DEBUG_SCAN ( globs.debug[ 9 ] ) /* show scanner tokens */
462
+ #define DEBUG_MEM ( globs.debug[ 9 ] ) /* show memory use */
463
+
464
+ #define DEBUG_PROFILE ( globs.debug[ 10 ] ) /* dump rule execution times */
465
+ #define DEBUG_PARSE ( globs.debug[ 11 ] ) /* debug parsing */
466
+ #define DEBUG_GRAPH ( globs.debug[ 12 ] ) /* debug dependencies */
467
+ #define DEBUG_FATE ( globs.debug[ 13 ] ) /* show fate changes in make0() */
468
+
469
+ /* Everyone gets the memory definitions. */
470
+ #include "mem.h"
471
+
472
+ /* They also get the profile functions. */
473
+ #include "debug.h"
474
+
475
+ #endif
mosesdecoder/jam-files/engine/jamgram.y ADDED
@@ -0,0 +1,373 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ %token _BANG_t
2
+ %token _BANG_EQUALS_t
3
+ %token _AMPER_t
4
+ %token _AMPERAMPER_t
5
+ %token _LPAREN_t
6
+ %token _RPAREN_t
7
+ %token _PLUS_EQUALS_t
8
+ %token _COLON_t
9
+ %token _SEMIC_t
10
+ %token _LANGLE_t
11
+ %token _LANGLE_EQUALS_t
12
+ %token _EQUALS_t
13
+ %token _RANGLE_t
14
+ %token _RANGLE_EQUALS_t
15
+ %token _QUESTION_EQUALS_t
16
+ %token _LBRACKET_t
17
+ %token _RBRACKET_t
18
+ %token ACTIONS_t
19
+ %token BIND_t
20
+ %token CASE_t
21
+ %token CLASS_t
22
+ %token DEFAULT_t
23
+ %token ELSE_t
24
+ %token EXISTING_t
25
+ %token FOR_t
26
+ %token IF_t
27
+ %token IGNORE_t
28
+ %token IN_t
29
+ %token INCLUDE_t
30
+ %token LOCAL_t
31
+ %token MODULE_t
32
+ %token ON_t
33
+ %token PIECEMEAL_t
34
+ %token QUIETLY_t
35
+ %token RETURN_t
36
+ %token RULE_t
37
+ %token SWITCH_t
38
+ %token TOGETHER_t
39
+ %token UPDATED_t
40
+ %token WHILE_t
41
+ %token _LBRACE_t
42
+ %token _BAR_t
43
+ %token _BARBAR_t
44
+ %token _RBRACE_t
45
+ /*
46
+ * Copyright 1993, 2000 Christopher Seiwald.
47
+ *
48
+ * This file is part of Jam - see jam.c for Copyright information.
49
+ */
50
+
51
+ /* This file is ALSO:
52
+ * Copyright 2001-2004 David Abrahams.
53
+ * Distributed under the Boost Software License, Version 1.0.
54
+ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
55
+ */
56
+
57
+ /*
58
+ * jamgram.yy - jam grammar
59
+ *
60
+ * 04/13/94 (seiwald) - added shorthand L0 for null list pointer
61
+ * 06/01/94 (seiwald) - new 'actions existing' does existing sources
62
+ * 08/23/94 (seiwald) - Support for '+=' (append to variable)
63
+ * 08/31/94 (seiwald) - Allow ?= as alias for "default =".
64
+ * 09/15/94 (seiwald) - if conditionals take only single arguments, so
65
+ * that 'if foo == bar' gives syntax error (use =).
66
+ * 02/11/95 (seiwald) - when scanning arguments to rules, only treat
67
+ * punctuation keywords as keywords. All arg lists
68
+ * are terminated with punctuation keywords.
69
+ *
70
+ * 09/11/00 (seiwald) - Support for function calls:
71
+ *
72
+ * Rules now return lists (LIST *), rather than void.
73
+ *
74
+ * New "[ rule ]" syntax evals rule into a LIST.
75
+ *
76
+ * Lists are now generated by compile_list() and
77
+ * compile_append(), and any other rule that indirectly
78
+ * makes a list, rather than being built directly here,
79
+ * so that lists values can contain rule evaluations.
80
+ *
81
+ * New 'return' rule sets the return value, though
82
+ * other statements also may have return values.
83
+ *
84
+ * 'run' production split from 'block' production so
85
+ * that empty blocks can be handled separately.
86
+ */
87
+
88
+ %token ARG STRING
89
+
90
+ %left _BARBAR_t _BAR_t
91
+ %left _AMPERAMPER_t _AMPER_t
92
+ %left _EQUALS_t _BANG_EQUALS_t IN_t
93
+ %left _LANGLE_t _LANGLE_EQUALS_t _RANGLE_t _RANGLE_EQUALS_t
94
+ %left _BANG_t
95
+
96
+ %{
97
+ #include "jam.h"
98
+
99
+ #include "lists.h"
100
+ #include "parse.h"
101
+ #include "scan.h"
102
+ #include "compile.h"
103
+ #include "object.h"
104
+ #include "rules.h"
105
+
106
+ # define YYMAXDEPTH 10000 /* for OSF and other less endowed yaccs */
107
+
108
+ # define F0 -1
109
+ # define P0 (PARSE *)0
110
+ # define S0 (OBJECT *)0
111
+
112
+ # define pappend( l,r ) parse_make( PARSE_APPEND,l,r,P0,S0,S0,0 )
113
+ # define peval( c,l,r ) parse_make( PARSE_EVAL,l,r,P0,S0,S0,c )
114
+ # define pfor( s,l,r,x ) parse_make( PARSE_FOREACH,l,r,P0,s,S0,x )
115
+ # define pif( l,r,t ) parse_make( PARSE_IF,l,r,t,S0,S0,0 )
116
+ # define pincl( l ) parse_make( PARSE_INCLUDE,l,P0,P0,S0,S0,0 )
117
+ # define plist( s ) parse_make( PARSE_LIST,P0,P0,P0,s,S0,0 )
118
+ # define plocal( l,r,t ) parse_make( PARSE_LOCAL,l,r,t,S0,S0,0 )
119
+ # define pmodule( l,r ) parse_make( PARSE_MODULE,l,r,P0,S0,S0,0 )
120
+ # define pclass( l,r ) parse_make( PARSE_CLASS,l,r,P0,S0,S0,0 )
121
+ # define pnull() parse_make( PARSE_NULL,P0,P0,P0,S0,S0,0 )
122
+ # define pon( l,r ) parse_make( PARSE_ON,l,r,P0,S0,S0,0 )
123
+ # define prule( s,p ) parse_make( PARSE_RULE,p,P0,P0,s,S0,0 )
124
+ # define prules( l,r ) parse_make( PARSE_RULES,l,r,P0,S0,S0,0 )
125
+ # define pset( l,r,a ) parse_make( PARSE_SET,l,r,P0,S0,S0,a )
126
+ # define pset1( l,r,t,a ) parse_make( PARSE_SETTINGS,l,r,t,S0,S0,a )
127
+ # define psetc( s,p,a,l ) parse_make( PARSE_SETCOMP,p,a,P0,s,S0,l )
128
+ # define psete( s,l,s1,f ) parse_make( PARSE_SETEXEC,l,P0,P0,s,s1,f )
129
+ # define pswitch( l,r ) parse_make( PARSE_SWITCH,l,r,P0,S0,S0,0 )
130
+ # define pwhile( l,r ) parse_make( PARSE_WHILE,l,r,P0,S0,S0,0 )
131
+
132
+ # define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
133
+ # define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
134
+
135
+ %}
136
+
137
+ %%
138
+
139
+ run : /* empty */
140
+ /* do nothing */
141
+ | rules
142
+ { parse_save( $1.parse ); }
143
+ ;
144
+
145
+ /*
146
+ * block - zero or more rules
147
+ * rules - one or more rules
148
+ * rule - any one of jam's rules
149
+ * right-recursive so rules execute in order.
150
+ */
151
+
152
+ block : null
153
+ { $$.parse = $1.parse; }
154
+ | rules
155
+ { $$.parse = $1.parse; }
156
+ ;
157
+
158
+ rules : rule
159
+ { $$.parse = $1.parse; }
160
+ | rule rules
161
+ { $$.parse = prules( $1.parse, $2.parse ); }
162
+ | LOCAL_t list assign_list_opt _SEMIC_t block
163
+ { $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
164
+ ;
165
+
166
+ null : /* empty */
167
+ { $$.parse = pnull(); }
168
+ ;
169
+
170
+ assign_list_opt : _EQUALS_t list
171
+ { $$.parse = $2.parse; $$.number = ASSIGN_SET; }
172
+ | null
173
+ { $$.parse = $1.parse; $$.number = ASSIGN_APPEND; }
174
+ ;
175
+
176
+ arglist_opt : _LPAREN_t lol _RPAREN_t
177
+ { $$.parse = $2.parse; }
178
+ |
179
+ { $$.parse = P0; }
180
+ ;
181
+
182
+ local_opt : LOCAL_t
183
+ { $$.number = 1; }
184
+ | /* empty */
185
+ { $$.number = 0; }
186
+ ;
187
+
188
+ rule : _LBRACE_t block _RBRACE_t
189
+ { $$.parse = $2.parse; }
190
+ | INCLUDE_t list _SEMIC_t
191
+ { $$.parse = pincl( $2.parse ); }
192
+ | ARG lol _SEMIC_t
193
+ { $$.parse = prule( $1.string, $2.parse ); }
194
+ | arg assign list _SEMIC_t
195
+ { $$.parse = pset( $1.parse, $3.parse, $2.number ); }
196
+ | arg ON_t list assign list _SEMIC_t
197
+ { $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
198
+ | RETURN_t list _SEMIC_t
199
+ { $$.parse = $2.parse; }
200
+ | FOR_t local_opt ARG IN_t list _LBRACE_t block _RBRACE_t
201
+ { $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
202
+ | SWITCH_t list _LBRACE_t cases _RBRACE_t
203
+ { $$.parse = pswitch( $2.parse, $4.parse ); }
204
+ | IF_t expr _LBRACE_t block _RBRACE_t
205
+ { $$.parse = pif( $2.parse, $4.parse, pnull() ); }
206
+ | MODULE_t list _LBRACE_t block _RBRACE_t
207
+ { $$.parse = pmodule( $2.parse, $4.parse ); }
208
+ | CLASS_t lol _LBRACE_t block _RBRACE_t
209
+ { $$.parse = pclass( $2.parse, $4.parse ); }
210
+ | WHILE_t expr _LBRACE_t block _RBRACE_t
211
+ { $$.parse = pwhile( $2.parse, $4.parse ); }
212
+ | IF_t expr _LBRACE_t block _RBRACE_t ELSE_t rule
213
+ { $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
214
+ | local_opt RULE_t ARG arglist_opt rule
215
+ { $$.parse = psetc( $3.string, $5.parse, $4.parse, $1.number ); }
216
+ | ON_t arg rule
217
+ { $$.parse = pon( $2.parse, $3.parse ); }
218
+ | ACTIONS_t eflags ARG bindlist _LBRACE_t
219
+ { yymode( SCAN_STRING ); }
220
+ STRING
221
+ { yymode( SCAN_NORMAL ); }
222
+ _RBRACE_t
223
+ { $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
224
+ ;
225
+
226
+ /*
227
+ * assign - = or +=
228
+ */
229
+
230
+ assign : _EQUALS_t
231
+ { $$.number = ASSIGN_SET; }
232
+ | _PLUS_EQUALS_t
233
+ { $$.number = ASSIGN_APPEND; }
234
+ | _QUESTION_EQUALS_t
235
+ { $$.number = ASSIGN_DEFAULT; }
236
+ | DEFAULT_t _EQUALS_t
237
+ { $$.number = ASSIGN_DEFAULT; }
238
+ ;
239
+
240
+ /*
241
+ * expr - an expression for if
242
+ */
243
+ expr : arg
244
+ { $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
245
+ | expr _EQUALS_t expr
246
+ { $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
247
+ | expr _BANG_EQUALS_t expr
248
+ { $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
249
+ | expr _LANGLE_t expr
250
+ { $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
251
+ | expr _LANGLE_EQUALS_t expr
252
+ { $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
253
+ | expr _RANGLE_t expr
254
+ { $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
255
+ | expr _RANGLE_EQUALS_t expr
256
+ { $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
257
+ | expr _AMPER_t expr
258
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
259
+ | expr _AMPERAMPER_t expr
260
+ { $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
261
+ | expr _BAR_t expr
262
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
263
+ | expr _BARBAR_t expr
264
+ { $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
265
+ | arg IN_t list
266
+ { $$.parse = peval( EXPR_IN, $1.parse, $3.parse ); }
267
+ | _BANG_t expr
268
+ { $$.parse = peval( EXPR_NOT, $2.parse, pnull() ); }
269
+ | _LPAREN_t expr _RPAREN_t
270
+ { $$.parse = $2.parse; }
271
+ ;
272
+
273
+
274
+ /*
275
+ * cases - action elements inside a 'switch'
276
+ * case - a single action element inside a 'switch'
277
+ * right-recursive rule so cases can be examined in order.
278
+ */
279
+
280
+ cases : /* empty */
281
+ { $$.parse = P0; }
282
+ | case cases
283
+ { $$.parse = pnode( $1.parse, $2.parse ); }
284
+ ;
285
+
286
+ case : CASE_t ARG _COLON_t block
287
+ { $$.parse = psnode( $2.string, $4.parse ); }
288
+ ;
289
+
290
+ /*
291
+ * lol - list of lists
292
+ * right-recursive rule so that lists can be added in order.
293
+ */
294
+
295
+ lol : list
296
+ { $$.parse = pnode( P0, $1.parse ); }
297
+ | list _COLON_t lol
298
+ { $$.parse = pnode( $3.parse, $1.parse ); }
299
+ ;
300
+
301
+ /*
302
+ * list - zero or more args in a LIST
303
+ * listp - list (in puncutation only mode)
304
+ * arg - one ARG or function call
305
+ */
306
+
307
+ list : listp
308
+ { $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
309
+ ;
310
+
311
+ listp : /* empty */
312
+ { $$.parse = pnull(); yymode( SCAN_PUNCT ); }
313
+ | listp arg
314
+ { $$.parse = pappend( $1.parse, $2.parse ); }
315
+ ;
316
+
317
+ arg : ARG
318
+ { $$.parse = plist( $1.string ); }
319
+ | _LBRACKET_t { yymode( SCAN_NORMAL ); } func _RBRACKET_t
320
+ { $$.parse = $3.parse; }
321
+ ;
322
+
323
+ /*
324
+ * func - a function call (inside [])
325
+ * This needs to be split cleanly out of 'rule'
326
+ */
327
+
328
+ func : ARG lol
329
+ { $$.parse = prule( $1.string, $2.parse ); }
330
+ | ON_t arg ARG lol
331
+ { $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
332
+ | ON_t arg RETURN_t list
333
+ { $$.parse = pon( $2.parse, $4.parse ); }
334
+ ;
335
+
336
+
337
+ /*
338
+ * eflags - zero or more modifiers to 'executes'
339
+ * eflag - a single modifier to 'executes'
340
+ */
341
+
342
+ eflags : /* empty */
343
+ { $$.number = 0; }
344
+ | eflags eflag
345
+ { $$.number = $1.number | $2.number; }
346
+ ;
347
+
348
+ eflag : UPDATED_t
349
+ { $$.number = EXEC_UPDATED; }
350
+ | TOGETHER_t
351
+ { $$.number = EXEC_TOGETHER; }
352
+ | IGNORE_t
353
+ { $$.number = EXEC_IGNORE; }
354
+ | QUIETLY_t
355
+ { $$.number = EXEC_QUIETLY; }
356
+ | PIECEMEAL_t
357
+ { $$.number = EXEC_PIECEMEAL; }
358
+ | EXISTING_t
359
+ { $$.number = EXEC_EXISTING; }
360
+ ;
361
+
362
+
363
+ /*
364
+ * bindlist - list of variable to bind for an action
365
+ */
366
+
367
+ bindlist : /* empty */
368
+ { $$.parse = pnull(); }
369
+ | BIND_t list
370
+ { $$.parse = $2.parse; }
371
+ ;
372
+
373
+