~ubuntu-branches/ubuntu/saucy/dejagnu/saucy

« back to all changes in this revision

Viewing changes to lib/dg.exp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Jacobowitz
  • Date: 2004-02-09 15:07:58 UTC
  • Revision ID: james.westby@ubuntu.com-20040209150758-oaj7r5zrop60v8sb
Tags: upstream-1.4.4
ImportĀ upstreamĀ versionĀ 1.4.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# `dg' general purpose testcase driver.
 
2
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
 
3
# 2001, 2002, 2003 Free Software Foundation, Inc.
 
4
#
 
5
# This file is part of DejaGnu.
 
6
#
 
7
# DejaGnu is free software; you can redistribute it and/or modify it
 
8
# under the terms of the GNU General Public License as published by
 
9
# the Free Software Foundation; either version 2 of the License, or
 
10
# (at your option) any later version.
 
11
#
 
12
# DejaGnu is distributed in the hope that it will be useful, but
 
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
# General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with DejaGnu; if not, write to the Free Software Foundation,
 
19
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
20
 
 
21
# This file was written by Doug Evans (dje@cygnus.com).
 
22
 
 
23
# This file is based on old-dejagnu.exp.  It is intended to be more extensible
 
24
# without incurring the overhead that old-dejagnu.exp can.  All test framework
 
25
# commands appear in the testcase as "{ dg-xxx args ... }".  We pull them out
 
26
# with one grep, and then run the function(s) named by "dg-xxx".  When running
 
27
# dg-xxx, the line number that it occurs on is always passed as the first
 
28
# argument.  We also support different kinds of tools via callbacks.
 
29
#
 
30
# The currently supported options are:
 
31
#
 
32
# dg-prms-id N
 
33
#       set prms_id to N
 
34
#
 
35
# dg-options "options ..." [{ target selector }]
 
36
#       specify special options to pass to the tool (eg: compiler)
 
37
#
 
38
# dg-do do-what-keyword [{ target/xfail selector }]
 
39
#       `do-what-keyword' is tool specific and is passed unchanged to
 
40
#       ${tool}-dg-test.  An example is gcc where `keyword' can be any of:
 
41
#       preprocess|compile|assemble|link|run
 
42
#       and will do one of: produce a .i, produce a .s, produce a .o,
 
43
#       produce an a.out, or produce an a.out and run it (the default is
 
44
#       compile).
 
45
#
 
46
# dg-error regexp comment [{ target/xfail selector } [{.|0|linenum}]]
 
47
#       indicate an error message <regexp> is expected on this line
 
48
#       (the test fails if it doesn't occur)
 
49
#       Linenum=0 for general tool messages (eg: -V arg missing).
 
50
#       "." means the current line.
 
51
#
 
52
# dg-warning regexp comment [{ target/xfail selector } [{.|0|linenum}]]
 
53
#       indicate a warning message <regexp> is expected on this line
 
54
#       (the test fails if it doesn't occur)
 
55
#
 
56
# dg-bogus regexp comment [{ target/xfail selector } [{.|0|linenum}]]
 
57
#       indicate a bogus error message <regexp> use to occur here
 
58
#       (the test fails if it does occur)
 
59
#
 
60
# dg-build regexp comment [{ target/xfail selector }]
 
61
#       indicate the build use to fail for some reason
 
62
#       (errors covered here include bad assembler generated, tool crashes,
 
63
#       and link failures)
 
64
#       (the test fails if it does occur)
 
65
#
 
66
# dg-excess-errors comment [{ target/xfail selector }]
 
67
#       indicate excess errors are expected (any line)
 
68
#       (this should only be used sparingly and temporarily)
 
69
#
 
70
# dg-output regexp [{ target selector }]
 
71
#       indicate the expected output of the program is <regexp>
 
72
#       (there may be multiple occurrences of this, they are concatenated)
 
73
#
 
74
# dg-final { tcl code }
 
75
#       add some tcl code to be run at the end
 
76
#       (there may be multiple occurrences of this, they are concatenated)
 
77
#       (unbalanced braces must be \-escaped)
 
78
#
 
79
# "{ target selector }" is a list of expressions that determine whether the
 
80
# test succeeds or fails for a particular target, or in some cases whether the
 
81
# option applies for a particular target.  If the case of `dg-do' it specifies
 
82
# whether the testcase is even attempted on the specified target.
 
83
#
 
84
# The target selector is always optional.  The format is one of:
 
85
#
 
86
# { xfail *-*-* ... } - the test is expected to fail for the given targets
 
87
# { target *-*-* ... } - the option only applies to the given targets
 
88
#
 
89
# At least one target must be specified, use *-*-* for "all targets".
 
90
# At present it is not possible to specify both `xfail' and `target'.
 
91
# "native" may be used in place of "*-*-*".
 
92
#
 
93
# Example:
 
94
#
 
95
#       [ ... some complicated code ... ]
 
96
#       return a; /* { dg-build "fatal" "ran out of spill regs" { xfail i386-*-* } } */
 
97
#
 
98
# In this example, the compiler use to crash on the "return a;" for some
 
