Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/v2/kernel/errors.jam @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

  • Property svn:executable set to *
File size: 7.1 KB
Line 
1#  (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
2#  distribute this software is granted provided this copyright notice appears in
3#  all copies. This software is provided "as is" without express or implied
4#  warranty, and with no claim as to its suitability for any purpose.
5
6# Print a stack backtrace leading to this rule's caller. Each
7# argument represents a line of output to be printed after the first
8# line of the backtrace.
9rule backtrace ( skip-frames prefix messages * : * )
10{
11    local frame-skips = 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 ;
12    local drop-elements = $(frame-skips[$(skip-frames)]) ;
13    if ! ( $(skip-frames) in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 )
14    {
15        ECHO warning: backtrace doesn't support skipping
16          $(skip-frames) frames; using 1 instead. ;
17        drop-elements = 5 ;
18    }
19   
20    local args = $(.args) ;   
21    if $(.user-modules-only)
22    {
23        local bt = [ nearest-user-location ] ;
24        ECHO "$(prefix) at $(bt) " ;
25        for local n in $(args)
26        {           
27            if $($(n))-is-not-empty
28            {
29                ECHO $(prefix) $($(n)) ;
30            }
31        }       
32    }
33    else
34    {
35        # get the whole backtrace, then drop the initial quadruples
36        # corresponding to the frames that must be skipped.
37        local bt = [ BACKTRACE ] ;
38        bt = $(bt[$(drop-elements)-]) ;
39       
40        while $(bt)
41        {
42            local m = [ MATCH ^(.+)\\.$ : $(bt[3]) ] ;
43            ECHO $(bt[1]):$(bt[2]): "in" $(bt[4]) "from module" $(m) ;
44       
45                       
46            # the first time through, print each argument on a separate
47            # line
48            for local n in $(args)
49            {
50                if $($(n))-is-not-empty
51                {
52                    ECHO $(prefix) $($(n)) ;
53                }
54            }
55            args = ; # kill args so that this never happens again
56           
57            # Move on to the next quadruple
58            bt = $(bt[5-]) ;
59        }
60    }   
61}
62
63.args ?= messages 2 3 4 5 6 7 8 9 ;
64.disabled ?= ;
65.last-error-$(.args) ?= ;
66
67# try-catch --
68#
69# This is not really an exception-handling mechanism, but it does
70# allow us to perform some error-checking on our
71# error-checking. Errors are suppressed after a try, and the first one
72# is recorded. Use catch to check that the error message matched
73# expectations.
74
75# begin looking for error messages
76rule try ( )
77{
78    .disabled += true ;
79    .last-error-$(.args) = ;
80}
81
82# stop looking for error messages; generate an error if an argument of
83# messages is not found in the corresponding argument in the error call.
84rule catch ( messages * : * )
85{
86    .disabled = $(.disabled[2-]) ; # pop the stack   
87   
88    import sequence ;
89
90    if ! $(.last-error-$(.args))-is-nonempty
91    {
92        error-skip-frames 3 expected an error, but none occurred ;
93    }
94    else
95    {
96        for local n in $(.args)
97        {
98            if ! $($(n)) in $(.last-error-$(n))
99            {
100                local v = [ sequence.join $($(n)) : " " ] ;
101                v ?= "" ;
102                local joined = [ sequence.join $(.last-error-$(n)) : " " ] ;
103
104                .last-error-$(.args) = ;
105                error-skip-frames 3 expected \"$(v)\" in argument $(n) of error
106                  : got \"$(joined)\" instead ;
107            }
108        }
109    }
110}
111
112rule error-skip-frames ( skip-frames messages * : * )
113{
114    if ! $(.disabled)
115    {
116        backtrace $(skip-frames) error: $(messages) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
117        EXIT ;
118    }
119    else if ! $(.last-error-$(.args))
120    {
121        for local n in $(.args)
122        {
123            # Add an extra empty string so that we always have
124            # something in the event of an error
125            .last-error-$(n) = $($(n)) "" ;
126        }
127    }
128}
129
130if --no-error-backtrace in [ modules.peek : ARGV ]
131{
132    .no-error-backtrace = true ;
133}
134
135
136# Print an error message with a stack backtrace and exit.
137rule error ( messages * : * )
138{
139    if $(.no-error-backtrace)
140    {
141        # Print each argument on a separate line.
142        for local n in $(.args)
143        {
144            if $($(n))-is-not-empty
145            {
146                if ! $(first-printed)
147                {                   
148                    ECHO error: $($(n)) ;
149                    first-printed = true ;
150                }
151                else
152                {
153                    ECHO $($(n)) ;                   
154                }                               
155            }
156        }       
157        EXIT ;
158    }
159    else
160    {       
161        error-skip-frames 3 $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
162    }   
163}
164
165# Same as 'error', but the generated backtrace will include only user files.
166rule user-error ( messages * : * )
167{
168    .user-modules-only = 1 ;
169    error-skip-frames 3 $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
170}
171
172
173# Print a warning message with a stack backtrace and exit.
174rule warning
175{
176    backtrace 2 warning: $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
177}
178
179# convert an arbitrary argument list into a list with ":" separators
180# and quoted elements representing the same information. This is
181# mostly useful for formatting descriptions of the arguments with
182# which a rule was called when reporting an error.
183rule lol->list ( * )
184{
185    local result ;
186    local remaining = 1 2 3 4 5 6 7 8 9 ;
187    while $($(remaining))
188    {
189        local n = $(remaining[1]) ;
190        remaining = $(remaining[2-]) ;
191       
192        if $(n) != 1
193        {
194            result += ":" ;
195        }
196        result += \"$($(n))\" ;
197    }
198    return $(result) ;
199}
200
201# Return the file:line for the nearest entry in backtrace which correspond
202# to a user module.
203rule nearest-user-location ( )
204{
205    local bt = [ BACKTRACE ] ;
206   
207    local result ;
208    while $(bt) && ! $(result)
209    {
210        local m = [ MATCH ^(.+)\\.$ : $(bt[3]) ] ;
211        local user-modules = ([Jj]amfile(.jam|.v2|)|user-config.jam|site-config.jam|project-root.jam) ;
212       
213        if [ MATCH $(user-modules) : $(bt[1]:D=) ]
214        {               
215            result = $(bt[1]):$(bt[2]) ;
216        }           
217        bt = $(bt[5-]) ;
218    }
219    return $(result) ;
220}
221
222# If optimized rule is available in jam, use it.
223if NEAREST_USER_LOCATION in [ RULENAMES ]
224{
225    rule nearest-user-location ( )
226    {
227        local r = [ NEAREST_USER_LOCATION ] ;
228        return $(r[1]):$(r[2]) ;
229    }   
230}
231
232
233
234rule __test__ ( )
235{
236    # show that we can correctly catch an expected error
237    try ;
238    {
239        error an error occurred : somewhere ;
240    }
241    catch an error occurred : somewhere ;
242   
243    # show that unexpected errors generate real errors
244    try ;
245    {
246        try ;
247        {
248            error an error occurred : somewhere ;
249        }
250        catch an error occurred : nowhere ;
251    }
252    catch expected \"nowhere\" in argument 2 ;
253   
254    # show that not catching an error where one was expected is an
255    # error
256    try ;
257    {
258        try ;
259        {
260        }
261        catch ;
262    }
263    catch expected an error, but none occurred ;
264}
Note: See TracBrowser for help on using the repository browser.