Rev 5 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of The TenDRA Project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*/
/*
Crown Copyright (c) 1997
This TenDRA(r) Computer Program is subject to Copyright
owned by the United Kingdom Secretary of State for Defence
acting through the Defence Evaluation and Research Agency
(DERA). It is made available to Recipients with a
royalty-free licence for its use, reproduction, transfer
to other parties and amendment for any purpose not excluding
product development provided that any such use et cetera
shall be deemed to be acceptance of the following conditions:-
(1) Its Recipients shall ensure that this Notice is
reproduced upon any copies or amended versions of it;
(2) Any amended version of it shall be clearly marked to
show both the nature of and the organisation responsible
for the relevant amendment or amendments;
(3) Its onward transfer from a recipient to another
party shall be deemed to be that party's acceptance of
these conditions;
(4) DERA gives no warranty or assurance as to its
quality or suitability for any purpose and DERA accepts
no liability whatsoever in relation to any use to which
it may be put.
*/
#include "config.h"
#include "filename.h"
#include "list.h"
#include "archive.h"
#include "execute.h"
#include "flags.h"
#include "options.h"
#include "stages.h"
#include "startup.h"
#include "suffix.h"
#include "utility.h"
/*
* BINARY OBJECT FILE TYPE
*
* The type of binary object file to be produced, for example, by the assembler
* varies according to whether it will later be included in a spec archive.
* This value determines this file type.
*/
int binary_obj_type = BINARY_OBJ;
/*
* COPY A FILE
*
* This routine moves the file from to the file to. If to is null then from is
* copied to the standard output. All the routines in this module return their
* set of output files. This may be null if an error has occurred.
*/
static filename *
do_move(filename *from, filename *to)
{
if (from == null) {
return (from);
}
if (to) {
if (streq(from->name, to->name)) {
return (to);
}
cmd_list(exec_move);
cmd_filename(from);
cmd_filename(to);
} else {
cmd_list(exec_cat);
cmd_filename(from);
}
return (execute(from, to));
}
/*
* PRESERVE A FILE
*
* This routine preserves the file p by moving it, if necessary, to the work
* directory. It returns the new location of p.
*/
filename *
do_keep(filename *p)
{
if (p->storage == TEMP_FILE) {
filename *q = make_filename(p, p->type, PRESERVED_FILE);
cmd_list(exec_move);
cmd_filename(p);
cmd_filename(q);
IGNORE execute(no_filename, no_filename);
return (q);
}
return (p);
}
/*
* TEMPORARY FILE NAME
*
* This is set by uniq_filename to be either its output file or a temporary
* file if the output corresponds to an input file.
*/
static filename *uniq_tempfile = null;
/*
* MAKE A UNIQUE FILE NAME
*
* This routine creates a filename with name nm, type t and storage s. If this
* coincides with one of the files in input then a temporary file is stored in
* uniq_tempfile, otherwise it holds the output file.
*/
static filename *
uniq_filename(char *nm, int t, int s, filename *input)
{
filename *p = find_filename(nm, t);
filename *q = make_filename(p, t, s);
uniq_tempfile = q;
for (p = input; p != null; p = p->next) {
if (streq(p->name, q->name)) {
if (p->storage == TEMP_FILE) {
uniq_tempfile = make_filename(no_filename, t,
TEMP_FILE);
} else {
char *m;
static char plus[] = { EXTRA_KEY, 0 };
q->name = string_concat(q->name, plus);
switch (t)EXHAUSTIVE {
case INDEP_TDF:
m = "merged TDF capsule";
break;
case TDF_ARCHIVE:
m = "archive file";
break;
case C_SPEC:
m = "linked C spec file";
break;
case CPP_SPEC:
m = "linked C++ spec file";
break;
case EXECUTABLE:
m = "executable";
break;
}
error(WARNING,
"Renaming %s '%s' to '%s' to avoid clash with input",
m, p->name, q->name);
}
return (q);
}
}
return (q);
}
/*
* PRINT PRODUCER/PREPROCESSOR OPTIONS
*
* The C/C++ to TDF producers and the TDF C/C++ preprocessor accept the same
* command-line options; the parameter 'pp' is used to determine which startup
* files are appropriate.
*/
static void
producer_options(int pp)
{
boolean is_c = (pp == PRODUCE_ID || pp == PREPROC_ID);
if (!flag_nepc && std_prod_portfile) {
cmd_string("-n");
cmd_string(std_prod_portfile->item);
}
if (flag_diag) {
if (flag_diag == 1) {
cmd_string("-g1");
} else {
cmd_string("-g2");
}
}
if (flag_incl) {
cmd_string("-H");
}
if (flag_startup) {
if (is_c) {
cmd_list(std_prod_startup);
cmd_list(usr_prod_startup);
} else {
cmd_list(std_cpp_prod_startup);
cmd_list(usr_cpp_prod_startup);
}
if (startup_opt) {
cmd_string(startup_opt);
}
cmd_list(usr_prod_foptions);
cmd_list(usr_prod_eoptions);
if (endup_opt) {
cmd_string(endup_opt);
}
}
cmd_list(usr_prod_incldirs);
if (!is_c) {
cmd_list(std_cpp_prod_incldirs);
}
cmd_list(std_prod_incldirs);
if (flag_startup) {
if (is_c) {
cmd_list(std_prod_startdirs);
} else {
cmd_list(std_cpp_prod_startdirs);
}
}
if (checker) {
cmd_string("-c");
}
if (make_pretty) {
cmd_string("-t");
}
return;
}
/*
* APPLY THE C PRODUCER
*
* This routine applies the C to TDF producer to input and returns the result.
*/
filename *
do_produce(filename *input)
{
boolean spec_produced;
filename *output, *spec;
if (input == null) {
return (input);
}
output = make_filename(input, INDEP_TDF, where(INDEP_TDF));
cmd_list(exec_produce);
if (allow_specs == 1) {
spec = make_filename(input, C_SPEC, where(C_SPEC));
if (dump_opts) {
cmd_string(string_concat(dump_opts, spec->name));
} else {
cmd_string("-s");
cmd_string(spec->name);
}
}
cmd_list(opt_produce);
producer_options(PRODUCE_ID);
cmd_filename(input);
cmd_filename(output);
/* Execute the command */
enable_delayed_signal();
output = execute(input, output);
spec_produced = (allow_specs == 1) && (last_return != 2) &&
(checker || output != null);
disable_delayed_signal();
process_delayed_signal();
if (spec_produced) {
SET(spec);
output = add_filename(output, spec);
}
if (allow_specs == 2) {
spec = make_filename(input, C_SPEC, where(C_SPEC));
cmd_list(exec_touch);
cmd_filename(spec);
cmd_string("-k");
spec = execute(no_filename, spec);
output = add_filename(output, spec);
}
return (output);
}
/*
* APPLY THE C PREPROCESSOR
*
* This routine applies the TDF C preprocessor to input and returns the result.
* If files of type PREPROC_C are not being preserved then the output is sent
* to the standard output.
*/
filename *
do_preproc(filename *input)
{
filename *output;
if (input == null) {
return (input);
}
if (checker && !use_system_cc) {
return (input);
}
if (keeps[PREPROC_C]) {
output = make_filename(input, PREPROC_C, where(PREPROC_C));
} else {
output = null;
}
cmd_list(exec_preproc);
cmd_list(opt_preproc);
producer_options(PREPROC_ID);
cmd_filename(input);
if (output) {
cmd_filename(output);
}
output = execute(input, output);
return (output);
}
/*
* APPLY THE C++ PRODUCER
*
* This routine applies the C++ to TDF producer to input and returns the
* result.
*/
filename *
do_cpp_produce(filename *input)
{
filename *spec;
filename *output, *producer_output;
if (input == null) {
return (input);
}
output = make_filename(input, INDEP_TDF, where(INDEP_TDF));
cmd_list(exec_cpp_produce);
if (allow_specs == 1) {
spec = make_filename(input, CPP_SPEC, where(CPP_SPEC));
if (dump_opts) {
cmd_string(string_concat(dump_opts, spec->name));
} else {
cmd_string("-s");
cmd_string(spec->name);
}
}
cmd_list(opt_cpp_produce);
producer_options(CPP_PRODUCE_ID);
cmd_filename(input);
cmd_filename(output);
producer_output = execute(input, output);
/*
* If we are in checker mode and intermodular checks are enabled we
* must ignore any errors from the producer and continue to run the
* dump_linker.
*/
if (checker) {
reset_exec_error();
} else {
output = producer_output;
}
if (allow_specs == 1) {
SET(spec);
output = add_filename(output, spec);
}
if (allow_specs == 2 && output) {
spec = make_filename(input, CPP_SPEC, where(CPP_SPEC));
cmd_list(exec_touch);
cmd_filename(spec);
cmd_string("-k");
spec = execute(no_filename, spec);
output = add_filename(output, spec);
}
return (output);
}
/*
* APPLY THE C++ PREPROCESSOR
*
* This routine applies the TDF C++ preprocessor to input and returns the
* result. If files of type PREPROC_C are not being preserved then the output
* is copied to the standard output.
*/
filename *
do_cpp_preproc(filename *input)
{
filename *output;
if (input == null) {
return (input);
}
if (checker && !use_system_cc) {
return (input);
}
if (keeps[PREPROC_CPP]) {
output = make_filename(input, PREPROC_CPP, where(PREPROC_CPP));
} else {
output = null;
}
cmd_list(exec_cpp_preproc);
cmd_list(opt_cpp_preproc);
producer_options(CPP_PREPROC_ID);
cmd_filename(input);
if (output != null) {
cmd_filename(output);
}
output = execute(input, output);
return (output);
}
/*
* APPLY THE TDF LINKER
*
* This routine applies the TDF linker to input and returns the result. This
* is the normal action of the TDF linker - linking target independent TDF with
* the TDF libraries to form target dependent TDF (also see do_tdf_build).
*/
filename *
do_tdf_link(filename *input)
{
filename *output;
if (input == null || stops[INDEP_TDF]) {
return (input);
}
output = make_filename(input, DEP_TDF, where(DEP_TDF));
cmd_list(exec_tdf_link);
cmd_list(opt_tdf_link);
cmd_list(usr_tdf_link_libdirs);
cmd_list(std_tdf_link_libdirs);
cmd_list(usr_tdf_link_libs);
cmd_list(std_tdf_link_libs);
cmd_string("-o");
cmd_filename(output);
cmd_filename(input);
if (tokdef_output) {
cmd_string(tokdef_output);
}
return (execute(input, output));
}
/*
* APPLY THE TDF LINKER TO BUILD A COMPLEX
*
* This routine applies the TDF linker to combine a set of target independent
* TDF capsules, input, into a single independent TDF capsule, which is then
* returned. To avoid possible clashes with the input files, the output is
* firstly directed to a temporary file, which is then moved to the output
* file.
*/
filename *
do_tdf_build(filename *input)
{
int keep;
filename *output;
if (input == null) {
return (input);
}
if (exec_error) {
return (null);
}
keep = where(INDEP_TDF_COMPLEX);
output = uniq_filename(name_j_file, INDEP_TDF, keep, input);
cmd_list(exec_tdf_link);
cmd_list(opt_tdf_link);
if (flag_merge_all) {
cmd_string("-a");
cmd_string("-k");
cmd_string("tag");
cmd_string("main");
}
cmd_string("-o");
cmd_filename(uniq_tempfile);
cmd_filename(input);
return (do_move(execute(input, uniq_tempfile), output));
}
/*
* APPLY THE TRANSLATOR
*
* This routine applies the TDF translator to the input files, input, and
* returns the result. This routine is complicated by the fact that most TDF
* translators produce assembler source, but some bypass the assembler to
* directly produce binary object files. The mips translator produces two
* output files, a .G file and a .T file, so this is also a special case.
*/
filename *
do_translate(filename *input)
{
int t;
filename *output;
if (input == null || stops[DEP_TDF]) {
return (input);
}
if (use_assembler) {
t = AS_SOURCE;
output = make_filename(input, t, where(t));
} else {
t = binary_obj_type;
output = make_filename(input, t, where(t));
output->type = BINARY_OBJ;
}
cmd_list(exec_translate);
if (flag_diag) {
if (flag_diag == 2) {
cmd_string("-J");
} else {
if (flag_optim) {
cmd_string("-HO");
} else {
cmd_string("-H");
}
}
}
if (flag_nepc) {
cmd_string("-E");
}
if (use_mips_assembler) {
static char *vflag = null;
if (vflag == null) {
vflag = string_concat("-V", version_flag);
}
cmd_string(vflag);
}
cmd_list(opt_translate);
if (use_mips_assembler || use_alpha_assembler) {
/* Deal with the mips assembler */
t = MIPS_G_FILE;
output->aux = make_filename(input, t, where(t));
t = MIPS_T_FILE;
output->aux->aux = make_filename(input, t, where(t));
if (keeps[AS_SOURCE]) {
cmd_string("-S");
cmd_filename(input);
cmd_filename(output->aux);
cmd_filename(output->aux->aux);
cmd_filename(output);
} else {
cmd_filename(input);
cmd_filename(output->aux);
cmd_filename(output->aux->aux);
}
} else if (use_assembler) {
/* Deal with normal assemblers */
cmd_filename(input);
cmd_filename(output);
} else {
/* Deal with non-assemblers */
if (keeps[AS_SOURCE]) {
t = AS_SOURCE;
output->aux = make_filename(input, t, where(t));
cmd_string("-S");
cmd_filename(input);
cmd_filename(output);
cmd_filename(output->aux);
} else {
cmd_filename(input);
cmd_filename(output);
}
}
return (execute(input, output));
}
/*
* APPLY THE ASSEMBLER
*
* This routine applies the assembler to the input files, input, and returns
* the result. The routine is complicated because of the need to handle the .G
* and .T files output by the mips translator.
*/
filename *
do_assemble(filename *input)
{
filename *output;
int t = binary_obj_type;
if (input == null || stops[AS_SOURCE]) {
return (input);
}
output = make_filename(input, t, where(t));
output->type = BINARY_OBJ;
if (input->aux && input->aux->type == MIPS_G_FILE &&
input->aux->aux && input->aux->aux->type == MIPS_T_FILE) {
/* Deal with the mips assembler */
cmd_list(exec_assemble_mips);
cmd_list(opt_assemble_mips);
cmd_string("-o");
cmd_filename(output);
cmd_filename(input->aux);
cmd_string("-t");
cmd_filename(input->aux->aux);
} else {
/* Deal with normal assemblers */
cmd_list(exec_assemble);
cmd_list(opt_assemble);
cmd_string("-o");
cmd_filename(output);
cmd_filename(input);
}
return (execute(input, output));
}
/*
* LIST OF LIBRARIES
*
* This is set by linker_options to be the list of libraries passed to the
* linker. Needs to be passed twice in the case of DYNLINK with shared
* libaries.
*/
static list *dl_libs = null;
/*
* DYNLINK SWITCH
*
* This remains 0 if normal linking is being done, and is set to 1 before the
* first-stage dynamic-initialisation linking. After the first call to
* 'linker_options', the value is increase so that it becomes two for the
* second-stage link.
*/
static int dl_state = 0;
/*
* PRINT LINK/DYNLINK OPTIONS
*
* The link and dynlink stages use the same command-line options with the
* exception of crt0, crt1 and crtn files since the dynamic-initialisation
* linking doesn't produce an executable. The variable 'use_dynlink' is either
* 1, 2 or 3 depending on whether the CRT startup files are linked on the
* first, second or both of the two dynlink stages.
*/
static void
linker_options(filename *input, filename *output)
{
if (use_system_cc) {
cmd_list(exec_cc);
if (flag_diag) {
cmd_string("-g");
}
if (flag_strip) {
cmd_string("-s");
}
cmd_list(opt_cc);
cmd_string("-o");
cmd_filename(output);
} else {
cmd_list(exec_link);
if (dl_state == 1) {
cmd_string("-r");
} else {
cmd_list(std_link_entry);
}
if (flag_strip && (dl_state != 1)) {
cmd_string("-s");
}
cmd_list(opt_link);
cmd_string("-o");
cmd_filename(output);
if ((dl_state == 0) || (dl_state & use_dynlink)!= 0) {
cmd_list(std_link_crt0);
cmd_list(std_link_crt1);
}
}
if (use_hp_linker) {
filename *p;
for (p = input; p != null; p = p->next) {
char *arg = p->name;
if (strneq(arg, "-B", 2)) {
cmd_string("-B");
cmd_string(arg + 2);
} else if (strneq(arg, "-L", 2)) {
cmd_string("-L");
cmd_string(arg + 2);
} else if (strneq(arg, "-l", 2)) {
/*
* Save up -l options for inclusion after any
* -L options.
*/
dl_libs = add_item(dl_libs, arg);
} else {
cmd_string(arg);
}
}
} else {
filename *p;
for (p = input; p != null; p = p->next) {
char *arg = p->name;
if (strneq(arg, "-l", 2)) {
/*
* Save up -l options for inclusion after any
* -L options.
*/
dl_libs = add_item(dl_libs, arg);
} else if (dl_state && (p->storage == INPUT_OPTION)) {
/*
* Add input options to user link options for
* subsequent use.
*/
opt_link = add_item(opt_link, arg);
cmd_string(arg);
} else {
cmd_string(arg);
}
}
}
if (!use_system_cc) {
/* usr_link_libdirs forms part of input */
cmd_list(std_link_libdirs);
}
/* now include the -l options */
if (dl_libs != null) {
cmd_list(dl_libs);
}
if (!use_system_cc) {
/* usr_link_libs forms part of input */
cmd_list(std_link_libs);
cmd_list(std_link_c_libs);
if ((dl_state == 0) || (dl_state & use_dynlink)!= 0) {
cmd_list(std_link_crtp_n);
cmd_list(std_link_crtn);
}
}
dl_state++;
return;
}
/*
* APPLY THE RS6000/SPARC DYNAMIC INITIALISATION PROGRAM
*
* This routine calls the program to create a .s file with the necessary
* dynamic initialisation calls for AIX and SunOS, and adds the corresponding
* .o to the file list.
*/
filename *
do_dynlink(filename *input)
{
filename *linked_ofiles, *extra_sfile, *output = null;
if (input == null || stops[BINARY_OBJ]) {
return (input);
}
if (checker && !use_system_cc) {
return (input);
}
if (!exec_error) {
linked_ofiles = make_filename(no_filename, binary_obj_type,
TEMP_FILE);
dl_state = 1;
linker_options(input, linked_ofiles);
IGNORE execute(input, output);
}
if (!exec_error) {
output = make_filename(no_filename, AS_SOURCE, TEMP_FILE);
cmd_list(exec_dynlink);
cmd_list(opt_dynlink);
SET(linked_ofiles);
cmd_filename(linked_ofiles);
cmd_filename(output);
extra_sfile = execute(linked_ofiles, output);
}
if (exec_error) {
last_return = 1;
return (null);
}
SET(linked_ofiles);
SET(extra_sfile);
output = do_assemble(extra_sfile);
if (use_dynlink == 3) {
return (add_filename(output, input));
}
return (add_filename(output, linked_ofiles));
}
/*
* APPLY THE SYSTEM LINKER
*
* This routine applies the system linker to the input files, input, and
* returns the result. The output executable name is, by default,
* EXECUTABLE_NAME. Things are slightly complicated by the fact that the HP
* linkers insist on certain options being in two parts.
*/
filename *
do_link(filename *input)
{
int keep;
filename *output;
if (input == null || stops[BINARY_OBJ]) {
return (input);
}
if (checker && !use_system_cc) {
return (input);
}
if (exec_error) {
last_return = 1;
return (null);
}
keep = where(EXECUTABLE);
output = uniq_filename(EXECUTABLE_NAME, EXECUTABLE, keep, no_filename);
linker_options(input, output);
return (execute(input, output));
}
/*
* APPLY THE TDF NOTATION COMPILER
*
* This routine applies the TDF notation compiler to the input files, input,
* and returns the result.
*/
filename *
do_notation(filename *input)
{
int keep;
filename *output;
if (input == null) {
return (input);
}
keep = where(INDEP_TDF);
if (tokdef_name && streq(input->name, tokdef_name)) {
keep = TEMP_FILE;
}
output = make_filename(input, INDEP_TDF, keep);
cmd_list(exec_notation);
cmd_list(opt_notation);
cmd_list(usr_prod_incldirs);
cmd_filename(input);
cmd_filename(output);
return (execute(input, output));
}
/*
* APPLY THE PL_TDF COMPILER
*
* This routine applies the PL_TDF compiler to the input files, input, and
* returns the result.
*/
filename *
do_pl_tdf(filename *input)
{
filename *output;
if (input == null) {
return (input);
}
output = make_filename(input, INDEP_TDF, where(INDEP_TDF));
cmd_list(exec_pl_tdf);
cmd_list(opt_pl_tdf);
cmd_list(usr_pl_tdf_incldirs);
if (flag_diag) {
cmd_string("-g");
}
cmd_filename(input);
cmd_filename(output);
return (execute(input, output));
}
/*
* APPLY THE TDF PRETTY PRINTER
*
* This routine applies the TDF pretty printer to the input files, input, and
* returns the result.
*/
filename *
do_pretty(filename *input)
{
filename *output;
if (input == null || stops[DEP_TDF]) {
return (input);
}
output = make_filename(input, PRETTY_TDF, where(PRETTY_TDF));
cmd_list(exec_pretty);
if (flag_diag) {
cmd_string("-g");
}
cmd_list(opt_pretty);
cmd_filename(input);
cmd_filename(output);
return (execute(input, output));
}
/*
* SPLIT A TDF ARCHIVE
*
* This routine splits the TDF archive, input, and returns the result.
*/
filename *
do_split_arch(filename *input)
{
if (input == null) {
return (input);
}
cmd_list(exec_split_arch);
cmd_filename(input);
return (execute(input, no_filename));
}
/*
* BUILD A TDF ARCHIVE
*
* This routine creates a TDF archive from the input files, input, and the
* archive options, opt_archive, and returns the result. The output archive
* name is, by default, TDF_ARCHIVE_NAME. The aux field of the output contains
* the archive contents.
*/
filename *
do_build_arch(filename *input)
{
int keep;
filename *output;
if (input == null || stops[INDEP_TDF]) {
return (input);
}
if (exec_error) {
return (null);
}
archive_type = TDF_ARCHIVE;
keep = where(TDF_ARCHIVE);
output = uniq_filename(TDF_ARCHIVE_NAME, TDF_ARCHIVE, keep,
no_filename);
cmd_list(exec_build_arch);
cmd_filename(output);
cmd_filename(input);
if (opt_archive) {
cmd_string(ARCHIVE_OPTION_START);
cmd_list(opt_archive);
}
output = execute(input, output);
if (output) {
output->aux = input;
}
return (output);
}
/*
* BUILD AN ARCHIVE FILE
*
* This routine creates an archive file of type t from the input files and
* returns the result. The aux field of the output contains the archive
* contents.
*/
filename *
do_build_file(filename *input, int t)
{
int s;
filename *output;
if (input == null) {
return (input);
}
if (!(keeps[t] || keeps_aux[t] == 1)) {
return (input);
}
archive_type = t;
s = input->type;
input->type = UNKNOWN_TYPE;
output = make_filename(input, t, where(t));
input->type = s;
cmd_list(exec_build_arch);
cmd_filename(output);
cmd_filename(input);
if (allow_specs == 2) {
cmd_string(ARCHIVE_OPTION_START);
cmd_string("--2CS");
}
output = execute(input, output);
if (output) {
output->aux = input;
}
return (output);
}
/*
* LINK A NUMBER OF C AND C++ SPECS
*
* This routine links a number of C++ specs, input, into one, which is then
* returned. To avoid possible clashes with the input files, the output is
* firstly directed to a temporary file, which is then moved to the output
* file. The variable t is the dummy file type, C_SPEC_1, C_SPEC_2, CPP_SPEC_1
* or CPP_SPEC_2.
*/
filename *
do_link_specs(filename *input, int t)
{
int keep;
filename *output, *spec_file;
if (input == null) {
return (input);
}
if (t == C_SPEC_2 || t == CPP_SPEC_2) {
/* Don't link in these cases */
if (stops[BINARY_OBJ]) {
return (input);
}
}
if (exec_error && !checker) {
last_return = 1;
return (null);
}
keep = where(t);
if (allow_specs == 1 && dump_opts == null) {
output = make_filename(no_filename, INDEP_TDF, TEMP_FILE);
if (t == C_SPEC_1 || t == C_SPEC_2) {
spec_file = uniq_filename(name_k_file, C_SPEC, keep,
input);
cmd_list(exec_spec_link);
cmd_list(opt_spec_link);
} else {
spec_file = uniq_filename(name_K_file, CPP_SPEC, keep,
input);
cmd_list(exec_cpp_spec_link);
cmd_list(opt_cpp_spec_link);
}
if (checker) {
cmd_string("-c");
}
if (make_pretty) {
cmd_string("-t");
}
cmd_string("-s");
cmd_string(uniq_tempfile->name);
cmd_filename(input);
cmd_filename(output);
output = execute(input, output);
if (checker) {
output = null;
}
output = add_filename(output, do_move(uniq_tempfile,
spec_file));
} else {
if (t == C_SPEC_1 || t == C_SPEC_2) {
output = uniq_filename(name_k_file, C_SPEC, keep,
input);
} else {
output = uniq_filename(name_K_file, CPP_SPEC, keep,
input);
}
if (allow_specs == 1) {
cmd_list(exec_dump_link);
cmd_list(opt_dump_link);
cmd_filename(input);
cmd_filename(output);
output = execute(input, output);
} else {
cmd_list(exec_touch);
cmd_filename(uniq_tempfile);
cmd_string("-k");
output = execute(no_filename, output);
}
}
return (output);
}
/*
* USE THE SYSTEM COMPILER
*
* tcc may optionally be used do invoke the system compiler, cc. This routine
* applies cc to the input files, input, compiling as far as files of type t,
* and returning the output files.
*/
filename *
do_cc(filename *input, int t)
{
char *flag;
filename *output;
if (input == null) {
return (input);
}
output = make_filename(input, t, where(t));
if (t == PREPROC_C) {
if (keeps[t]) {
flag = "-P";
} else {
flag = "-E";
output = null;
}
} else if (t == AS_SOURCE) {
flag = "-S";
} else {
flag = "-c";
output->type = BINARY_OBJ;
}
cmd_list(exec_cc);
cmd_string(flag);
if (flag_diag) {
cmd_string("-g");
}
cmd_list(opt_cc);
if (use_sparc_cc == 2 && output) {
filename *real_output;
real_output = make_filename(input, output->type,
PRESERVED_FILE);
real_output->name = find_basename(real_output->name);
cmd_filename(input);
real_output = execute(input, real_output);
return (do_move(real_output, output));
} else {
if (output) {
cmd_string("-o");
cmd_filename(output);
}
cmd_filename(input);
return (execute(input, output));
}
}