99
# target and that it still does crash on i386-*-*.  Admittedly, this is a
 
100
# contrived example.
 
101
#
 
102
# ??? It might be possible to add additional optional arguments by having
 
103
# something like: { dg-error ".*syntax.*" "syntax error" { { foo 1 } ... } }
 
104
#
 
105
# Callbacks
 
106
#
 
107
# ${tool}-dg-test testfile do-what-keyword extra-flags
 
108
#
 
109
#       Run the test, be it compiler, assembler, or whatever.
 
110
#
 
111
# ${tool}-dg-prune target_triplet text
 
112
#
 
113
#       Optional callback to delete output from the tool that can occur
 
114
#       even in successful ("pass") situations and interfere with output
 
115
#       pattern matching.  This also gives the tool an opportunity to review
 
116
#       the output and check for any conditions which indicate an "untested"
 
117
#       or "unresolved" state.  An example is if a testcase is too big and
 
118
#       fills all available ram (which can happen for 16 bit cpus).  The
 
119
#       result is either the pruned text or
 
120
#       "::untested|unresolved|unsupported::message"
 
121
#       (eg: "::unsupported::memory full").
 
122
#
 
123
# Notes:
 
124
# 1) All runnable testcases must return 0 from main() for success.
 
125
#    You can't rely on getting any return code from target boards, and the
 
126
#    `exec' command says a program fails if it returns non-zero.
 
127
#
 
128
# Language independence is (theoretically) achieved by:
 
129
#
 
130
# 1) Using global $tool to indicate the language (eg: gcc, g++, gas, etc.).
 
131
#    This should only be used to look up other objects.  We don't want to
 
132
#    have to add code for each new language that is supported.  If this is
 
133
#    done right, no code needs to be added here for each new language.
 
134
#
 
135
# 2) Passing tool options in as arguments.
 
136
#
 
137
#    Earlier versions of ${tool}_start (eg: gcc_start) would only take the name
 
138
#    of the file to compile as an argument.  Newer versions accept a list of
 
139
#    one or two elements, the second being a string of *all* options to pass
 
140
#    to the tool.  We require this facility.
 
141
#
 
142
# 3) Callbacks.
 
143
#
 
144
# Try not to do anything else that makes life difficult.
 
145
#
 
146
# The normal way to write a testsuite is to have a .exp file containing:
 
147
#
 
148
# load_lib ${tool}-dg.exp
 
149
# dg-init
 
150
# dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/foo*]] ...
 
151
# dg-finish
 
152
 
 
153
# Global state variables.
 
154
# The defaults are for GCC.
 
155
 
 
156
# The default do-what keyword.
 
157
set dg-do-what-default compile
 
158
 
 
159
# When dg-interpreter-batch-mode is 1, no execution test or excess error
 
160
# tests are performed.
 
161
set dg-interpreter-batch-mode 0
 
162
 
 
163
# Line number format.  This is how line numbers appear in program output.
 
164
set dg-linenum-format ":%d:"
 
165
proc dg-format-linenum { linenum } {
 
166
    global dg-linenum-format
 
167
    return [format ${dg-linenum-format} $linenum]
 
168
}
 
169
 
 
170
# Useful subroutines.
 
171
 
 
172
# dg-get-options -- pick out the dg-xxx options in a testcase
 
173
#
 
174
# PROG is the file name of the testcase.
 
175
# The result is a list of options found.
 
176
#
 
177
# Example: For the following testcase:
 
178
#
 
179
# /* { dg-prms-id 1234 } */
 
180
# int foo { return 0; } /* { dg-build fatal "some comment" } */
 
181
#
 
182
# we return:
 
183
#
 
184
# { dg-prms-id 1 1234 } { dg-build 2 fatal "some comment" }
 
185
 
 
186
proc dg-get-options { prog } {
 
187
    set result ""
 
188
 
 
189
    set tmp [grep $prog "{\[ \t\]\+dg-\[-a-z\]\+\[ \t\]\+.*\[ \t\]\+}" line]
 
190
    if ![string match "" $tmp] {
 
191
        foreach i $tmp {
 
192
            #send_user "Found: $i\n"
 
193
            # FIXME: When to use "+" and "\+" isn't clear.
 
194
            # Seems to me it took awhile to get this to work.
 
195
            regexp "(\[0-9\]\+)\[ \t\]\+{\[ \t\]+(dg-\[-a-z\]+)\[ \t\]\+(.*)\[ \t\]+}\[^\}\]*(\n|$)" $i i line cmd args
 
196
            #send_user "Found: $cmd $line $args\n"
 
197
            append result " { $cmd $line $args }"
 
198
        }
 
199
    }
 
200
 
 
201
    #send_user "Returning: $result\n"
 
202
    return $result
 
203
}
 
204
 
 
205
#
 
206
# Process optional xfail/target arguments
 
207
#
 
208
# SELECTOR is "xfail target-triplet-1 ..." or "target target-triplet-1 ..."
 
209
# `target-triplet' may be "native".
 
