1# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2# 2001, 2002, 2003 Free Software Foundation, Inc.
3#
4# This file is part of DejaGnu.
5#
6# DejaGnu is free software; you can redistribute it and/or modify it
7# under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# DejaGnu is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14# General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with DejaGnu; if not, write to the Free Software Foundation,
18# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20# This file was written by Rob Savoye. (rob@welcomehome.org)
21# and extensively modified by Bob Manson. (manson@cygnus.com)
22
23# a hairy pattern to recognize text
24set text "\[- A-Za-z0-9\.\;\"\_\:\'\`\(\)\!\#\=\+\?\&\*]"
25
26#
27# this is a collection of support procs for the target data
28# structures. We use a named array, since Tcl has no real data
29# structures. Here's the special index words for the array:
30#       Required fields are:
31#	    name    - the name of the target. (mostly for error messages) This
32#		      should also be the string used for this target's array.
33#                     It should also be the same as the linker script so we
34#		      can find them dynamically.
35#       Optional fields are:
36#	    ldflags - the flags required to produce a fully linked executable.
37#	    config  - the target canonical for this target. This is a regexp
38#		      as passed to istarget or isnative.
39#	    cflags  - the flags required to produce an object file from a
40#		      source file.
41#	    connect - the connectmode for this target. This is for both IP and
42#		      serial connections.
43#	    hostname  - the hostname of the target. This is for TCP/IP based
44#		      connections, and is also used for versions of tip that
45#		      use /etc/remote.
46#	    serial  - the serial port. This is typically /dev/tty? or com?:.
47#	    baud    - the baud rate for a serial port connection.
48#	    netport - the IP port.
49#	    x10     - parameters for the x10 controller (used to reboot)
50#	    fileid  - the fileid or spawn id of of the connection.
51#	    prompt  - a regexp for matching the prompt.
52#	    ioport  - the port for I/O on dual port systems.
53#
54# there are three main arrays, indexed in with "target", "build", and "host".
55# all other targets are indexed with a name usually based on the linker script
56# like "idp", or "ex93x.ld".
57#
58
59#
60# Set the target connection.
61#
62proc push_target { name } {
63    global target_abbrev
64
65    pop_config  target
66    push_config target $name
67}
68
69#
70# Set the host connnection.
71#
72proc push_host { name } {
73    pop_config host
74    push_config host $name
75}
76
77#
78# Set the build connnection.
79#
80proc push_build { name } {
81    pop_config build
82    push_config build $name
83}
84
85#
86# Set the config for the current host or target connection.
87#
88proc push_config { type name } {
89    global target_info
90
91    verbose "pushing config for $type, name is $name"
92    if [info exists target_info($type,name)] {
93	if { $target_info($type,name) == $name } {
94	    error "pushing config for $type, '$name' twice"
95	}
96    }
97    set target_info($type,name) $name
98}
99
100#
101# Set the current connection for target or host.
102#
103proc pop_config { type  } {
104    global target_info
105
106    if [info exists target_info(${type},name)] {
107	unset target_info(${type},name)
108    }
109}
110
111#
112# Unset the target connection.
113#
114proc pop_target { } {
115    pop_config target
116}
117
118#
119# Unset the host connection.
120#
121proc pop_host { } {
122    pop_config host
123}
124
125#
126# Remove extraneous warnings we don't care about
127#
128proc prune_warnings { text } {
129    global host_triplet
130
131    # remove the \r part of "\r\n" so we don't break all the patterns
132    # we want to match.
133    regsub -all -- "\r" $text "" text
134
135    # This is from sun4's.  Do it for all machines for now.
136    # The "\\1" is to try to preserve a "\n" but only if necessary.
137    if [ishost "sparc-*-sunos*"] {
138	regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
139    }
140
141    # See Brendan for the raison d'etre of this one.
142    if [ishost "alpha*-*-*"] {
143        regsub -all "(^|\n)(/usr/(ucb|bin)/ld.*without exceptions was\[^\n\]+\n?)" $text "\\1" text
144    }
145    if [ishost "hppa*-*-hpux*"] {
146       # Ignore the compiler's warnings about PA incompatibility.
147       regsub -all "(^|\n)\[^\n\]*PA 2.0 object file \[^\n\]* was detected. The linked output may not run on a PA 1.x system." $text "" text
148
149       regsub -all "(^|\n)\[^\n\]*PA 2.0 object file \[^\n\]* was detected. The linked output may not run on a PA 1.x system." $text "" text
150
151       # And the linker's +vcompatwarnings verbage.
152       regsub -all "(^|\n)\[^\n\]*Linker features were used that may not be supported\[^\n\]*.\[^\n\]*." $text "" text
153
154       # Ignore these warnings, which the HP aCC compiler seems to
155       # generate on HP-UX 10.30 and 11.0.  (Something is probably
156       # wrong with some system headers, but still...)
157       #
158       # This particular warning always is given with a line of warning
159       # text, followed by a source line, followed by a line with "^^^"
160       # underlining an offending symbol name.  Here we slurp up the
161       # warning text and the next two lines, assuming that they are
162       # the source line and underline chars.
163       #
164       regsub -all "Warning .*The linkage directive is ignored for an object or function declared static..\[^\n\]*.\[^\n\]*." $text "" text
165
166       # Ignore these warnings, which I often see from the ANSI C
167       # compiler installed on HP-UX 11.0 machines.  (Something is
168       # probably wrong with an installation, or perhaps NLS isn't
169       # quite healthy yet on 11.0.  In either case, it's easier to
170       # "fix" this nit here, than it is to track down & fix the
171       # root cause.)
172       #
173       # This particular warning always is given with a line of warning
174       # text, followed by line that says "Using internal messages".
175       #
176       regsub -all "Warning: Unable to open pxdb message catalog.*" $text "" text
177       regsub -all ".* Using internal messages.*" $text "" text
178
179       # Another form of the "unable to find message catalog" warning.
180       #
181       regsub -all "cpp: warning .*Possibly incorrect message catalog." $text "" text
182
183       # Another odd warning on 11.0.
184       #
185       regsub -all "aCC .assigner.: Warning .*Could not find library for -l.*" $text "" text
186
187       # Oh heck, just keep adding 'em here...
188       #
189       regsub -all "aCC .assigner.: Warning .*Could not satisfy instantiation request for \[^\n\]* contained in\[^\n\]*\n\t/lib/pa20_64/lib\[a-zA-Z0-9\]*.sl" $text "" text
190
191      # Remove the lines that are output by the HP F77 compiler to
192      # indicate the functions that are being compiled.
193      upvar compiler_type compiler_type
194      if { [info exists compiler_type] && $compiler_type == "f77" } {
195	  regsub -all "\[ \ta-zA-Z_0-9\./\]*:\[\r\n\]+" $text "" text
196      }
197
198      # Ignore the warnings about unknown options
199      regsub -all ".*warning \[0-9\]+: Unknown option.*ignored.*" $text "" text
200
201      }
202
203    # Ignore these.
204    regsub -all "(^|\n)\[^\n\]*linker input file unused since linking not done" $text "" text
205    regsub -all "(^|\n)\[^\n\]*file path prefix \[^\n\]* never used" $text "" text
206
207    # This is from sun4's.  Do it for all machines for now.
208    # The "\\1" is to try to preserve a "\n" but only if necessary.
209    regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
210
211    # This happens when compiling on Alpha OSF/1 with cc -g -O.
212    regsub -all "(^|\n)(\n*uopt: Warning: file not optimized; use -g3 if both optimization and debug wanted\n?)+" $text "\\1" text
213
214    # This happens when compiling on Alpha OSF using gas.
215    regsub -all "(^|\n)(/usr/.*/ld:\nWarning: Linking some objects which contain exception information sections\n\tand some which do not. This may cause fatal runtime exception handling\n\tproblems\[^\n\]*\n?)+" $text "\\1" text
216
217    # This happens on SunOS with cc -g -O.
218    regsub -all "(^|\n)(cc: Warning: -O conflicts with -g. -O turned off.\n?)+" $text "\\1" text
219
220    # This happens when assembling code with the native HP assembler
221    regsub -all "(^|\n)(as:\[^\n\]*err#13.\n  .warning.\[^\n\]*\n?)+" $text "\\1" text
222
223    # When using the HP assembler, -g isn't supported.
224    regsub -all "(^|\n)(cc1: warning: -g is only supported when using GAS on this processor\[^\n\]*\ncc1: warning:\[^\n\]*\n?)+" $text "\\1" text
225    regsub -all "(^|\n)(cc1plus: warning: -g is only supported when using GAS on this processor\[^\n\]*\ncc1plus: warning:\[^\n\]*\n?)+" $text "\\1" text
226
227    # This happens when testing across NFS.
228    regsub -all "(^|\n)((NFS|nfs) server \[^\n\]* not responding\[^\n\]*\n?)+" $text "\\1" text
229    regsub -all "(^|\n)((NFS|nfs) server \[^\n\]* (ok|is alive again)\[^\n\]*\n?)+" $text "\\1" text
230
231    # This happens when testing across NFS on osf4.
232    regsub -all "(^|\n)(NFS3 server \[^\n\]* not responding still trying\[^\n\]*\n?)+" $text "\\1" text
233    regsub -all "(^|\n)(NFS3 server \[^\n\]* ok\[^\n\]*\n?)+" $text "\\1" text
234
235    # When using the IRIX 6 o32 assembler, -g isn't supported
236    regsub -all "(^|\n)(cc1: warning: `-g' not supported by this configuration of GCC\[^\n\]*\n?)+" $text "\\1" text
237    regsub -all "(^|\n)(cc1plus: warning: `-g' not supported by this configuration of GCC\[^\n\]*\n?)+" $text "\\1" text
238
239    regsub -all "(^|\n)(cc1: warning: -mabi=32 does not support -g\[^\n\]*\n?)+" $text "\\1" text
240    regsub -all "(^|\n)(cc1plus: warning: -mabi=32 does not support -g\[^\n\]*\n?)+" $text "\\1" text
241
242    # This happens with the o32 assembler on IRIX 6.
243    regsub -all "(^|\n)(as: Warning: -O3 is not supported for assembly compiles for ucode compilers; changing to -O2.\n?)+" $text "\\1" text
244
245    # This happens when using g++ on a DWARF system.
246    regsub -all "(^|\n)(cc1plus: warning: -g option not supported for C\\+\\+ on systems using the DWARF debugging format\n?)+" $text "\\1" text
247
248    # This is from sun4's.  Do it for all machines for now.
249    # The "\\1" is to try to preserve a "\n" but only if necessary.
250    regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
251
252    # See Brendan for the raison d'etre of this one.
253    if [string match "alpha*-*-*" $host_triplet] {
254        regsub -all "(^|\n)(/usr/(ucb|bin)/ld.*without exceptions was\[^\n\]+\n?)" $text "\\1" text
255    }
256
257    # Don't pay attention to the AIX4 linker warnings.
258    regsub -all "(^|\n)(ld:.*WARNING: Duplicate.*ld:.*Use the -bload\[^\n\]*\n?)" $text "\\1" text
259
260    # Or the IRIX 6 ones.
261    regsub -all "(^|\n)(ld(|32|64): WARNING \[^\n\]*\n?)+" $text "\\1" text
262    regsub -all "(^|\n)(ld(|32|64): Giving up.*Use -wall\[^\n\]*\n?)+" $text "\\1" text
263
264    # Or the NetBSD ones.
265     regsub -all "(^|\n)(\[^\n\]*: In function\[^\n\]*\n\[^\n\]\[^\n\]*warning:this program uses \[^\n\]*)" $text "\\1" text
266     regsub -all "(^|\n)(\[^\n\]*: In function\[^\n\]*\n\[^\n\]\[^\n\]*warning:reference to compatibility \[^\n\]*)" $text "\\1" text
267     regsub -all "(^|\n)(\[^\n\]*:\[0-9\]+: warning: \[^\n\]* possibly used unsafely, use \[^\n\]*\n?)" $text "\\1" text
268    regsub -all "(^|\n)(\[^\n\]*: warning: reference to compatibility glob\[^\n\]*\n?)" $text "\\1" text
269
270    # GNU ld warns about functions marked as dangerous in GNU libc.
271    regsub -all "(^|\n)\[^\n\]*: In function\[^\n\]*\n\[^\n\]\[^\n\]*function is dangerous\[^\n\]*" $text "" text
272
273     # GNU ld warns about functions marked as dangerous in GNU libc.
274     regsub -all "(^|\n)\[^\n\]*: In function\[^\n\]*\n\[^\n\]\[^\n\]*the use of \[^\n\]* is dangerous, better use \[^\n\]*" $text "" text
275
276     # Libgloss libnosys defines functions that warn when linked in
277    regsub -all "(^|\n)\[^\n\]*: In function\[^\n\]*\n\[^\n\]\[^\n\]*is not implemented and will always fail\[^\n\]*" $text "" text
278
279    # Cygwin cc1 warns about -fpic and -fPIC
280    regsub -all ".*: warning: -f(pic|PIC) ignored for target .*" $text "" text
281
282    # It might be tempting to get carried away and delete blank lines, etc.
283    # Just delete *exactly* what we're ask to, and that's it.
284    return $text
285}
286
287#
288# Invoke the compiler. This gets interesting cause the compiler may
289# not be on the same machine we're running DejaGnu on.
290#
291
292proc target_compile {source destfile type options} {
293    set target [target_info name]
294    if { [info proc ${target}_compile] != "" } {
295        return [${target}_compile $source $destfile $type $options]
296    } else {
297        return [default_target_compile $source $destfile $type $options]
298    }
299}
300
301proc default_target_compile {source destfile type options} {
302    global target_triplet
303    global tool_root_dir
304    global CFLAGS_FOR_TARGET
305    global compiler_flags
306
307    if { $destfile == "" && $type != "preprocess" && $type != "none" } {
308	error "Must supply an output filename for the compile to default_target_compile"
309    }
310
311    set add_flags ""
312    set libs ""
313    set compiler_type "c"
314    set compiler ""
315    set ldflags ""
316    set dest [target_info name]
317
318    if [info exists CFLAGS_FOR_TARGET] {
319	append add_flags " $CFLAGS_FOR_TARGET"
320    }
321
322    if [info exists target_info(host,name)] {
323	set host [host_info name]
324    } else {
325	set host "unix"
326    }
327
328    foreach i $options {
329	if { $i == "c++" } {
330	    set compiler_type "c++"
331	    if [board_info $dest exists cxxflags] {
332		append add_flags " [target_info cxxflags]"
333	    }
334	    append add_flags " [g++_include_flags]"
335	    if [board_info $dest exists c++compiler] {
336		set compiler [target_info c++compiler]
337	    } else {
338		set compiler [find_g++]
339	    }
340	}
341
342	if { $i == "f77" } {
343	    set compiler_type "f77"
344	    if [board_info $dest exists f77flags] {
345		append add_flags " [target_info f77flags]"
346	    }
347#	    append add_flags " [f77_include_flags]"
348	    if [board_info $dest exists f77compiler] {
349		set compiler [target_info f77compiler]
350	    } else {
351		set compiler [find_g77]
352	    }
353	}
354
355	if [regexp "^dest=" $i] {
356	    regsub "^dest=" $i "" tmp
357	    if [board_info $tmp exists name] {
358		set dest [board_info $tmp name]
359	    } else {
360		set dest $tmp
361	    }
362	}
363	if [regexp "^compiler=" $i] {
364	    regsub "^compiler=" $i "" tmp
365	    set compiler $tmp
366	}
367	if [regexp "^additional_flags=" $i] {
368	    regsub "^additional_flags=" $i "" tmp
369	    append add_flags " $tmp"
370	}
371	if [regexp "^ldflags=" $i] {
372	    regsub "^ldflags=" $i "" tmp
373	    append ldflags " $tmp"
374	}
375	if [regexp "^libs=" $i] {
376	    regsub "^libs=" $i "" tmp
377	    append libs " $tmp"
378	}
379	if [regexp "^incdir=" $i] {
380	    regsub "^incdir=" $i "-I" tmp
381	    append add_flags " $tmp"
382	}
383	if [regexp "^libdir=" $i] {
384	    regsub "^libdir=" $i "-L" tmp
385	    append add_flags " $tmp"
386	}
387	if [regexp "^ldscript=" $i] {
388	    regsub "^ldscript=" $i "" ldscript
389	}
390 	if [regexp "^redirect=" $i] {
391 	    regsub "^redirect=" $i "" redirect
392 	}
393 	if [regexp "^optimize=" $i] {
394 	    regsub "^optimize=" $i "" optimize
395 	}
396 	if [regexp "^timeout=" $i] {
397 	    regsub "^timeout=" $i "" timeout
398 	}
399    }
400
401    if [board_info $host exists cflags_for_target] {
402	append add_flags " [board_info $host cflags_for_target]"
403    }
404
405    global CC_FOR_TARGET
406    global CXX_FOR_TARGET
407    global F77_FOR_TARGET
408
409    if [info exists CC_FOR_TARGET] {
410	if { $compiler == "" } {
411	    set compiler $CC_FOR_TARGET
412	}
413    }
414
415    if [info exists CXX_FOR_TARGET] {
416	if { $compiler_type == "c++" } {
417	    set compiler $CXX_FOR_TARGET
418	}
419    }
420
421    if [info exists F77_FOR_TARGET] {
422	if { $compiler_type == "f77" } {
423	    set compiler $F77_FOR_TARGET
424	}
425    }
426
427    if { $compiler == "" } {
428	set compiler [board_info $dest compiler]
429	if { $compiler == "" } {
430	    return "default_target_compile: No compiler to compile with"
431	}
432    }
433
434    if ![is_remote host] {
435	if { [which $compiler] == 0 } {
436	    return "default_target_compile: Can't find $compiler."
437	}
438    }
439
440    if {$type == "object"} {
441	append add_flags " -c"
442    }
443
444    if { $type == "preprocess" } {
445	append add_flags " -E"
446    }
447
448    if { $type == "assembly" } {
449	append add_flags " -S"
450    }
451
452    if [board_info $dest exists cflags] {
453	append add_flags " [board_info $dest cflags]"
454    }
455
456    if { $type == "executable" } {
457	# This must be added here.
458	# if [board_info $dest exists ldscript] {
459	#     append add_flags " [board_info $dest ldscript]"
460	# }
461
462	if [board_info $dest exists ldflags] {
463	    append add_flags " [board_info $dest ldflags]"
464	}
465	if { $compiler_type == "c++" } {
466	    append add_flags " [g++_link_flags]"
467	}
468	if [isnative] {
469	    # This is a lose.
470	    catch "glob -nocomplain $tool_root_dir/libstdc++/libstdc++.so* $tool_root_dir/libstdc++/libstdc++.sl" tmp
471	    if { ${tmp} != "" } {
472		if [regexp ".*solaris2.*" $target_triplet] {
473		    # Solaris 2
474		    append add_flags " -R$tool_root_dir/libstdc++"
475		} elseif [regexp ".*(osf|irix5|linux).*" $target_triplet] {
476		    # OSF/1 or Irix5
477		    append add_flags " -Wl,-rpath,$tool_root_dir/libstdc++"
478		} elseif [regexp ".*hppa.*" $target_triplet] {
479		    # HP/UX
480		    append add_flags " -Wl,-a,shared_archive"
481		}
482	    }
483	}
484    }
485
486    if ![info exists ldscript] {
487	set ldscript [board_info $dest ldscript]
488    }
489
490    foreach i $options {
491	if { $i == "debug" } {
492	    if [board_info $dest exists debug_flags] {
493		append add_flags " [board_info $dest debug_flags]"
494	    } else {
495		append add_flags " -g"
496	    }
497	}
498    }
499
500    if [info exists optimize] {
501	append add_flags " $optimize"
502    }
503
504    if { $type == "executable" } {
505	append add_flags " $ldflags"
506	foreach x $libs {
507	    if [file exists $x] {
508		append source " $x"
509	    } else {
510		append add_flags " $x"
511	    }
512	}
513
514	if [board_info $dest exists libs] {
515	    append add_flags " [board_info $dest libs]"
516	}
517
518	# This probably isn't such a good idea, but it avoids nasty
519	# hackiness in the testsuites.
520	# The math library must be linked in before the C library.  The C
521	# library is linked in by the linker script, so this must be before
522	# the linker script.
523	if [board_info $dest exists mathlib] {
524	    append add_flags " [board_info $dest mathlib]"
525	} else {
526	    append add_flags " -lm"
527	}
528
529	# This must be added here.
530	append add_flags " $ldscript"
531
532	if [board_info $dest exists remote_link] {
533	    # Relink option.
534	    append add_flags " -Wl,-r"
535	}
536	if [board_info $dest exists output_format] {
537	    append add_flags " -Wl,-oformat,[board_info $dest output_format]"
538	}
539    }
540
541    if [board_info $dest exists multilib_flags] {
542	append add_flags " [board_info $dest multilib_flags]"
543    }
544
545    verbose "doing compile"
546
547    set sources ""
548    if [is_remote host] {
549	foreach x $source {
550	    set file [remote_download host $x]
551	    if { $file == "" } {
552		warning "Unable to download $x to host."
553		return "Unable to download $x to host."
554	    } else {
555		append sources " $file"
556	    }
557	}
558    } else {
559	set sources $source
560    }
561
562    if [is_remote host] {
563	append add_flags " -o a.out"
564	remote_file host delete a.out
565    } else {
566	if { $destfile != "" } {
567	    append add_flags " -o $destfile"
568	}
569    }
570
571    # This is obscure: we put SOURCES at the end when building an
572    # object, because otherwise, in some situations, libtool will
573    # become confused about the name of the actual source file.
574    if {$type == "object"} {
575        set opts "$add_flags $sources"
576    } else {
577        set opts "$sources $add_flags"
578    }
579
580    if [is_remote host] {
581	if [host_info exists use_at] {
582	    set fid [open "atfile" "w"]
583	    puts $fid "$opts"
584	    close $fid
585	    set opts "@[remote_download host atfile]"
586	    remote_file build delete atfile
587	}
588    }
589
590    verbose "Invoking the compiler as $compiler $opts" 2
591
592    if [info exists redirect] {
593	verbose "Redirecting output to $redirect" 2
594	set status [remote_exec host "$compiler $opts" "" "" $redirect]
595    } else {
596	if [info exists timeout] {
597	    verbose "Setting timeout to $timeout" 2
598	    set status [remote_exec host "$compiler $opts" "" "" "" $timeout]
599	} else {
600	    set status [remote_exec host "$compiler $opts"]
601	}
602    }
603
604    set compiler_flags $opts
605    if [is_remote host] {
606	remote_upload host a.out $destfile
607	remote_file host delete a.out
608    }
609    set comp_output [prune_warnings [lindex $status 1]]
610    regsub "^\[\r\n\]+" $comp_output "" comp_output
611    if { [lindex $status 0] != 0 } {
612	verbose -log "compiler exited with status [lindex $status 0]"
613    }
614    if { [lindex $status 1] != "" } {
615	verbose -log "output is:\n[lindex $status 1]" 2
616    }
617    if { [lindex $status 0] != 0 && "${comp_output}" == "" } {
618	set comp_output "exit status is [lindex $status 0]"
619    }
620    return ${comp_output}
621}
622
623proc reboot_target { } {
624    set result [remote_reboot target]
625    puts "REBOOT_TARGET: \"$result\""
626    return ${result}
627}
628
629#
630# Invoke this if you really want as to be called directly, rather than
631# calling the compiler. FLAGS are any additional flags to pass to the
632# assembler.
633#
634proc target_assemble { source destfile flags } {
635    return [default_target_assemble $source $destfile $flags]
636}
637
638proc default_target_assemble { source destfile flags } {
639    global AS_FOR_TARGET
640    global ASFLAGS_FOR_TARGET
641
642    if [info exists AS_FOR_TARGET] {
643	set AS "$AS_FOR_TARGET"
644    } else {
645	if ![board_info target exists assembler] {
646	    set AS [find_gas]
647	} else {
648	    set AS [board_info target assembler]
649	}
650    }
651
652    if [info exists ASFLAGS_FOR_TARGET] {
653	append flags " $ASFLAGS_FOR_TARGET"
654    }
655
656    if [is_remote host] {
657	set source [remote_download host $source]
658	set dest "a.out"
659    } else {
660	set dest $destfile
661    }
662    set status [remote_exec host "$AS $source $flags -o $dest"]
663    if [is_remote host] {
664	remote_upload host $dest $destfile
665    }
666
667    set comp_output [prune_warnings [lindex $status 1]]
668    if { [lindex $status 0] != 0 } {
669	verbose -log "assembler exited with status [lindex $status 0]"
670    }
671    if { [lindex $status 1] != "" } {
672	verbose -log "assembler output is:\n[lindex $status 1]" 2
673    }
674    return ${comp_output}
675}
676
677#
678# Invoke this if you really want ld to be called directly, rather than
679# calling the compiler. FLAGS are any additional flags to pass to the
680# linker.
681#
682proc target_link { objects destfile flags } {
683    return [default_link target "$objects" "$destfile" $flags]
684}
685
686proc default_link { board objects destfile flags } {
687    global LD_FOR_TARGET
688    global LDFLAGS_FOR_TARGET
689
690    # return -L's in ldflags
691    proc only--Ls { ldflags } {
692	set result ""
693	set ldflags [split $ldflags]
694	set len [llength $ldflags]
695	for { set i 0 } { $i < $len } { incr i } {
696	    # ??? We ignore the situation where a -L is actually the argument
697	    # to an option.
698	    set arg [lindex $ldflags $i]
699	    regsub "^-Wl," $arg "" arg
700	    if [regexp "^-L" $arg] {
701		# Is the directory in the next arg, or part of this one?
702		if { "$arg" == "-L" } {
703		    if { $i + 1 < $len } {
704			append result " -L [lindex $ldflags $i+1]"
705			incr i
706		    }
707		} else {
708		    append result " $arg"
709		}
710	    }
711	}
712	return $result
713    }
714
715    if [info exists LD_FOR_TARGET] {
716	set LD "$LD_FOR_TARGET"
717    } else {
718	if ![board_info target exists linker] {
719	    set LD [find_ld]
720	} else {
721	    set LD [board_info target linker]
722	}
723    }
724
725    if [info exists LDFLAGS_FOR_TARGET] {
726	append flags " $LDFLAGS_FOR_TARGET"
727    }
728
729    # `ldflags' consists of arguments to gcc (that are then
730    # passed to ld), not arguments to ld directly.
731    # We need the -L's.
732    if [board_info $board exists ldflags] {
733	set ldflags [board_info $board ldflags]
734	set ldflags [only--Ls $ldflags]
735	append flags " $ldflags"
736    }
737
738    if [board_info $board exists ldscript] {
739	# strip leading -Wl, if present
740	set ldscript [board_info $board ldscript]
741	regsub "^-Wl," $ldscript "" ldscript
742	append flags " $ldscript"
743    }
744
745    if [is_remote host] {
746	foreach x $objects {
747	    set nobjects "$nobjects [remote_download host $x]"
748	}
749	set objects "$nobjects"
750	set dest "a.out"
751    } else {
752	set dest $destfile
753    }
754    set status [remote_exec host "$LD $objects $flags -o $dest"]
755    if [is_remote host] {
756	remote_upload host $dest $destfile
757    }
758
759    set comp_output [prune_warnings [lindex $status 1]]
760    if { [lindex $status 0] != 0 } {
761	verbose -log "linker exited with status [lindex $status 0]"
762    }
763    if { [lindex $status 1] != "" } {
764	verbose -log "linker output is:\n[lindex $status 1]" 2
765    }
766    return ${comp_output}
767}
768