bfd/
[platform/upstream/binutils.git] / ld / testsuite / lib / ld-lib.exp
1 # Support routines for LD testsuite.
2 #   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 #    2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4 #
5 # This file is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
18
19 # Extract and print the version number of ld.
20 #
21 proc default_ld_version { ld } {
22     global host_triplet
23
24     if { [which $ld] == 0 } then {
25         perror "$ld does not exist"
26         exit 1
27     }
28
29     catch "exec $ld --version" tmp
30     set tmp [prune_warnings $tmp]
31     regexp "\[^\n\]* (cygnus-|)(\[-0-9.a-zA-Z-\]+)\[\r\n\].*" $tmp version cyg number
32     if [info exists number] then {
33         clone_output "$ld $number\n"
34     }
35 }
36
37 # Link an object using relocation.
38 #
39 proc default_ld_relocate { ld target objects } {
40     global HOSTING_EMU
41     global host_triplet
42     global exec_output
43
44     if { [which $ld] == 0 } then {
45         perror "$ld does not exist"
46         return 0
47     }
48
49     catch "exec rm -f $target" exec_output
50
51     verbose -log "$ld $HOSTING_EMU -o $target -r $objects"
52
53     catch "exec $ld $HOSTING_EMU -o $target -r $objects" exec_output
54     set exec_output [prune_warnings $exec_output]
55     if [string match "" $exec_output] then {
56         return 1
57     } else {
58         verbose -log "$exec_output"
59         return 0
60     }
61 }
62
63 # Check to see if ld is being invoked with a non-endian output format
64 #
65 proc is_endian_output_format { object_flags } {
66
67     if {[string match "*-oformat binary*" $object_flags] ||      \
68         [string match "*-oformat ieee*" $object_flags] ||        \
69         [string match "*-oformat ihex*" $object_flags] ||        \
70         [string match "*-oformat netbsd-core*" $object_flags] || \
71         [string match "*-oformat srec*" $object_flags] ||        \
72         [string match "*-oformat tekhex*" $object_flags] ||      \
73         [string match "*-oformat trad-core*" $object_flags] } then {
74         return 0
75     } else {
76         return 1
77     }
78 }
79
80 # Look for big-endian or little-endian switches in the multlib
81 # options and translate these into a -EB or -EL switch.  Note
82 # we cannot rely upon proc process_multilib_options to do this
83 # for us because for some targets the compiler does not support
84 # -EB/-EL but it does support -mbig-endian/-mlittle-endian, and
85 # the site.exp file will include the switch "-mbig-endian"
86 # (rather than "big-endian") which is not detected by proc
87 # process_multilib_options.
88 #
89 proc big_or_little_endian {} {
90
91     if [board_info [target_info name] exists multilib_flags] {
92         set tmp_flags " [board_info [target_info name] multilib_flags]"
93
94         foreach x $tmp_flags {
95             case $x in {
96                 {*big*endian eb EB -eb -EB -mb -meb} {
97                     set flags " -EB"
98                     return $flags
99                 }
100                 {*little*endian el EL -el -EL -ml -mel} {
101                     set flags " -EL"
102                     return $flags
103                 }
104             }
105         }
106     }
107
108     set flags ""
109     return $flags
110 }
111
112 # Link a program using ld.
113 #
114 proc default_ld_link { ld target objects } {
115     global HOSTING_EMU
116     global HOSTING_CRT0
117     global HOSTING_LIBS
118     global LIBS
119     global host_triplet
120     global link_output
121     global exec_output
122
123     set objs "$HOSTING_CRT0 $objects"
124     set libs "$LIBS $HOSTING_LIBS"
125
126     if { [which $ld] == 0 } then {
127         perror "$ld does not exist"
128         return 0
129     }
130
131     if [is_endian_output_format $objects] then {
132         set flags [big_or_little_endian]
133     } else {
134         set flags ""
135     }
136
137     catch "exec rm -f $target" exec_output
138
139     verbose -log "$ld $HOSTING_EMU $flags -o $target $objs $libs"
140
141     catch "exec $ld $HOSTING_EMU $flags -o $target $objs $libs" link_output
142     set exec_output [prune_warnings $link_output]
143     if [string match "" $exec_output] then {
144         return 1
145     } else {
146         verbose -log "$exec_output"
147         return 0
148     }
149 }
150
151 # Link a program using ld, without including any libraries.
152 #
153 proc default_ld_simple_link { ld target objects } {
154     global host_triplet
155     global link_output
156     global gcc_ld_flag
157     global exec_output
158
159     if { [which $ld] == 0 } then {
160         perror "$ld does not exist"
161         return 0
162     }
163
164     if [is_endian_output_format $objects] then {
165         set flags [big_or_little_endian]
166     } else {
167         set flags ""
168     }
169
170     # If we are compiling with gcc, we want to add gcc_ld_flag to
171     # flags.  Rather than determine this in some complex way, we guess
172     # based on the name of the compiler.
173     set ldexe $ld
174     set ldparm [string first " " $ld]
175     if { $ldparm > 0 } then {
176         set ldexe [string range $ld 0 $ldparm]
177     }
178     set ldexe [string replace $ldexe 0 [string last "/" $ldexe] ""]
179     if {[string match "*gcc*" $ldexe] || [string match "*++*" $ldexe]} then {
180         set flags "$gcc_ld_flag $flags"
181     }
182
183     catch "exec rm -f $target" exec_output
184
185     verbose -log "$ld $flags -o $target $objects"
186
187     catch "exec $ld $flags -o $target $objects" link_output
188     set exec_output [prune_warnings $link_output]
189
190     # We don't care if we get a warning about a non-existent start
191     # symbol, since the default linker script might use ENTRY.
192     regsub -all "(^|\n)(\[^\n\]*: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
193
194     if [string match "" $exec_output] then {
195         return 1
196     } else {
197         verbose -log "$exec_output"
198         return 0
199     }
200 }
201
202 # Compile an object using cc.
203 #
204 proc default_ld_compile { cc source object } {
205     global CFLAGS
206     global srcdir
207     global subdir
208     global host_triplet
209     global gcc_gas_flag
210
211     set cc_prog $cc
212     if {[llength $cc_prog] > 1} then {
213         set cc_prog [lindex $cc_prog 0]
214     }
215     if {[which $cc_prog] == 0} then {
216         perror "$cc_prog does not exist"
217         return 0
218     }
219
220     catch "exec rm -f $object" exec_output
221
222     set flags "-I$srcdir/$subdir $CFLAGS"
223
224     # If we are compiling with gcc, we want to add gcc_gas_flag to
225     # flags.  Rather than determine this in some complex way, we guess
226     # based on the name of the compiler.
227     set ccexe $cc
228     set ccparm [string first " " $cc]
229     set ccflags ""
230     if { $ccparm > 0 } then {
231         set ccflags [string range $cc $ccparm end]
232         set ccexe [string range $cc 0 $ccparm]
233         set cc $ccexe
234     }
235     set ccexe [string replace $ccexe 0 [string last "/" $ccexe] ""]
236     if {[string match "*gcc*" $ccexe] || [string match "*++*" $ccexe]} then {
237         set flags "$gcc_gas_flag $flags"
238     }
239
240     if [board_info [target_info name] exists multilib_flags] {
241         append flags " [board_info [target_info name] multilib_flags]"
242     }
243
244     verbose -log "$cc $flags $ccflags -c $source -o $object"
245
246     catch "exec $cc $flags $ccflags -c $source -o $object" exec_output
247     set exec_output [prune_warnings $exec_output]
248     if [string match "" $exec_output] then {
249         if {![file exists $object]} then {
250             regexp ".*/(\[^/\]*)$" $source all dobj
251             regsub "\\.c" $dobj ".o" realobj
252             verbose "looking for $realobj"
253             if {[file exists $realobj]} then {
254                 verbose -log "mv $realobj $object"
255                 catch "exec mv $realobj $object" exec_output
256                 set exec_output [prune_warnings $exec_output]
257                 if {![string match "" $exec_output]} then {
258                     verbose -log "$exec_output"
259                     perror "could not move $realobj to $object"
260                     return 0
261                 }
262             } else {
263                 perror "$object not found after compilation"
264                 return 0
265             }
266         }
267         return 1
268     } else {
269         verbose -log "$exec_output"
270         perror "$source: compilation failed"
271         return 0
272     }
273 }
274
275 # Assemble a file.
276 #
277 proc default_ld_assemble { as source object } {
278     global ASFLAGS
279     global host_triplet
280
281     if {[which $as] == 0} then {
282         perror "$as does not exist"
283         return 0
284     }
285
286     if ![info exists ASFLAGS] { set ASFLAGS "" }
287
288     set flags [big_or_little_endian]
289
290     verbose -log "$as $flags $ASFLAGS -o $object $source"
291
292     catch "exec $as $flags $ASFLAGS -o $object $source" exec_output
293     set exec_output [prune_warnings $exec_output]
294     if [string match "" $exec_output] then {
295         return 1
296     } else {
297         verbose -log "$exec_output"
298         perror "$source: assembly failed"
299         return 0
300     }
301 }
302
303 # Run nm on a file, putting the result in the array nm_output.
304 #
305 proc default_ld_nm { nm nmflags object } {
306     global NMFLAGS
307     global nm_output
308     global host_triplet
309
310     if {[which $nm] == 0} then {
311         perror "$nm does not exist"
312         return 0
313     }
314
315     if {[info exists nm_output]} {
316       unset nm_output
317     }
318
319     if ![info exists NMFLAGS] { set NMFLAGS "" }
320
321     # Ensure consistent sorting of symbols
322     if {[info exists env(LC_ALL)]} {
323         set old_lc_all $env(LC_ALL)
324     }
325     set env(LC_ALL) "C"
326     verbose -log "$nm $NMFLAGS $nmflags $object >tmpdir/nm.out"
327
328     catch "exec $nm $NMFLAGS $nmflags $object >tmpdir/nm.out" exec_output
329     if {[info exists old_lc_all]} {
330         set env(LC_ALL) $old_lc_all
331     } else {
332         unset env(LC_ALL)
333     }
334     set exec_output [prune_warnings $exec_output]
335     if [string match "" $exec_output] then {
336         set file [open tmpdir/nm.out r]
337         while { [gets $file line] != -1 } {
338             verbose "$line" 2
339             if [regexp "^(\[0-9a-fA-F\]+) \[a-zA-Z0-9\] \\.*(.+)$" $line whole value name] {
340                 set name [string trimleft $name "_"]
341                 verbose "Setting nm_output($name) to 0x$value" 2
342                 set nm_output($name) 0x$value
343             }
344         }
345         close $file
346         return 1
347     } else {
348         verbose -log "$exec_output"
349         perror "$object: nm failed"
350         return 0
351     }
352 }
353
354 # True if the object format is known to be ELF.
355 #
356 proc is_elf_format {} {
357     if { ![istarget *-*-sysv4*] \
358          && ![istarget *-*-unixware*] \
359          && ![istarget *-*-elf*] \
360          && ![istarget *-*-eabi*] \
361          && ![istarget hppa*64*-*-hpux*] \
362          && ![istarget *-*-linux*] \
363          && ![istarget frv-*-uclinux*] \
364          && ![istarget *-*-irix5*] \
365          && ![istarget *-*-irix6*] \
366          && ![istarget *-*-netbsd*] \
367          && ![istarget *-*-solaris2*] } {
368         return 0
369     }
370
371     if { [istarget *-*-linux*aout*] \
372          || [istarget *-*-linux*oldld*] } {
373         return 0
374     }
375
376     if { ![istarget *-*-netbsdelf*] \
377          && ([istarget *-*-netbsd*aout*] \
378              || [istarget *-*-netbsdpe*] \
379              || [istarget arm*-*-netbsd*] \
380              || [istarget sparc-*-netbsd*] \
381              || [istarget i*86-*-netbsd*] \
382              || [istarget m68*-*-netbsd*] \
383              || [istarget vax-*-netbsd*] \
384              || [istarget ns32k-*-netbsd*]) } {
385         return 0
386     }
387     return 1
388 }
389
390 # True if the object format is known to be 64-bit ELF.
391 #
392 proc is_elf64 { binary_file } {
393     global READELF
394     global READELFFLAGS
395
396     set readelf_size ""
397     catch "exec $READELF $READELFFLAGS -h $binary_file > readelf.out" got
398
399     if ![string match "" $got] then {
400         return 0
401     }
402
403     if { ![regexp "\n\[ \]*Class:\[ \]*ELF(\[0-9\]+)\n" \
404            [file_contents readelf.out] nil readelf_size] } {
405         return 0
406     }
407
408     if { $readelf_size == "64" } {
409         return 1
410     }
411
412     return 0
413 }
414
415 # True if the object format is known to be a.out.
416 #
417 proc is_aout_format {} {
418     if { [istarget *-*-*\[ab\]out*] \
419              || [istarget *-*-linux*oldld*] \
420              || [istarget *-*-msdos*] \
421              || [istarget arm-*-netbsd] \
422              || [istarget i?86-*-netbsd] \
423              || [istarget i?86-*-mach*] \
424              || [istarget i?86-*-vsta] \
425              || [istarget pdp11-*-*] \
426              || [istarget m68*-ericsson-ose] \
427              || [istarget m68k-hp-bsd*] \
428              || [istarget m68*-*-hpux*] \
429              || [istarget m68*-*-netbsd] \
430              || [istarget m68*-*-netbsd*4k*] \
431              || [istarget m68k-sony-*] \
432              || [istarget m68*-sun-sunos\[34\]*] \
433              || [istarget m68*-wrs-vxworks*] \
434              || [istarget ns32k-*-*] \
435              || [istarget sparc*-*-netbsd] \
436              || [istarget sparc-sun-sunos4*] \
437              || [istarget vax-dec-ultrix*] \
438              || [istarget vax-*-netbsd] } {
439         return 1
440     }
441     return 0
442 }
443
444 # True if the object format is known to be PE COFF.
445 #
446 proc is_pecoff_format {} {
447     if { ![istarget *-*-mingw*] \
448          && ![istarget *-*-cygwin*] \
449          && ![istarget *-*-pe*] } {
450         return 0
451     }
452
453     return 1
454 }
455
456 # Compares two files line-by-line.
457 #   Returns differences if exist.
458 #   Returns null if file(s) cannot be opened.
459 #
460 proc simple_diff { file_1 file_2 } {
461     global target
462
463     set eof -1
464     set differences 0
465
466     if [file exists $file_1] then {
467         set file_a [open $file_1 r]
468     } else {
469         warning "$file_1 doesn't exist"
470         return
471     }
472
473     if [file exists $file_2] then {
474         set file_b [open $file_2 r]
475     } else {
476         fail "$file_2 doesn't exist"
477         return
478     }
479
480     verbose "# Diff'ing: $file_1 $file_2\n" 2
481
482     while { [gets $file_a line] != $eof } {
483         if [regexp "^#.*$" $line] then {
484             continue
485         } else {
486             lappend list_a $line
487         }
488     }
489     close $file_a
490
491     while { [gets $file_b line] != $eof } {
492         if [regexp "^#.*$" $line] then {
493             continue
494         } else {
495             lappend list_b $line
496         }
497     }
498     close $file_b
499
500     for { set i 0 } { $i < [llength $list_a] } { incr i } {
501         set line_a [lindex $list_a $i]
502         set line_b [lindex $list_b $i]
503
504         verbose "\t$file_1: $i: $line_a\n" 3
505         verbose "\t$file_2: $i: $line_b\n" 3
506         if [string compare $line_a $line_b] then {
507             verbose -log "\t$file_1: $i: $line_a\n"
508             verbose -log "\t$file_2: $i: $line_b\n"
509
510             fail "Test: $target"
511             return
512         }
513     }
514
515     if { [llength $list_a] != [llength $list_b] } {
516         fail "Test: $target"
517         return
518     }
519
520     if $differences<1 then {
521         pass "Test: $target"
522     }
523 }
524
525 # run_dump_test FILE
526 # Copied from gas testsuite, tweaked and further extended.
527 #
528 # Assemble a .s file, then run some utility on it and check the output.
529 #
530 # There should be an assembly language file named FILE.s in the test
531 # suite directory, and a pattern file called FILE.d.  `run_dump_test'
532 # will assemble FILE.s, run some tool like `objdump', `objcopy', or
533 # `nm' on the .o file to produce textual output, and then analyze that
534 # with regexps.  The FILE.d file specifies what program to run, and
535 # what to expect in its output.
536 #
537 # The FILE.d file begins with zero or more option lines, which specify
538 # flags to pass to the assembler, the program to run to dump the
539 # assembler's output, and the options it wants.  The option lines have
540 # the syntax:
541 #
542 #         # OPTION: VALUE
543 #
544 # OPTION is the name of some option, like "name" or "objdump", and
545 # VALUE is OPTION's value.  The valid options are described below.
546 # Whitespace is ignored everywhere, except within VALUE.  The option
547 # list ends with the first line that doesn't match the above syntax
548 # (hmm, not great for error detection).
549 #
550 # The interesting options are:
551 #
552 #   name: TEST-NAME
553 #       The name of this test, passed to DejaGNU's `pass' and `fail'
554 #       commands.  If omitted, this defaults to FILE, the root of the
555 #       .s and .d files' names.
556 #
557 #   as: FLAGS
558 #       When assembling, pass FLAGS to the assembler.
559 #       If assembling several files, you can pass different assembler
560 #       options in the "source" directives.  See below.
561 #
562 #   ld: FLAGS
563 #       Link assembled files using FLAGS, in the order of the "source"
564 #       directives, when using multiple files.
565 #
566 #   objcopy_linked_file: FLAGS
567 #       Run objcopy on the linked file with the specified flags.
568 #       This lets you transform the linked file using objcopy, before the
569 #       result is analyzed by an analyzer program specified below (which
570 #       may in turn *also* be objcopy).
571 #
572 #   PROG: PROGRAM-NAME
573 #       The name of the program to run to analyze the .o file produced
574 #       by the assembler or the linker output.  This can be omitted;
575 #       run_dump_test will guess which program to run by seeing which of
576 #       the flags options below is present.
577 #
578 #   objdump: FLAGS
579 #   nm: FLAGS
580 #   objcopy: FLAGS
581 #       Use the specified program to analyze the assembler or linker
582 #       output file, and pass it FLAGS, in addition to the output name.
583 #       Note that they are run with LC_ALL=C in the environment to give
584 #       consistent sorting of symbols.
585 #
586 #   source: SOURCE [FLAGS]
587 #       Assemble the file SOURCE.s using the flags in the "as" directive
588 #       and the (optional) FLAGS.  If omitted, the source defaults to
589 #       FILE.s.
590 #       This is useful if several .d files want to share a .s file.
591 #       More than one "source" directive can be given, which is useful
592 #       when testing linking.
593 #
594 #   xfail: TARGET
595 #       The test is expected to fail on TARGET.  This may occur more than
596 #       once.
597 #
598 #   target: TARGET
599 #       Only run the test for TARGET.  This may occur more than once; the
600 #       target being tested must match at least one.
601 #
602 #   notarget: TARGET
603 #       Do not run the test for TARGET.  This may occur more than once;
604 #       the target being tested must not match any of them.
605 #
606 #   error: REGEX
607 #       An error with message matching REGEX must be emitted for the test
608 #       to pass.  The PROG, objdump, nm and objcopy options have no
609 #       meaning and need not supplied if this is present.
610 #
611 #   warning: REGEX
612 #       Expect a linker warning matching REGEX.  It is an error to issue
613 #       both "error" and "warning".
614 #
615 # Each option may occur at most once unless otherwise mentioned.
616 #
617 # After the option lines come regexp lines.  `run_dump_test' calls
618 # `regexp_diff' to compare the output of the dumping tool against the
619 # regexps in FILE.d.  `regexp_diff' is defined later in this file; see
620 # further comments there.
621 #
622 proc run_dump_test { name } {
623     global subdir srcdir
624     global OBJDUMP NM AS OBJCOPY READELF LD
625     global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS
626     global host_triplet runtests
627     global env
628
629     if [string match "*/*" $name] {
630         set file $name
631         set name [file tail $name]
632     } else {
633         set file "$srcdir/$subdir/$name"
634     }
635
636     if ![runtest_file_p $runtests $name] then {
637         return
638     }
639
640     set opt_array [slurp_options "${file}.d"]
641     if { $opt_array == -1 } {
642         perror "error reading options from $file.d"
643         unresolved $subdir/$name
644         return
645     }
646     set dumpfile tmpdir/dump.out
647     set run_ld 0
648     set run_objcopy 0
649     set opts(as) {}
650     set opts(ld) {}
651     set opts(xfail) {}
652     set opts(target) {}
653     set opts(notarget) {}
654     set opts(objdump) {}
655     set opts(nm) {}
656     set opts(objcopy) {}
657     set opts(readelf) {}
658     set opts(name) {}
659     set opts(PROG) {}
660     set opts(source) {}
661     set opts(error) {}
662     set opts(warning) {}
663     set opts(objcopy_linked_file) {}
664     set asflags(${file}.s) {}
665
666     foreach i $opt_array {
667         set opt_name [lindex $i 0]
668         set opt_val [lindex $i 1]
669         if ![info exists opts($opt_name)] {
670             perror "unknown option $opt_name in file $file.d"
671             unresolved $subdir/$name
672             return
673         }
674
675         switch -- $opt_name {
676             xfail {}
677             target {}
678             notarget {}
679             source {
680                 # Move any source-specific as-flags to a separate array to
681                 # simplify processing.
682                 if { [llength $opt_val] > 1 } {
683                     set asflags([lindex $opt_val 0]) [lrange $opt_val 1 end]
684                     set opt_val [lindex $opt_val 0]
685                 } else {
686                     set asflags($opt_val) {}
687                 }
688             }
689             default {
690                 if [string length $opts($opt_name)] {
691                     perror "option $opt_name multiply set in $file.d"
692                     unresolved $subdir/$name
693                     return
694                 }
695
696                 # A single "# ld:" with no options should do the right thing.
697                 if { $opt_name == "ld" } {
698                     set run_ld 1
699                 }
700                 # Likewise objcopy_linked_file.
701                 if { $opt_name == "objcopy_linked_file" } {
702                     set run_objcopy 1
703                 }
704             }
705         }
706         set opts($opt_name) [concat $opts($opt_name) $opt_val]
707     }
708
709     # Decide early whether we should run the test for this target.
710     if { [llength $opts(target)] > 0 } {
711         set targmatch 0
712         foreach targ $opts(target) {
713             if [istarget $targ] {
714                 set targmatch 1
715                 break
716             }
717         }
718         if { $targmatch == 0 } {
719             return
720         }
721     }
722     foreach targ $opts(notarget) {
723         if [istarget $targ] {
724             return
725         }
726     }
727
728     set program ""
729     # It's meaningless to require an output-testing method when we
730     # expect an error.
731     if { $opts(error) == "" } {
732         if {$opts(PROG) != ""} {
733             switch -- $opts(PROG) {
734                 objdump { set program objdump }
735                 nm      { set program nm }
736                 objcopy { set program objcopy }
737                 readelf { set program readelf }
738                 default
739                 { perror "unrecognized program option $opts(PROG) in $file.d"
740                   unresolved $subdir/$name
741                   return }
742             }
743         } else {
744         # Guess which program to run, by seeing which option was specified.
745             foreach p {objdump objcopy nm readelf} {
746                 if {$opts($p) != ""} {
747                     if {$program != ""} {
748                         perror "ambiguous dump program in $file.d"
749                         unresolved $subdir/$name
750                         return
751                     } else {
752                         set program $p
753                     }
754                 }
755             }
756         }
757         if { $program == "" && $opts(warning) == "" } {
758             perror "dump program unspecified in $file.d"
759             unresolved $subdir/$name
760             return
761         }
762     }
763
764     if { $opts(name) == "" } {
765         set testname "$subdir/$name"
766     } else {
767         set testname $opts(name)
768     }
769
770     if { $opts(source) == "" } {
771         set sourcefiles [list ${file}.s]
772     } else {
773         set sourcefiles {}
774         foreach sf $opts(source) {
775             if { [string match "/*" $sf] } {
776                 lappend sourcefiles "$sf"
777             } else {
778                 lappend sourcefiles "$srcdir/$subdir/$sf"
779             }
780             # Must have asflags indexed on source name.
781             set asflags($srcdir/$subdir/$sf) $asflags($sf)
782         }
783     }
784
785     # Time to setup xfailures.
786     foreach targ $opts(xfail) {
787         setup_xfail $targ
788     }
789
790     # Assemble each file.
791     set objfiles {}
792     for { set i 0 } { $i < [llength $sourcefiles] } { incr i } {
793         set sourcefile [lindex $sourcefiles $i]
794
795         set objfile "tmpdir/dump$i.o"
796         catch "exec rm -f $objfile" exec_output
797         lappend objfiles $objfile
798         set cmd "$AS $ASFLAGS $opts(as) $asflags($sourcefile) -o $objfile $sourcefile"
799
800         send_log "$cmd\n"
801         set cmdret [catch "exec $cmd" comp_output]
802         set comp_output [prune_warnings $comp_output]
803
804         if { $cmdret != 0 || ![string match "" $comp_output] } then {
805             send_log "$comp_output\n"
806             verbose "$comp_output" 3
807
808             set exitstat "succeeded"
809             if { $cmdret != 0 } { set exitstat "failed" }
810             verbose -log "$exitstat with: <$comp_output>"
811             fail $testname
812             return
813         }
814     }
815
816     set expmsg $opts(error)
817     if { $opts(warning) != "" } {
818         if { $expmsg != "" } {
819             perror "$testname: mixing error and warning test-directives"
820             return
821         }
822         set expmsg $opts(warning)
823     }
824
825     # Perhaps link the file(s).
826     if { $run_ld } {
827         set objfile "tmpdir/dump"
828         catch "exec rm -f $objfile" exec_output
829
830         # Add -L$srcdir/$subdir so that the linker command can use
831         # linker scripts in the source directory.
832         set cmd "$LD $LDFLAGS -L$srcdir/$subdir \
833                    $opts(ld) -o $objfile $objfiles"
834
835         send_log "$cmd\n"
836         set cmdret [catch "exec $cmd" comp_output]
837         set comp_output [prune_warnings $comp_output]
838
839         if { $cmdret != 0 } then {
840             # If the executed program writes to stderr and stderr is not
841             # redirected, exec *always* returns failure, regardless of the
842             # program exit code.  Thankfully, we can retrieve the true
843             # return status from a special variable.  Redirection would
844             # cause a Tcl-specific message to be appended, and we'd rather
845             # not deal with that if we can help it.
846             global errorCode
847             if { [lindex $errorCode 0] == "NONE" } {
848                 set cmdret 0
849             }
850         }
851
852         if { $cmdret == 0 && $run_objcopy } {
853             set infile $objfile
854             set objfile "tmpdir/dump1"
855             catch "exec rm -f $objfile" exec_output
856
857             # Note that we don't use OBJCOPYFLAGS here; any flags must be
858             # explicitly specified.
859             set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile"
860
861             send_log "$cmd\n"
862             set cmdret [catch "exec $cmd" comp_output]
863             append comp_output [prune_warnings $comp_output]
864
865             if { $cmdret != 0 } then {
866                 global errorCode
867                 if { [lindex $errorCode 0] == "NONE" } {
868                     set cmdret 0
869                 }
870             }
871         }
872
873         if { $cmdret != 0 || $comp_output != "" || $expmsg != "" } then {
874             set exitstat "succeeded"
875             if { $cmdret != 0 } { set exitstat "failed" }
876             verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
877             send_log "$comp_output\n"
878             verbose "$comp_output" 3
879
880             if { [regexp $expmsg $comp_output] \
881                     && (($cmdret == 0) == ($opts(warning) != "")) } {
882                 # We have the expected output from ld.
883                 if { $opts(error) != "" || $program == "" } {
884                     pass $testname
885                     return
886                 }
887             } else {
888                 verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
889                 fail $testname
890                 return
891             }
892         }
893     } else {
894         set objfile "tmpdir/dump0.o"
895     }
896
897     # We must not have expected failure if we get here.
898     if { $opts(error) != "" } {
899         fail $testname
900         return
901     }
902
903     set progopts1 $opts($program)
904     eval set progopts \$[string toupper $program]FLAGS
905     eval set binary \$[string toupper $program]
906
907     if { [which $binary] == 0 } {
908         untested $testname
909         return
910     }
911
912     if { $progopts1 == "" } { set $progopts1 "-r" }
913     verbose "running $binary $progopts $progopts1" 3
914
915     # Objcopy, unlike the other two, won't send its output to stdout,
916     # so we have to run it specially.
917     set cmd "$binary $progopts $progopts1 $objfile > $dumpfile"
918     if { $program == "objcopy" } {
919         set cmd "$binary $progopts $progopts1 $objfile $dumpfile"
920     }
921
922     # Ensure consistent sorting of symbols
923     if {[info exists env(LC_ALL)]} {
924         set old_lc_all $env(LC_ALL)
925     }
926     set env(LC_ALL) "C"
927     send_log "$cmd\n"
928     catch "exec $cmd" comp_output
929     if {[info exists old_lc_all]} {
930         set env(LC_ALL) $old_lc_all
931     } else {
932         unset env(LC_ALL)
933     }
934     set comp_output [prune_warnings $comp_output]
935     if ![string match "" $comp_output] then {
936         send_log "$comp_output\n"
937         fail $testname
938         return
939     }
940
941     verbose_eval {[file_contents $dumpfile]} 3
942     if { [regexp_diff $dumpfile "${file}.d"] } then {
943         fail $testname
944         verbose "output is [file_contents $dumpfile]" 2
945         return
946     }
947
948     pass $testname
949 }
950
951 proc slurp_options { file } {
952     if [catch { set f [open $file r] } x] {
953         #perror "couldn't open `$file': $x"
954         perror "$x"
955         return -1
956     }
957     set opt_array {}
958     # whitespace expression
959     set ws  {[  ]*}
960     set nws {[^         ]*}
961     # whitespace is ignored anywhere except within the options list;
962     # option names are alphabetic plus underscore only.
963     set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$"
964     while { [gets $f line] != -1 } {
965         set line [string trim $line]
966         # Whitespace here is space-tab.
967         if [regexp $pat $line xxx opt_name opt_val] {
968             # match!
969             lappend opt_array [list $opt_name $opt_val]
970         } else {
971             break
972         }
973     }
974     close $f
975     return $opt_array
976 }
977
978 # regexp_diff, copied from gas, based on simple_diff above.
979 #       compares two files line-by-line
980 #       file1 contains strings, file2 contains regexps and #-comments
981 #       blank lines are ignored in either file
982 #       returns non-zero if differences exist
983 #
984 proc regexp_diff { file_1 file_2 } {
985
986     set eof -1
987     set end_1 0
988     set end_2 0
989     set differences 0
990     set diff_pass 0
991
992     if [file exists $file_1] then {
993         set file_a [open $file_1 r]
994     } else {
995         warning "$file_1 doesn't exist"
996         return 1
997     }
998
999     if [file exists $file_2] then {
1000         set file_b [open $file_2 r]
1001     } else {
1002         fail "$file_2 doesn't exist"
1003         close $file_a
1004         return 1
1005     }
1006
1007     verbose " Regexp-diff'ing: $file_1 $file_2" 2
1008
1009     while { 1 } {
1010         set line_a ""
1011         set line_b ""
1012         while { [string length $line_a] == 0 } {
1013             if { [gets $file_a line_a] == $eof } {
1014                 set end_1 1
1015                 break
1016             }
1017         }
1018         while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
1019             if [ string match "#pass" $line_b ] {
1020                 set end_2 1
1021                 set diff_pass 1
1022                 break
1023             } elseif [ string match "#..." $line_b ] {
1024                 if { [gets $file_b line_b] == $eof } {
1025                     set end_2 1
1026                     set diff_pass 1
1027                     break
1028                 }
1029                 verbose "looking for \"^$line_b$\"" 3
1030                 while { ![regexp "^$line_b$" "$line_a"] } {
1031                     verbose "skipping    \"$line_a\"" 3
1032                     if { [gets $file_a line_a] == $eof } {
1033                         set end_1 1
1034                         break
1035                     }
1036                 }
1037                 break
1038             }
1039             if { [gets $file_b line_b] == $eof } {
1040                 set end_2 1
1041                 break
1042             }
1043         }
1044
1045         if { $diff_pass } {
1046             break
1047         } elseif { $end_1 && $end_2 } {
1048             break
1049         } elseif { $end_1 } {
1050             send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
1051             verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
1052             set differences 1
1053             break
1054         } elseif { $end_2 } {
1055             send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
1056             verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
1057             set differences 1
1058             break
1059         } else {
1060             verbose "regexp \"^$line_b$\"\nline   \"$line_a\"" 3
1061             if ![regexp "^$line_b$" "$line_a"] {
1062                 send_log "regexp_diff match failure\n"
1063                 send_log "regexp \"^$line_b$\"\nline   \"$line_a\"\n"
1064                 set differences 1
1065             }
1066         }
1067     }
1068
1069     if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
1070         send_log "$file_1 and $file_2 are different lengths\n"
1071         verbose "$file_1 and $file_2 are different lengths" 3
1072         set differences 1
1073     }
1074
1075     close $file_a
1076     close $file_b
1077
1078     return $differences
1079 }
1080
1081 proc file_contents { filename } {
1082     set file [open $filename r]
1083     set contents [read $file]
1084     close $file
1085     return $contents
1086 }
1087
1088 # List contains test-items with 3 items followed by 2 lists, one item and
1089 # one optional item:
1090 # 0:name 1:ld options 2:assembler options
1091 # 3:filenames of assembler files 4: action and options. 5: name of output file
1092 # 6:compiler flags (optional)
1093 #
1094 # Actions:
1095 # objdump: Apply objdump options on result.  Compare with regex (last arg).
1096 # nm: Apply nm options on result.  Compare with regex (last arg).
1097 # readelf: Apply readelf options on result.  Compare with regex (last arg).
1098 #
1099 proc run_ld_link_tests { ldtests } {
1100     global ld
1101     global as
1102     global nm
1103     global objdump
1104     global READELF
1105     global srcdir
1106     global subdir
1107     global env
1108     global CC
1109     global CFLAGS
1110
1111     foreach testitem $ldtests {
1112         set testname [lindex $testitem 0]
1113         set ld_options [lindex $testitem 1]
1114         set as_options [lindex $testitem 2]
1115         set src_files  [lindex $testitem 3]
1116         set actions [lindex $testitem 4]
1117         set binfile tmpdir/[lindex $testitem 5]
1118         set cflags [lindex $testitem 6]
1119         set objfiles {}
1120         set is_unresolved 0
1121         set failed 0
1122
1123 #       verbose -log "Testname is $testname"
1124 #       verbose -log "ld_options is $ld_options"
1125 #       verbose -log "as_options is $as_options"
1126 #       verbose -log "src_files is $src_files"
1127 #       verbose -log "actions is $actions"
1128 #       verbose -log "binfile is $binfile"
1129
1130         # Assemble each file in the test.
1131         foreach src_file $src_files {
1132             set objfile "tmpdir/[file rootname $src_file].o"
1133             lappend objfiles $objfile
1134
1135             if { [file extension $src_file] == ".c" } {
1136                 set as_file "tmpdir/[file rootname $src_file].s"
1137                 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
1138                     set is_unresolved 1
1139                     break
1140                 }
1141             } else {
1142                 set as_file "$srcdir/$subdir/$src_file"
1143             }
1144             if ![ld_assemble $as "$as_options $as_file" $objfile] {
1145                 set is_unresolved 1
1146                 break
1147             }
1148         }
1149
1150         # Catch assembler errors.
1151         if { $is_unresolved != 0 } {
1152             unresolved $testname
1153             continue
1154         }
1155
1156         if ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
1157             fail $testname
1158         } else {
1159             set failed 0
1160             foreach actionlist $actions {
1161                 set action [lindex $actionlist 0]
1162                 set progopts [lindex $actionlist 1]
1163
1164                 # There are actions where we run regexp_diff on the
1165                 # output, and there are other actions (presumably).
1166                 # Handling of the former look the same.
1167                 set dump_prog ""
1168                 switch -- $action {
1169                     objdump
1170                         { set dump_prog $objdump }
1171                     nm
1172                         { set dump_prog $nm }
1173                     readelf
1174                         { set dump_prog $READELF }
1175                     default
1176                         {
1177                             perror "Unrecognized action $action"
1178                             set is_unresolved 1
1179                             break
1180                         }
1181                     }
1182
1183                 if { $dump_prog != "" } {
1184                     set dumpfile [lindex $actionlist 2]
1185                     set binary $dump_prog
1186
1187                     # Ensure consistent sorting of symbols
1188                     if {[info exists env(LC_ALL)]} {
1189                         set old_lc_all $env(LC_ALL)
1190                     }
1191                     set env(LC_ALL) "C"
1192                     set cmd "$binary $progopts $binfile > dump.out"
1193                     send_log "$cmd\n"
1194                     catch "exec $cmd" comp_output
1195                     if {[info exists old_lc_all]} {
1196                         set env(LC_ALL) $old_lc_all
1197                     } else {
1198                         unset env(LC_ALL)
1199                     }
1200                     set comp_output [prune_warnings $comp_output]
1201
1202                     if ![string match "" $comp_output] then {
1203                         send_log "$comp_output\n"
1204                         set failed 1
1205                         break
1206                     }
1207
1208                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1209                         verbose "output is [file_contents "dump.out"]" 2
1210                         set failed 1
1211                         break
1212                     }
1213                 }
1214             }
1215
1216             if { $failed != 0 } {
1217                 fail $testname
1218             } else { if { $is_unresolved == 0 } {
1219                 pass $testname
1220             } }
1221         }
1222
1223         # Catch action errors.
1224         if { $is_unresolved != 0 } {
1225             unresolved $testname
1226             continue
1227         }
1228     }
1229 }
1230
1231
1232 proc verbose_eval { expr { level 1 } } {
1233     global verbose
1234     if $verbose>$level then { eval verbose "$expr" $level }
1235 }
1236
1237 # This definition is taken from an unreleased version of DejaGnu.  Once
1238 # that version gets released, and has been out in the world for a few
1239 # months at least, it may be safe to delete this copy.
1240 if ![string length [info proc prune_warnings]] {
1241     #
1242     # prune_warnings -- delete various system verbosities from TEXT
1243     #
1244     # An example is:
1245     # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
1246     #
1247     # Sites with particular verbose os's may wish to override this in site.exp.
1248     #
1249     proc prune_warnings { text } {
1250         # This is from sun4's.  Do it for all machines for now.
1251         # The "\\1" is to try to preserve a "\n" but only if necessary.
1252         regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
1253
1254         # It might be tempting to get carried away and delete blank lines, etc.
1255         # Just delete *exactly* what we're ask to, and that's it.
1256         return $text
1257     }
1258 }
1259
1260 # targets_to_xfail is a list of target triplets to be xfailed.
1261 # ldtests contains test-items with 3 items followed by 1 lists, 2 items
1262 # and 3 optional items:
1263 #   0:name
1264 #   1:ld options
1265 #   2:assembler options
1266 #   3:filenames of source files
1267 #   4:name of output file
1268 #   5:expected output
1269 #   6:compiler flags (optional)
1270 #   7:language (optional)
1271 #   8:linker warning (optional)
1272
1273 proc run_ld_link_exec_tests { targets_to_xfail ldtests } {
1274     global ld
1275     global as
1276     global srcdir
1277     global subdir
1278     global env
1279     global CC
1280     global CXX
1281     global CFLAGS
1282     global errcnt
1283     global exec_output
1284
1285     foreach testitem $ldtests {
1286         foreach target $targets_to_xfail {
1287             setup_xfail $target
1288         }
1289         set testname [lindex $testitem 0]
1290         set ld_options [lindex $testitem 1]
1291         set as_options [lindex $testitem 2]
1292         set src_files  [lindex $testitem 3]
1293         set binfile tmpdir/[lindex $testitem 4]
1294         set expfile [lindex $testitem 5]
1295         set cflags [lindex $testitem 6]
1296         set lang [lindex $testitem 7]
1297         set warning [lindex $testitem 8]
1298         set objfiles {}
1299         set failed 0
1300
1301 #       verbose -log "Testname is $testname"
1302 #       verbose -log "ld_options is $ld_options"
1303 #       verbose -log "as_options is $as_options"
1304 #       verbose -log "src_files is $src_files"
1305 #       verbose -log "actions is $actions"
1306 #       verbose -log "binfile is $binfile"
1307
1308         # Assemble each file in the test.
1309         foreach src_file $src_files {
1310             set objfile "tmpdir/[file rootname $src_file].o"
1311             lappend objfiles $objfile
1312
1313             # We ignore warnings since some compilers may generate
1314             # incorrect section attributes and the assembler will warn
1315             # them.
1316             ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1317
1318             # We have to use $CC to build PIE and shared library.
1319             if { [ string match "c" $lang ] } {
1320                 set link_proc ld_simple_link
1321                 set link_cmd $CC
1322             } elseif { [ string match "c++" $lang ] } {
1323                 set link_proc ld_simple_link
1324                 set link_cmd $CXX
1325             } elseif { [ string match "-shared" $ld_options ] \
1326                  || [ string match "-pie" $ld_options ] } {
1327                 set link_proc ld_simple_link
1328                 set link_cmd $CC
1329             } else {
1330                 set link_proc ld_link
1331                 set link_cmd $ld
1332             }
1333
1334             if ![$link_proc $link_cmd $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
1335                 set failed 1
1336             } else {
1337                 set failed 0
1338             }
1339
1340             # Check if exec_output is expected.
1341             if { $warning != "" } then {
1342                 verbose -log "returned with: <$exec_output>, expected: <$warning>"
1343                 if { [regexp $warning $exec_output] } then {
1344                     set failed 0
1345                 } else {
1346                     set failed 1
1347                 }
1348             }
1349
1350             if { $failed == 0 } {
1351                 send_log "Running: $binfile > $binfile.out\n"
1352                 verbose "Running: $binfile > $binfile.out"
1353                 catch "exec $binfile > $binfile.out" exec_output
1354             
1355                 if ![string match "" $exec_output] then {
1356                     send_log "$exec_output\n"
1357                     verbose "$exec_output" 1
1358                     set failed 1
1359                 } else {
1360                     send_log "diff $binfile.out $srcdir/$subdir/$expfile\n"
1361                     verbose "diff $binfile.out $srcdir/$subdir/$expfile"
1362                     catch "exec diff $binfile.out $srcdir/$subdir/$expfile" exec_output
1363                     set exec_output [prune_warnings $exec_output]
1364
1365                     if ![string match "" $exec_output] then {
1366                         send_log "$exec_output\n"
1367                         verbose "$exec_output" 1
1368                         set failed 1
1369                     }
1370                 }
1371             }
1372
1373             if { $failed != 0 } {
1374                 fail $testname
1375             } else {
1376                 set errcnt 0
1377                 pass $testname
1378             }
1379         }
1380     }
1381 }
1382
1383 # List contains test-items with 3 items followed by 2 lists, one item and
1384 # one optional item:
1385 #  0:name
1386 #  1:link options
1387 #  2:compile options
1388 #  3:filenames of source files
1389 #  4:action and options.
1390 #  5:name of output file
1391 #  6:language (optional)
1392 #
1393 # Actions:
1394 # objdump: Apply objdump options on result.  Compare with regex (last arg).
1395 # nm: Apply nm options on result.  Compare with regex (last arg).
1396 # readelf: Apply readelf options on result.  Compare with regex (last arg).
1397 #
1398 proc run_cc_link_tests { ldtests } {
1399     global nm
1400     global objdump
1401     global READELF
1402     global srcdir
1403     global subdir
1404     global env
1405     global CC
1406     global CXX
1407     global CFLAGS
1408
1409     foreach testitem $ldtests {
1410         set testname [lindex $testitem 0]
1411         set ldflags [lindex $testitem 1]
1412         set cflags [lindex $testitem 2]
1413         set src_files  [lindex $testitem 3]
1414         set actions [lindex $testitem 4]
1415         set binfile tmpdir/[lindex $testitem 5]
1416         set lang [lindex $testitem 6]
1417         set objfiles {}
1418         set is_unresolved 0
1419         set failed 0
1420
1421         # Compile each file in the test.
1422         foreach src_file $src_files {
1423             set objfile "tmpdir/[file rootname $src_file].o"
1424             lappend objfiles $objfile
1425
1426             # We ignore warnings since some compilers may generate
1427             # incorrect section attributes and the assembler will warn
1428             # them.
1429             ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1430         }
1431
1432         # Clear error and warning counts.
1433         reset_vars
1434
1435         if { [ string match "c++" $lang ] } {
1436             set cc_cmd $CXX
1437         } else {
1438             set cc_cmd $CC
1439         }
1440
1441         if ![ld_simple_link $cc_cmd $binfile "-L$srcdir/$subdir $ldflags $objfiles"] {
1442             fail $testname
1443         } else {
1444             set failed 0
1445             foreach actionlist $actions {
1446                 set action [lindex $actionlist 0]
1447                 set progopts [lindex $actionlist 1]
1448
1449                 # There are actions where we run regexp_diff on the
1450                 # output, and there are other actions (presumably).
1451                 # Handling of the former look the same.
1452                 set dump_prog ""
1453                 switch -- $action {
1454                     objdump
1455                         { set dump_prog $objdump }
1456                     nm
1457                         { set dump_prog $nm }
1458                     readelf
1459                         { set dump_prog $READELF }
1460                     default
1461                         {
1462                             perror "Unrecognized action $action"
1463                             set is_unresolved 1
1464                             break
1465                         }
1466                     }
1467
1468                 if { $dump_prog != "" } {
1469                     set dumpfile [lindex $actionlist 2]
1470                     set binary $dump_prog
1471
1472                     # Ensure consistent sorting of symbols
1473                     if {[info exists env(LC_ALL)]} {
1474                         set old_lc_all $env(LC_ALL)
1475                     }
1476                     set env(LC_ALL) "C"
1477                     set cmd "$binary $progopts $binfile > dump.out"
1478                     send_log "$cmd\n"
1479                     catch "exec $cmd" comp_output
1480                     if {[info exists old_lc_all]} {
1481                         set env(LC_ALL) $old_lc_all
1482                     } else {
1483                         unset env(LC_ALL)
1484                     }
1485                     set comp_output [prune_warnings $comp_output]
1486
1487                     if ![string match "" $comp_output] then {
1488                         send_log "$comp_output\n"
1489                         set failed 1
1490                         break
1491                     }
1492
1493                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1494                         verbose "output is [file_contents "dump.out"]" 2
1495                         set failed 1
1496                         break
1497                     }
1498                 }
1499             }
1500
1501             if { $failed != 0 } {
1502                 fail $testname
1503             } else { if { $is_unresolved == 0 } {
1504                 pass $testname
1505             } }
1506         }
1507
1508         # Catch action errors.
1509         if { $is_unresolved != 0 } {
1510             unresolved $testname
1511             continue
1512         }
1513     }
1514 }