210
# For xfail, the result is "F" (expected to Fail) if the current target is
 
211
# affected, otherwise "P" (expected to Pass).
 
212
# For target, the result is "S" (target is Selected) if the target is selected,
 
213
# otherwise "N" (target is Not selected).
 
214
#
 
215
proc dg-process-target { selector } {
 
216
    global target_triplet
 
217
 
 
218
    set isnative [isnative]
 
219
    set triplet_match 0
 
220
 
 
221
    #send_user "dg-process-target: $selector\n"
 
222
 
 
223
    set selector [string trim $selector]
 
224
    if [regexp "^xfail " $selector] {
 
225
        set what xfail
 
226
    } elseif [regexp "^target " $selector] {
 
227
        set what target
 
228
    } else {
 
229
        # The use of error here and in other dg-xxx utilities is intentional.
 
230
        # dg-test will catch them and do the right thing.
 
231
        error "syntax error in target selector \"$selector\""
 
232
    }
 
233
 
 
234
    # ??? This should work but it doesn't.  tcl bug?
 
235
    #if [regexp "^${what}(( \[^ \]+-\[^ \]+-\[^ \]+)|( native))+$" $selector tmp selector]
 
236
    if [regexp "^${what}( \[^ \]+-\[^ \]+-\[^ \]+| native)+$" $selector] {
 
237
        regsub "^${what} " $selector "" selector
 
238
        #send_user "selector: $selector\n"
 
239
        foreach triplet $selector {
 
240
            if [string match $triplet $target_triplet] {
 
241
                set triplet_match 1
 
242
            } elseif { $isnative && $triplet == "native" } {
 
243
                set triplet_match 1
 
244
            }
 
245
        }
 
246
    } else {
 
247
        error "syntax error in target selector \"$selector\""
 
248
    }
 
249
 
 
250
    if { $triplet_match } {
 
251
        return [expr { $what == "xfail" ? "F" : "S" }]
 
252
    } else {
 
253
        return [expr { $what == "xfail" ? "P" : "N" }]
 
254
    }
 
255
}
 
256
 
 
257
# Predefined user option handlers.
 
258
# The line number is always the first element.
 
259
# Note that each of these are varargs procs (they have an `args' argument).
 
260
# Tests for optional arguments are coded with ">=" to simplify adding new ones.
 
261
 
 
262
proc dg-prms-id { args } {
 
263
    global prms_id      ;# this is a testing framework variable
 
264
 
 
265
    if { [llength $args] > 2 } {
 
266
        error "[lindex $args 0]: too many arguments"
 
267
        return
 
268
    }
 
269
 
 
270
    set prms_id [lindex $args 1]
 
271
}
 
272
 
 
273
#
 
274
# Set tool options
 
275
#
 
276
# Different options can be used for different targets by having multiple
 
277
# instances, selecting a different target each time.  Since options are
 
278
# processed in order, put the default value first.  Subsequent occurrences
 
279
# will override previous ones.
 
280
#
 
281
 
 
282
proc dg-options { args } {
 
283
    upvar dg-extra-tool-flags extra-tool-flags
 
284
 
 
285
    if { [llength $args] > 3 } {
 
286
        error "[lindex $args 0]: too many arguments"
 
287
        return
 
288
    }
 
289
 
 
290
    if { [llength $args] >= 3 } {
 
291
        switch [dg-process-target [lindex $args 2]] {
 
292
            "S" { set extra-tool-flags [lindex $args 1] }
 
293
            "N" { }
 
294
            "F" { error "[lindex $args 0]: `xfail' not allowed here" }
 
295
            "P" { error "[lindex $args 0]: `xfail' not allowed here" }
 
296
        }
 
297
    } else {
 
298
        set extra-tool-flags [lindex $args 1]
 
299
    }
 
300
}
 
301
 
 
302
#
 
303
# Record what to do (compile/run/etc.)
 
304
#
 
305
# Multiple instances are supported (since we don't support target and xfail
 
306
# selectors on one line), though it doesn't make much sense to change the
 
307
# compile/assemble/link/run field.  Nor does it make any sense to have
 
308
# multiple lines of target selectors (use one line).
 
309
#
 
310
proc dg-do { args } {
 
311
    upvar dg-do-what do-what
 
312
 
 
313
    if { [llength $args] > 3 } {
 
314
        error "[lindex $args 0]: too many arguments"
 
315
        return
 
316
    }
 
317
 
 
318
    set selected [lindex ${do-what} 1]  ;# selected? (""/S/N)
 
319
    set expected [lindex ${do-what} 2]  ;# expected to pass/fail (P/F)
 
320
 
 
321
    if { [llength $args] >= 3 } {
 
322
        switch [dg-process-target [lindex $args 2]] {
 
323
            "S" {
 
324
                set selected "S"
 
325
            }
 
326
            "N" {
 
327
                # Don't deselect a target if it's been explicitly selected,
 
328
                # but indicate a specific target has been selected (so don't
 
329
                # do this testcase if it's not appropriate for this target).
 
330
                # The user really shouldn't have multiple lines of target
 
331
                # selectors, but try to do the intuitive thing (multiple lines
 
332
                # are OR'd together).
 
333
                if { $selected != "S" } {
 
334
                    set selected "N"
 
335
                }
 
336
            }
 
337
            "F" { set expected "F" }
 
338
            "P" {
 
339
                # There's nothing to do for "P".  We don't want to clobber a
 
340
                # previous xfail for this target.
 
341
            }
 
342
        }
 
343
    } else {
 
344
        # Note: A previous occurrence of `dg-do' with target/xfail selectors
 
345
        # is a user mistake.  We clobber previous values here.
 
346
        set selected S
 
347
        set expected P
 
348
    }
 
349
 
 
350
    switch [lindex $args 1] {
 
351
        "preprocess" { }
 
352
        "compile" { }
 
353
        "assemble" { }
 
354
        "link" { }
 
355
        "run" { }
 
356
        default {
 
357
            error "[lindex $args 0]: syntax error"
 
358
        }
 
359
    }
 
360
    set do-what [list [lindex $args 1] $selected $expected]
 
361
}
 
362
 
 
363
proc dg-error { args } {
 
364
    upvar dg-messages messages
 
365
 
 
366
    if { [llength $args] > 5 } {
 
367
        error "[lindex $args 0]: too many arguments"
 
368
        return
 
369
    }
 
370
 
 
371
    set xfail ""
 
372
    if { [llength $args] >= 4 } {
 
373
        switch [dg-process-target [lindex $args 3]] {
 
374
            "F" { set xfail "X" }
 
375
            "P" { set xfail "" }
 
376
            "N" {
 
377
                # If we get "N", this error doesn't apply to us so ignore it.
 
378
                return
 
379
            }
 
380
        }
 
381
    }
 
382
 
 
383
    if { [llength $args] >= 5 } {
 
384
        switch [lindex $args 4] {
 
385
            "." { set line [dg-format-linenum [lindex $args 0]] }
 
386
            "0" { set line "" }
 
387
            "default" { set line [dg-format-linenum [lindex $args 4]] }
 
388
        }
 
389
    } else {
 
390
        set line [dg-format-linenum [lindex $args 0]]
 
391
    }
 
392
 
 
393
    lappend messages [list $line "${xfail}ERROR" [lindex $args 1] [lindex $args 2]]
 
394
}
 
395
 
 
396
proc dg-warning { args } {
 
397
    upvar dg-messages messages
 
398
 
 
399
    if { [llength $args] > 5 } {
 
400
        error "[lindex $args 0]: too many arguments"
 
401
        return
 
402
    }
 
403
 
 
404
    set xfail ""
 
405
    if { [llength $args] >= 4 } {
 
406
        switch [dg-process-target [lindex $args 3]] {
 
407
            "F" { set xfail "X" }
 
408
            "P" { set xfail "" }
 
409
            "N" {
 
410
                # If we get "N", this warning doesn't apply to us so ignore it.
 
411
                return
 
412
            }
 
413
        }
 
414
    }
 
415
 
 
416
    if { [llength $args] >= 5 } {
 
417
        switch [lindex $args 4] {
 
418
            "." { set line [dg-format-linenum [lindex $args 0]] }
 
419
            "0" { set line "" }
 
420
            "default" { set line [dg-format-linenum [lindex $args 4]] }
 
421
        }
 
422
    } else {
 
423
        set line [dg-format-linenum [lindex $args 0]]
 
424
    }
 
425
 
 
426
    lappend messages [list $line "${xfail}WARNING" [lindex $args 1] [lindex $args 2]]
 
427
}
 
428
 
 
429
proc dg-bogus { args } {
 
430
    upvar dg-messages messages
 
431
 
 
432
    if { [llength $args] > 5 } {
 
433
        error "[lindex $args 0]: too many arguments"
 
434
        return
 
435
    }
 
436
 
 
437
    set xfail ""
 
438
    if { [llength $args] >= 4 } {
 
439
        switch [dg-process-target [lindex $args 3]] {
 
440
            "F" { set xfail "X" }
 
441
            "P" { set xfail "" }
 
442
            "N" {
 
443
                # If we get "N", this message doesn't apply to us so ignore it.
 
444
                return
 
445
            }
 
446
        }
 
447
    }
 
448
 
 
449
    if { [llength $args] >= 5 } {
 
450
        switch [lindex $args 4] {
 
451
            "." { set line [dg-format-linenum [lindex $args 0]] }
 
452
            "0" { set line "" }
 
453
            "default" { set line [dg-format-linenum [lindex $args 4]] }
 
454
        }
 
455
    } else {
 
456
        set line [dg-format-linenum [lindex $args 0]]
 
457
    }
 
458
 
 
459
    lappend messages [list $line "${xfail}BOGUS" [lindex $args 1] [lindex $args 2]]
 
460
}
 
461
 
 
462
proc dg-build { args } {
 
463
    upvar dg-messages messages
 
464
 
 
465
    if { [llength $args] > 4 } {
 
466
        error "[lindex $args 0]: too many arguments"
 
467
        return
 
468
    }
 
469
 
 
470
    set xfail ""
 
471
    if { [ llength $args] >= 4 } {
 
472
        switch [dg-process-target [lindex $args 3]] {
 
473
            "F" { set xfail "X" }
 
474
            "P" { set xfail "" }
 
475
            "N" {
 
476
                # If we get "N", this lossage doesn't apply to us so ignore it.
 
477
                return
 
478
            }
 
479
        }
 
480
    }
 
481
 
 
482
    lappend messages [list [lindex $args 0] "${xfail}BUILD" [lindex $args 1] [lindex $args 2]]
 
483
}
 
484
 
 
485
proc dg-excess-errors { args } {
 
486
    upvar dg-excess-errors-flag excess-errors-flag
 
487
 
 
488
    if { [llength $args] > 3 } {
 
489
        error "[lindex $args 0]: too many arguments"
 
490
        return
 
491
    }
 
492
 
 
493
    if { [llength $args] >= 3 } {
 
494
        switch [dg-process-target [lindex $args 2]] {
 
495
            "F" { set excess-errors-flag 1 }
 
496
            "S" { set excess-errors-flag 1 }
 
497
        }
 
498
    } else {
 
499
        set excess-errors-flag 1
 
500
    }
 
501
}
 
502
 
 
503
#
 
504
# Indicate expected program output
 
505
#
 
506
# We support multiple occurrences, but we do not implicitly insert newlines
 
507
# between them.
 
508
#
 
509
# Note that target boards don't all support this kind of thing so it's a good
 
510
# idea to specify the target all the time.  If one or more targets are
 
511
# explicitly selected, the test won't be performed if we're not one of them
 
512
# (as long as we were never mentioned).
 
513
#
 
514
# If you have target dependent output and want to set an xfail for one or more
 
515
# of them, use { dg-output "" { xfail a-b-c ... } }.  The "" won't contribute
 
516
# to the expected output.
 
517
#
 
518
proc dg-output { args } {
 
519
    upvar dg-output-text output-text
 
520
 
 
521
    if { [llength $args] > 3 } {
 
522
        error "[lindex $args 0]: too many arguments"
 
523
        return
 
524
    }
 
525
 
 
526
    # Allow target dependent output.
 
527
 
 
528
    set expected [lindex ${output-text} 0]
 
529
    if { [llength $args] >= 3 } {
 
530
        switch [dg-process-target [lindex $args 2]] {
 
531
            "N" { return }
 
532
            "S" { }
 
533
            "F" { set expected "F" }
 
534
            # Don't override a previous xfail.
 
535
            "P" { }
 
536
        }
 
537
    }
 
538
 
 
539
    if { [llength ${output-text}] == 1 } {
 
540
        # First occurrence.
 
541
        set output-text [list $expected [lindex $args 1]]
 
542
    } else {
 
543
        set output-text [list $expected "[lindex ${output-text} 1][lindex $args 1]"]
 
544
    }
 
545
}
 
546
 
 
547
proc dg-final { args } {
 
548
    upvar dg-final-code final-code
 
549
 
 
550
    if { [llength $args] > 2 } {
 
551
        error "[lindex $args 0]: too many arguments"
 
552
        return
 
553
    }
 
554
 
 
555
    #send_user "dg-final: $args\n"
 
556
    append final-code "[lindex $args 1]\n"
 
557
}
 
558
 
 
559
#
 
560
# Set up our environment
 
561
#
 
562
# There currently isn't much to do, but always calling it allows us to add
 
563
# enhancements without having to update our callers.
 
564
# It must be run before calling `dg-test'.
 
565
 
 
566
proc dg-init { } {
 
567
}
 
568
 
 
569
# dg-runtest -- simple main loop useful to most testsuites
 
570
#
 
571
# FLAGS is a set of options to always pass.
 
572
# DEFAULT_EXTRA_FLAGS is a set of options to pass if the testcase doesn't
 
573
# specify any (with dg-option).
 
574
# ??? We're flipping between "flag" and "option" here.
 
575
 
 
576
proc dg-runtest { testcases flags default-extra-flags } {
 
577
    global runtests
 
578
 
 
579
    foreach testcase $testcases {
 
580
        # If we're only testing specific files and this isn't one of them, skip it.
 
581
        if ![runtest_file_p $runtests $testcase] {
 
582
            continue
 
583
        }
 
584
        verbose "Testing [file tail [file dirname $testcase]]/[file tail $testcase]"
 
585
        dg-test $testcase $flags ${default-extra-flags}
 
586
    }
 
587
}
 
588
 
 
589
# dg-trim-dirname -- rip DIR_NAME out of FILE_NAME
 
590
#
 
591
# Syntax: dg-trim-dirname dir_name file_name
 
592
# We need to go through this contorsion in order to properly support
 
593
# directory-names which might have embedded regexp special characters.
 
594
 
 
595
proc dg-trim-dirname { dir_name file_name } {
 
596
    set special_character "\[\?\+\-\.\(\)\$\|\]"
 
597
    regsub -all $special_character $dir_name "\\\\&" dir_name
 
598
    regsub "^$dir_name/?" $file_name "" file_name
 
599
    return $file_name
 
600
}
 
601
 
 
602
# dg-test -- runs a new style DejaGnu test
 
603
#
 
604
# Syntax: dg-test [-keep-output] prog tool_flags default_extra_tool_flags
 
605
#
 
606
# PROG is the full path name of the file to pass to the tool (eg: compiler).
 
607
# TOOL_FLAGS is a set of options to always pass.
 
608
# DEFAULT_EXTRA_TOOL_FLAGS are additional options if the testcase has none.
 
609
 
 
610
#proc dg-test { prog tool_flags default_extra_tool_flags } {
 
611
proc dg-test { args } {
 
612
    global dg-do-what-default dg-interpreter-batch-mode dg-linenum-format
 
613
    global errorCode errorInfo
 
614
    global tool
 
615
    global srcdir               ;# eg: /calvin/dje/build/gcc/./testsuite/
 
616
    global host_triplet target_triplet
 
617
 
 
618
    set keep 0
 
619
    set i 0
 
620
 
 
621
    if { [string index [lindex $args 0] 0] == "-" } {
 
622
        for { set i 0 } { $i < [llength $args] } { incr i } {
 
623
            if { [lindex $args $i] == "--" } {
 
624
                incr i
 
625
                break
 
626
            } elseif { [lindex $args $i] == "-keep-output" } {
 
627
                set keep 1
 
628
            } elseif { [string index [lindex $args $i] 0] == "-" } {
 
629
                clone_output "ERROR: dg-test: illegal argument: [lindex $args $i]"
 
630
                return
 
631
            } else {
 
632
                break
 
633
            }
 
634
        }
 
635
    }
 
636
 
 
637
    if { $i + 3 != [llength $args] } {
 
638
        clone_output "ERROR: dg-test: missing arguments in call"
 
639
        return
 
640
    }
 
641
    set prog [lindex $args $i]
 
642
    set tool_flags [lindex $args [expr $i + 1]]
 
643
    set default_extra_tool_flags [lindex $args [expr $i + 2]]
 
644
 
 
645
    set text "\[- A-Za-z0-9\.\;\"\_\:\'\`\(\)\!\#\=\+\?\&\*]*"
 
646
 
 
647
    set name [dg-trim-dirname $srcdir $prog]
 
648
    # If we couldn't rip $srcdir out of `prog' then just do the best we can.
 
649
    # The point is to reduce the unnecessary noise in the logs.  Don't strip
 
650
    # out too much because different testcases with the same name can confuse
 
651
    # `test-tool'.
 
652
    if [string match "/*" $name] {
 
653
        set name "[file tail [file dirname $prog]]/[file tail $prog]"
 
654
    }
 
655
 
 
656
    # We append the compilation flags, if any, to ensure that the test case
 
657
    # names are unique.
 
658
    if { "$tool_flags" != "" } {
 
659
        set name "$name $tool_flags"
 
660
    }
 
661
 
 
662
    # Process any embedded dg options in the testcase.
 
663
 
 
664
    # Use "" for the second element of dg-do-what so we can tell if it's been
 
665
    # explicitly set to "S".
 
666
    set dg-do-what [list ${dg-do-what-default} "" P]
 
667
    set dg-excess-errors-flag 0
 
668
    set dg-messages ""
 
669
    set dg-extra-tool-flags $default_extra_tool_flags
 
670
    set dg-final-code ""
 
671
 
 
672
    # `dg-output-text' is a list of two elements: pass/fail and text.
 
673
    # Leave second element off for now (indicates "don't perform test")
 
674
    set dg-output-text "P"
 
675
 
 
676
    # Define our own "special function" `unknown' so we catch spelling errors.
 
677
    # But first rename the existing one so we can restore it afterwards.
 
678
    catch {rename dg-save-unknown ""}
 
679
    rename unknown dg-save-unknown
 
680
    proc unknown { args } {
 
681
        return -code error "unknown dg option: $args"
 
682
    }
 
683
 
 
684
    set tmp [dg-get-options $prog]
 
685
    foreach op $tmp {
 
686
        verbose "Processing option: $op" 3
 
687
        set status [catch "$op" errmsg]
 
688
        if { $status != 0 } {
 
689
            if { 0 && [info exists errorInfo] } {
 
690
                # This also prints a backtrace which will just confuse
 
691
                # testcase writers, so it's disabled.
 
692
                perror "$name: $errorInfo\n"
 
693
            } else {
 
694
                perror "$name: $errmsg for \"$op\"\n"
 
695
            }
 
696
            # ??? The call to unresolved here is necessary to clear `errcnt'.
 
697
            # What we really need is a proc like perror that doesn't set errcnt.
 
698
            # It should also set exit_status to 1.
 
699
            unresolved "$name: $errmsg for \"$op\""
 
700
            return
 
701
        }
 
702
    }
 
703
 
 
704
    # Restore normal error handling.
 
705
    rename unknown ""
 
706
    rename dg-save-unknown unknown
 
707
 
 
708
    # If we're not supposed to try this test on this target, we're done.
 
709
    if { [lindex ${dg-do-what} 1] == "N" } {
 
710
        unsupported "$name"
 
711
        verbose "$name not supported on this target, skipping it" 3
 
712
        return
 
713
    }
 
714
 
 
715
    # Run the tool and analyze the results.
 
716
    # The result of ${tool}-dg-test is in a bit of flux.
 
717
    # Currently it is the name of the output file (or "" if none).
 
718
    # If we need more than this it will grow into a list of things.
 
719
    # No intention is made (at this point) to preserve upward compatibility
 
720
    # (though at some point we'll have to).
 
721
 
 
722
    set results [${tool}-dg-test $prog [lindex ${dg-do-what} 0] "$tool_flags ${dg-extra-tool-flags}"]
 
723
 
 
724
    set comp_output [lindex $results 0]
 
725
    set output_file [lindex $results 1]
 
726
 
 
727
    #send_user "\nold_dejagnu.exp: comp_output1 = :$comp_output:\n\n"
 
728
    #send_user "\nold_dejagnu.exp: message = :$message:\n\n"
 
729
    #send_user "\nold_dejagnu.exp: message length = [llength $message]\n\n"
 
730
 
 
731
    foreach i ${dg-messages} {
 
732
        verbose "Scanning for message: $i" 4
 
733
 
 
734
        # Remove all error messages for the line [lindex $i 0]
 
735
        # in the source file.  If we find any, success!
 
736
        set line [lindex $i 0]
 
737
        set pattern [lindex $i 2]
 
738
        set comment [lindex $i 3]
 
739
        #send_user "Before:\n$comp_output\n"
 
740
        if [regsub -all "(^|\n)(\[^\n\]+$line\[^\n\]*($pattern)\[^\n\]*\n?)+" $comp_output "\n" comp_output] {
 
741
            set comp_output [string trimleft $comp_output]
 
742
            set ok pass
 
743
            set uhoh fail
 
744
        } else {
 
745
            set ok fail
 
746
            set uhoh pass
 
747
        }
 
748
        #send_user "After:\n$comp_output\n"
 
749
 
 
750
        # $line will either be a formatted line number or a number all by
 
751
        # itself.  Delete the formatting.
 
752
        scan $line ${dg-linenum-format} line
 
753
        switch [lindex $i 1] {
 
754
            "ERROR" {
 
755
                $ok "$name $comment (test for errors, line $line)"
 
756
            }
 
757
            "XERROR" {
 
758
                x$ok "$name $comment (test for errors, line $line)"
 
759
            }
 
760
            "WARNING" {
 
761
                $ok "$name $comment (test for warnings, line $line)"
 
762
            }
 
763
            "XWARNING" {
 
764
                x$ok "$name $comment (test for warnings, line $line)"
 
765
            }
 
766
            "BOGUS" {
 
767
                $uhoh "$name $comment (test for bogus messages, line $line)"
 
768
            }
 
769
            "XBOGUS" {
 
770
                x$uhoh "$name $comment (test for bogus messages, line $line)"
 
771
            }
 
772
            "BUILD" {
 
773
                $uhoh "$name $comment (test for build failure, line $line)"
 
774
            }
 
775
            "XBUILD" {
 
776
                x$uhoh "$name $comment (test for build failure, line $line)"
 
777
            }
 
778
            "EXEC" { }
 
779
            "XEXEC" { }
 
780
        }
 
781
        #send_user "\nold_dejagnu.exp: comp_output2= :$comp_output:\n\n"
 
782
    }
 
783
    #send_user "\nold_dejagnu.exp: comp_output3 = :$comp_output:\n\n"
 
784
 
 
785
    # Remove messages from the tool that we can ignore.
 
786
    #send_user "comp_output: $comp_output\n"
 
787
    set comp_output [prune_warnings $comp_output]
 
788
 
 
789
    if { [info proc ${tool}-dg-prune] != "" } {
 
790
        set comp_output [${tool}-dg-prune $target_triplet $comp_output]
 
791
        switch -glob $comp_output {
 
792
            "::untested::*" {
 
793
                regsub "::untested::" $comp_output "" message
 
794
                untested "$name: $message"
 
795
                return
 
796
            }
 
797
            "::unresolved::*" {
 
798
                regsub "::unresolved::" $comp_output "" message
 
799
                unresolved "$name: $message"
 
800
                return
 
801
            }
 
802
            "::unsupported::*" {
 
803
                regsub "::unsupported::" $comp_output "" message
 
804
                unsupported "$name: $message"
 
805
                return
 
806
            }
 
807
        }
 
808
    }
 
809
 
 
810
    # See if someone forgot to delete the extra lines.
 
811
    regsub -all "\n+" $comp_output "\n" comp_output
 
812
    regsub "^\n+" $comp_output "" comp_output
 
813
    #send_user "comp_output: $comp_output\n"
 
814
 
 
815
    # Don't do this if we're testing an interpreter.
 
816
    # FIXME: why?
 
817
    if { ${dg-interpreter-batch-mode} == 0 } {
 
818
        # Catch excess errors (new bugs or incomplete testcases).
 
819
        if ${dg-excess-errors-flag} {
 
820
            setup_xfail "*-*-*"
 
821
        }
 
822
        if ![string match "" $comp_output] {
 
823
            fail "$name (test for excess errors)"
 
824
            send_log "Excess errors:\n$comp_output\n"
 
825
        } else {
 
826
            pass "$name (test for excess errors)"
 
827
        }
 
828
    }
 
829
 
 
830
    # Run the executable image if asked to do so.
 
831
    # FIXME: This is the only place where we assume a standard meaning to
 
832
    # the `keyword' argument of dg-do.  This could be cleaned up.
 
833
    if { [lindex ${dg-do-what} 0] == "run" } {
 
834
        if ![file exists $output_file] {
 
835
            warning "$name compilation failed to produce executable"
 
836
        } else {
 
837
            set status -1
 
838
            set result [${tool}_load $output_file]
 
839
            set status [lindex $result 0]
 
840
            set output [lindex $result 1]
 
841
            #send_user "After exec, status: $status\n"
 
842
            if { [lindex ${dg-do-what} 2] == "F" } {
 
843
                setup_xfail "*-*-*"
 
844
            }
 
845
            if { "$status" == "pass" } {
 
846
                pass "$name execution test"
 
847
                verbose "Exec succeeded." 3
 
848
                if { [llength ${dg-output-text}] > 1 } {
 
849
                    #send_user "${dg-output-text}\n"
 
850
                    if { [lindex ${dg-output-text} 0] == "F" } {
 
851
                        setup_xfail "*-*-*"
 
852
                    }
 
853
                    set texttmp [lindex ${dg-output-text} 1]
 
854
                    if { ![regexp $texttmp ${output}] } {
 
855
                        fail "$name output pattern test, is ${output}, should match $texttmp"
 
856
                        verbose "Failed test for output pattern $texttmp" 3
 
857
                    } else {
 
858
                        pass "$name output pattern test, $texttmp"
 
859
                        verbose "Passed test for output pattern $texttmp" 3
 
860
                    }
 
861
                    unset texttmp
 
862
                }
 
863
            } elseif { "$status" == "fail" } {
 
864
                # It would be nice to get some info out of errorCode.
 
865
                if [info exists errorCode] {
 
866
                    verbose "Exec failed, errorCode: $errorCode" 3
 
867
                } else {
 
868
                    verbose "Exec failed, errorCode not defined!" 3
 
869
                }
 
870
                fail "$name execution test"
 
871
            } else {
 
872
                $status "$name execution test"
 
873
            }
 
874
        }
 
875
    }
 
876
 
 
877
    # Are there any further tests to perform?
 
878
    # Note that if the program has special run-time requirements, running
 
879
    # of the program can be delayed until here.  Ditto for other situations.
 
880
    # It would be a bit cumbersome though.
 
881
 
 
882
    if ![string match ${dg-final-code} ""] {
 
883
        regsub -all "\\\\(\[{}\])" ${dg-final-code} "\\1" dg-final-code
 
884
        # Note that the use of `args' here makes this a varargs proc.
 
885
        proc dg-final-proc { args } ${dg-final-code}
 
886
        verbose "Running dg-final tests." 3
 
887
        verbose "dg-final-proc:\n[info body dg-final-proc]" 4
 
888
        if [catch "dg-final-proc $prog" errmsg] {
 
889
            perror "$name: error executing dg-final: $errmsg"
 
890
            # ??? The call to unresolved here is necessary to clear `errcnt'.
 
891
            # What we really need is a proc like perror that doesn't set errcnt.
 
892
            # It should also set exit_status to 1.
 
893
            unresolved "$name: error executing dg-final: $errmsg"
 
894
        }
 
895
    }
 
896
 
 
897
    # Do some final clean up.
 
898
    # When testing an interpreter, we don't compile something and leave an
 
899
    # output file.
 
900
    if { ! ${keep} && ${dg-interpreter-batch-mode} == 0 } {
 
901
        catch "exec rm -f $output_file"
 
902
    }
 
903
}
 
904
 
 
905
#
 
906
# Do any necessary cleanups
 
907
#
 
908
# This is called at the end to undo anything dg-init did (that needs undoing).
 
909
#
 
910
proc dg-finish { } {
 
911
    # Reset this in case caller wonders whether s/he should.
 
912
    global prms_id
 
913
    set prms_id 0
 
914
 
 
915
    # The framework doesn't like to see any error remnants, so remove them.
 
916
    global errorInfo
 
917
    if [info exists errorInfo] {
 
918
        unset errorInfo
 
919
    }
 
920
 
 
921
    # If the tool has a "finish" routine, call it.
 
922
    # There may be a bit of duplication (eg: resetting prms_id), leave it.
 
923
    # Let's keep these procs robust.
 
924
    global tool
 
925
    if ![string match "" [info procs ${tool}_finish]] {
 
926
        ${tool}_finish
 
927
    }
 
928
}