Remove files that are not part of GCC distribution anymore.
This commit is contained in:
parent
096b39c236
commit
8902467bb7
@ -1,74 +0,0 @@
|
||||
/* Utility to pick a temporary filename prefix.
|
||||
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the libiberty library.
|
||||
Libiberty is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
Libiberty is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with libiberty; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* May get P_tmpdir. */
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include "libiberty.h"
|
||||
extern char *choose_tmpdir PARAMS ((void));
|
||||
|
||||
/* Name of temporary file.
|
||||
mktemp requires 6 trailing X's. */
|
||||
#define TEMP_FILE "ccXXXXXX"
|
||||
#define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
|
||||
|
||||
/*
|
||||
|
||||
@deftypefn Extension char* choose_temp_base (void)
|
||||
|
||||
Return a prefix for temporary file names or @code{NULL} if unable to
|
||||
find one. The current directory is chosen if all else fails so the
|
||||
program is exited if a temporary directory can't be found (@code{mktemp}
|
||||
fails). The buffer for the result is obtained with @code{xmalloc}.
|
||||
|
||||
This function is provided for backwards compatability only. Its use is
|
||||
not recommended.
|
||||
|
||||
@end deftypefn
|
||||
|
||||
*/
|
||||
|
||||
char *
|
||||
choose_temp_base ()
|
||||
{
|
||||
const char *base = choose_tmpdir ();
|
||||
char *temp_filename;
|
||||
int len;
|
||||
|
||||
len = strlen (base);
|
||||
temp_filename = xmalloc (len + TEMP_FILE_LEN + 1);
|
||||
strcpy (temp_filename, base);
|
||||
strcpy (temp_filename + len, TEMP_FILE);
|
||||
|
||||
mktemp (temp_filename);
|
||||
if (strlen (temp_filename) == 0)
|
||||
abort ();
|
||||
return temp_filename;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,459 +0,0 @@
|
||||
/* Definitions of target machine for GNU compiler, for DEC Alpha w/ELF.
|
||||
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Richard Henderson (rth@tamu.edu).
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#undef OBJECT_FORMAT_COFF
|
||||
#undef EXTENDED_COFF
|
||||
#define OBJECT_FORMAT_ELF 1
|
||||
|
||||
/* ??? Move all SDB stuff from alpha.h to osf.h. */
|
||||
#undef SDB_DEBUGGING_INFO
|
||||
|
||||
#define DBX_DEBUGGING_INFO 1
|
||||
#define DWARF2_DEBUGGING_INFO 1
|
||||
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
|
||||
|
||||
#undef ASM_FINAL_SPEC
|
||||
|
||||
/* alpha/ doesn't use elfos.h for some reason. */
|
||||
#define TARGET_OBJFMT_CPP_BUILTINS() \
|
||||
do \
|
||||
{ \
|
||||
builtin_define ("__ELF__"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#undef CC1_SPEC
|
||||
#define CC1_SPEC "%{G*}"
|
||||
|
||||
#undef ASM_SPEC
|
||||
#define ASM_SPEC "%{G*} %{relax:-relax} %{!gstabs*:-no-mdebug}%{gstabs*:-mdebug}"
|
||||
|
||||
#undef IDENT_ASM_OP
|
||||
#define IDENT_ASM_OP "\t.ident\t"
|
||||
|
||||
/* Output #ident as a .ident. */
|
||||
#undef ASM_OUTPUT_IDENT
|
||||
#define ASM_OUTPUT_IDENT(FILE, NAME) \
|
||||
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
|
||||
|
||||
/* This is how to allocate empty space in some section. The .zero
|
||||
pseudo-op is used for this on most svr4 assemblers. */
|
||||
|
||||
#undef SKIP_ASM_OP
|
||||
#define SKIP_ASM_OP "\t.zero\t"
|
||||
|
||||
#undef ASM_OUTPUT_SKIP
|
||||
#define ASM_OUTPUT_SKIP(FILE, SIZE) \
|
||||
fprintf (FILE, "%s"HOST_WIDE_INT_PRINT_UNSIGNED"\n", SKIP_ASM_OP, (SIZE))
|
||||
|
||||
/* Output the label which precedes a jumptable. Note that for all svr4
|
||||
systems where we actually generate jumptables (which is to say every
|
||||
svr4 target except i386, where we use casesi instead) we put the jump-
|
||||
tables into the .rodata section and since other stuff could have been
|
||||
put into the .rodata section prior to any given jumptable, we have to
|
||||
make sure that the location counter for the .rodata section gets pro-
|
||||
perly re-aligned prior to the actual beginning of the jump table. */
|
||||
|
||||
#undef ALIGN_ASM_OP
|
||||
#define ALIGN_ASM_OP "\t.align\t"
|
||||
|
||||
#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL
|
||||
#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \
|
||||
ASM_OUTPUT_ALIGN ((FILE), 2);
|
||||
#endif
|
||||
|
||||
#undef ASM_OUTPUT_CASE_LABEL
|
||||
#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \
|
||||
do { \
|
||||
ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \
|
||||
(*targetm.asm_out.internal_label) (FILE, PREFIX, NUM); \
|
||||
} while (0)
|
||||
|
||||
/* The standard SVR4 assembler seems to require that certain builtin
|
||||
library routines (e.g. .udiv) be explicitly declared as .globl
|
||||
in each assembly file where they are referenced. */
|
||||
|
||||
#undef ASM_OUTPUT_EXTERNAL_LIBCALL
|
||||
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
|
||||
(*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0))
|
||||
|
||||
/* This says how to output assembler code to declare an
|
||||
uninitialized external linkage data object. Under SVR4,
|
||||
the linker seems to want the alignment of data objects
|
||||
to depend on their types. We do exactly that here. */
|
||||
|
||||
#undef COMMON_ASM_OP
|
||||
#define COMMON_ASM_OP "\t.comm\t"
|
||||
|
||||
#undef ASM_OUTPUT_ALIGNED_COMMON
|
||||
#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
|
||||
do { \
|
||||
fprintf ((FILE), "%s", COMMON_ASM_OP); \
|
||||
assemble_name ((FILE), (NAME)); \
|
||||
fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
|
||||
} while (0)
|
||||
|
||||
/* This says how to output assembler code to declare an
|
||||
uninitialized internal linkage data object. Under SVR4,
|
||||
the linker seems to want the alignment of data objects
|
||||
to depend on their types. We do exactly that here. */
|
||||
|
||||
#undef ASM_OUTPUT_ALIGNED_LOCAL
|
||||
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
|
||||
do { \
|
||||
if ((SIZE) <= g_switch_value) \
|
||||
sbss_section(); \
|
||||
else \
|
||||
bss_section(); \
|
||||
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
|
||||
if (!flag_inhibit_size_directive) \
|
||||
ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
|
||||
ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
|
||||
ASM_OUTPUT_LABEL(FILE, NAME); \
|
||||
ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
|
||||
} while (0)
|
||||
|
||||
/* This says how to output assembler code to declare an
|
||||
uninitialized external linkage data object. */
|
||||
|
||||
#undef ASM_OUTPUT_ALIGNED_BSS
|
||||
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
|
||||
do { \
|
||||
ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \
|
||||
} while (0)
|
||||
|
||||
/* Biggest alignment supported by the object file format of this
|
||||
machine. Use this macro to limit the alignment which can be
|
||||
specified using the `__attribute__ ((aligned (N)))' construct. If
|
||||
not defined, the default value is `BIGGEST_ALIGNMENT'.
|
||||
|
||||
This value is really 2^63. Since gcc figures the alignment in bits,
|
||||
we could only potentially get to 2^60 on suitable hosts. Due to other
|
||||
considerations in varasm, we must restrict this to what fits in an int. */
|
||||
|
||||
#undef MAX_OFILE_ALIGNMENT
|
||||
#define MAX_OFILE_ALIGNMENT \
|
||||
(1 << (HOST_BITS_PER_INT < 64 ? HOST_BITS_PER_INT - 2 : 62))
|
||||
|
||||
/* This is the pseudo-op used to generate a contiguous sequence of byte
|
||||
values from a double-quoted string WITHOUT HAVING A TERMINATING NUL
|
||||
AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */
|
||||
|
||||
#undef ASCII_DATA_ASM_OP
|
||||
#define ASCII_DATA_ASM_OP "\t.ascii\t"
|
||||
|
||||
#undef READONLY_DATA_SECTION_ASM_OP
|
||||
#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata"
|
||||
#undef BSS_SECTION_ASM_OP
|
||||
#define BSS_SECTION_ASM_OP "\t.section\t.bss"
|
||||
#undef SBSS_SECTION_ASM_OP
|
||||
#define SBSS_SECTION_ASM_OP "\t.section\t.sbss,\"aw\""
|
||||
#undef SDATA_SECTION_ASM_OP
|
||||
#define SDATA_SECTION_ASM_OP "\t.section\t.sdata,\"aw\""
|
||||
|
||||
/* On svr4, we *do* have support for the .init and .fini sections, and we
|
||||
can put stuff in there to be executed before and after `main'. We let
|
||||
crtstuff.c and other files know this by defining the following symbols.
|
||||
The definitions say how to change sections to the .init and .fini
|
||||
sections. This is the same for all known svr4 assemblers. */
|
||||
|
||||
#undef INIT_SECTION_ASM_OP
|
||||
#define INIT_SECTION_ASM_OP "\t.section\t.init"
|
||||
#undef FINI_SECTION_ASM_OP
|
||||
#define FINI_SECTION_ASM_OP "\t.section\t.fini"
|
||||
|
||||
#ifdef HAVE_GAS_SUBSECTION_ORDERING
|
||||
|
||||
#define ASM_SECTION_START_OP "\t.subsection\t-1"
|
||||
|
||||
/* Output assembly directive to move to the beginning of current section. */
|
||||
#define ASM_OUTPUT_SECTION_START(FILE) \
|
||||
fprintf ((FILE), "%s\n", ASM_SECTION_START_OP)
|
||||
|
||||
#endif
|
||||
|
||||
/* A default list of other sections which we might be "in" at any given
|
||||
time. For targets that use additional sections (e.g. .tdesc) you
|
||||
should override this definition in the target-specific file which
|
||||
includes this file. */
|
||||
|
||||
#undef EXTRA_SECTIONS
|
||||
#define EXTRA_SECTIONS in_sbss, in_sdata
|
||||
|
||||
/* A default list of extra section function definitions. For targets
|
||||
that use additional sections (e.g. .tdesc) you should override this
|
||||
definition in the target-specific file which includes this file. */
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
SECTION_FUNCTION_TEMPLATE(sbss_section, in_sbss, SBSS_SECTION_ASM_OP) \
|
||||
SECTION_FUNCTION_TEMPLATE(sdata_section, in_sdata, SDATA_SECTION_ASM_OP)
|
||||
|
||||
extern void sbss_section (void);
|
||||
extern void sdata_section (void);
|
||||
|
||||
#undef SECTION_FUNCTION_TEMPLATE
|
||||
#define SECTION_FUNCTION_TEMPLATE(FN, ENUM, OP) \
|
||||
void FN (void) \
|
||||
{ \
|
||||
if (in_section != ENUM) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", OP); \
|
||||
in_section = ENUM; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Switch into a generic section. */
|
||||
#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
|
||||
#define TARGET_ASM_SELECT_SECTION default_elf_select_section
|
||||
|
||||
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
|
||||
|
||||
/* Define the strings used for the special svr4 .type and .size directives.
|
||||
These strings generally do not vary from one system running svr4 to
|
||||
another, but if a given system (e.g. m88k running svr) needs to use
|
||||
different pseudo-op names for these, they may be overridden in the
|
||||
file which includes this one. */
|
||||
|
||||
#undef TYPE_ASM_OP
|
||||
#define TYPE_ASM_OP "\t.type\t"
|
||||
#undef SIZE_ASM_OP
|
||||
#define SIZE_ASM_OP "\t.size\t"
|
||||
|
||||
/* This is how we tell the assembler that a symbol is weak. */
|
||||
|
||||
#undef ASM_WEAKEN_LABEL
|
||||
#define ASM_WEAKEN_LABEL(FILE, NAME) \
|
||||
do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
|
||||
fputc ('\n', FILE); } while (0)
|
||||
|
||||
/* This is how we tell the assembler that two symbols have the same value. */
|
||||
|
||||
#undef ASM_OUTPUT_DEF
|
||||
#define ASM_OUTPUT_DEF(FILE, ALIAS, NAME) \
|
||||
do { \
|
||||
assemble_name(FILE, ALIAS); \
|
||||
fputs(" = ", FILE); \
|
||||
assemble_name(FILE, NAME); \
|
||||
fputc('\n', FILE); \
|
||||
} while (0)
|
||||
|
||||
#undef ASM_OUTPUT_DEF_FROM_DECLS
|
||||
#define ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL, TARGET) \
|
||||
do { \
|
||||
const char *alias = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
|
||||
const char *name = IDENTIFIER_POINTER (TARGET); \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
{ \
|
||||
fputc ('$', FILE); \
|
||||
assemble_name (FILE, alias); \
|
||||
fputs ("..ng = $", FILE); \
|
||||
assemble_name (FILE, name); \
|
||||
fputs ("..ng\n", FILE); \
|
||||
} \
|
||||
assemble_name(FILE, alias); \
|
||||
fputs(" = ", FILE); \
|
||||
assemble_name(FILE, name); \
|
||||
fputc('\n', FILE); \
|
||||
} while (0)
|
||||
|
||||
/* The following macro defines the format used to output the second
|
||||
operand of the .type assembler directive. Different svr4 assemblers
|
||||
expect various different forms for this operand. The one given here
|
||||
is just a default. You may need to override it in your machine-
|
||||
specific tm.h file (depending upon the particulars of your assembler). */
|
||||
|
||||
#undef TYPE_OPERAND_FMT
|
||||
#define TYPE_OPERAND_FMT "@%s"
|
||||
|
||||
/* Write the extra assembler code needed to declare a function's result.
|
||||
Most svr4 assemblers don't require any special declaration of the
|
||||
result value, but there are exceptions. */
|
||||
|
||||
#ifndef ASM_DECLARE_RESULT
|
||||
#define ASM_DECLARE_RESULT(FILE, RESULT)
|
||||
#endif
|
||||
|
||||
/* These macros generate the special .type and .size directives which
|
||||
are used to set the corresponding fields of the linker symbol table
|
||||
entries in an ELF object file under SVR4. These macros also output
|
||||
the starting labels for the relevant functions/objects. */
|
||||
|
||||
/* Write the extra assembler code needed to declare an object properly. */
|
||||
|
||||
#undef ASM_DECLARE_OBJECT_NAME
|
||||
#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
|
||||
do { \
|
||||
HOST_WIDE_INT size; \
|
||||
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
|
||||
size_directive_output = 0; \
|
||||
if (!flag_inhibit_size_directive \
|
||||
&& DECL_SIZE (DECL) \
|
||||
&& (size = int_size_in_bytes (TREE_TYPE (DECL))) > 0) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
|
||||
} \
|
||||
ASM_OUTPUT_LABEL(FILE, NAME); \
|
||||
} while (0)
|
||||
|
||||
/* Output the size directive for a decl in rest_of_decl_compilation
|
||||
in the case where we did not do so before the initializer.
|
||||
Once we find the error_mark_node, we know that the value of
|
||||
size_directive_output was set
|
||||
by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
|
||||
|
||||
#undef ASM_FINISH_DECLARE_OBJECT
|
||||
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
|
||||
do { \
|
||||
const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
|
||||
HOST_WIDE_INT size; \
|
||||
if (!flag_inhibit_size_directive \
|
||||
&& DECL_SIZE (DECL) \
|
||||
&& ! AT_END && TOP_LEVEL \
|
||||
&& DECL_INITIAL (DECL) == error_mark_node \
|
||||
&& !size_directive_output \
|
||||
&& (size = int_size_in_bytes (TREE_TYPE (DECL))) > 0) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
|
||||
ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
|
||||
corresponds to a particular byte value [0..255]. For any
|
||||
given byte value, if the value in the corresponding table
|
||||
position is zero, the given character can be output directly.
|
||||
If the table value is 1, the byte must be output as a \ooo
|
||||
octal escape. If the tables value is anything else, then the
|
||||
byte value should be output as a \ followed by the value
|
||||
in the table. Note that we can use standard UN*X escape
|
||||
sequences for many control characters, but we don't use
|
||||
\a to represent BEL because some svr4 assemblers (e.g. on
|
||||
the i386) don't know about that. Also, we don't use \v
|
||||
since some versions of gas, such as 2.2 did not accept it. */
|
||||
|
||||
#undef ESCAPES
|
||||
#define ESCAPES \
|
||||
"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
|
||||
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
|
||||
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
|
||||
|
||||
/* Some svr4 assemblers have a limit on the number of characters which
|
||||
can appear in the operand of a .string directive. If your assembler
|
||||
has such a limitation, you should define STRING_LIMIT to reflect that
|
||||
limit. Note that at least some svr4 assemblers have a limit on the
|
||||
actual number of bytes in the double-quoted string, and that they
|
||||
count each character in an escape sequence as one byte. Thus, an
|
||||
escape sequence like \377 would count as four bytes.
|
||||
|
||||
If your target assembler doesn't support the .string directive, you
|
||||
should define this to zero. */
|
||||
|
||||
#undef STRING_LIMIT
|
||||
#define STRING_LIMIT ((unsigned) 256)
|
||||
#undef STRING_ASM_OP
|
||||
#define STRING_ASM_OP "\t.string\t"
|
||||
|
||||
/* GAS is the only Alpha/ELF assembler. */
|
||||
#undef TARGET_GAS
|
||||
#define TARGET_GAS (1)
|
||||
|
||||
/* Provide a STARTFILE_SPEC appropriate for ELF. Here we add the
|
||||
(even more) magical crtbegin.o file which provides part of the
|
||||
support for getting C++ file-scope static object constructed
|
||||
before entering `main'. */
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#ifdef HAVE_LD_PIE
|
||||
#define STARTFILE_SPEC \
|
||||
"%{!shared: %{pg|p:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}}\
|
||||
crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
|
||||
#else
|
||||
#define STARTFILE_SPEC \
|
||||
"%{!shared: %{pg|p:gcrt1.o%s;:crt1.o%s}}\
|
||||
crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
|
||||
#endif
|
||||
|
||||
/* Provide a ENDFILE_SPEC appropriate for ELF. Here we tack on the
|
||||
magical crtend.o file which provides part of the support for
|
||||
getting C++ file-scope static object constructed before entering
|
||||
`main', followed by a normal ELF "finalizer" file, `crtn.o'. */
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC \
|
||||
"%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
|
||||
%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
|
||||
|
||||
/* We support #pragma. */
|
||||
#define HANDLE_SYSV_PRAGMA 1
|
||||
|
||||
/* Select a format to encode pointers in exception handling data. CODE
|
||||
is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
|
||||
true if the symbol may be affected by dynamic relocations.
|
||||
|
||||
Since application size is already constrained to <2GB by the form of
|
||||
the ldgp relocation, we can use a 32-bit pc-relative relocation to
|
||||
static data. Dynamic data is accessed indirectly to allow for read
|
||||
only EH sections. */
|
||||
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
|
||||
(((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4)
|
||||
|
||||
/* If defined, a C statement to be executed just prior to the output of
|
||||
assembler code for INSN. */
|
||||
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
|
||||
(alpha_this_literal_sequence_number = 0, \
|
||||
alpha_this_gpdisp_sequence_number = 0)
|
||||
extern int alpha_this_literal_sequence_number;
|
||||
extern int alpha_this_gpdisp_sequence_number;
|
||||
|
||||
/* Since the bits of the _init and _fini function is spread across
|
||||
many object files, each potentially with its own GP, we must assume
|
||||
we need to load our GP. Further, the .init/.fini section can
|
||||
easily be more than 4MB away from the function to call so we can't
|
||||
use bsr. */
|
||||
#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
|
||||
asm (SECTION_OP "\n" \
|
||||
" br $29,1f\n" \
|
||||
"1: ldgp $29,0($29)\n" \
|
||||
" unop\n" \
|
||||
" jsr $26," USER_LABEL_PREFIX #FUNC "\n" \
|
||||
" .align 3\n" \
|
||||
" .previous");
|
||||
|
||||
/* If we have the capability create headers for efficient EH lookup.
|
||||
As of Jan 2002, only glibc 2.2.4 can actually make use of this, but
|
||||
I imagine that other systems will catch up. In the meantime, it
|
||||
doesn't harm to make sure that the data exists to be used later. */
|
||||
#if defined(HAVE_LD_EH_FRAME_HDR)
|
||||
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
|
||||
#endif
|
@ -1,133 +0,0 @@
|
||||
/* Definitions for DEC Alpha/AXP running FreeBSD using the ELF format
|
||||
Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc.
|
||||
Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#undef SUBTARGET_EXTRA_SPECS
|
||||
#define SUBTARGET_EXTRA_SPECS \
|
||||
{ "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER }
|
||||
|
||||
/* Provide a FBSD_TARGET_CPU_CPP_BUILTINS and CPP_SPEC appropriate for
|
||||
FreeBSD/alpha. Besides the dealing with
|
||||
the GCC option `-posix', and PIC issues as on all FreeBSD platforms, we must
|
||||
deal with the Alpha's FP issues. */
|
||||
|
||||
#undef FBSD_TARGET_CPU_CPP_BUILTINS
|
||||
#define FBSD_TARGET_CPU_CPP_BUILTINS() \
|
||||
do \
|
||||
{ \
|
||||
builtin_define ("__LP64__"); \
|
||||
if (flag_pic) \
|
||||
{ \
|
||||
builtin_define ("__PIC__"); \
|
||||
builtin_define ("__pic__"); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#undef CPP_SPEC
|
||||
#define CPP_SPEC "%(cpp_subtarget) %{posix:-D_POSIX_SOURCE}"
|
||||
|
||||
#define LINK_SPEC "%{G*} %{relax:-relax} \
|
||||
%{p:%nconsider using `-pg' instead of `-p' with gprof(1)} \
|
||||
%{Wl,*:%*} \
|
||||
%{assert*} %{R*} %{rpath*} %{defsym*} \
|
||||
%{shared:-Bshareable %{h*} %{soname*}} \
|
||||
%{!shared: \
|
||||
%{!static: \
|
||||
%{rdynamic:-export-dynamic} \
|
||||
%{!dynamic-linker:-dynamic-linker %(fbsd_dynamic_linker) }} \
|
||||
%{static:-Bstatic}} \
|
||||
%{symbolic:-Bsymbolic}"
|
||||
|
||||
/* Reset our STARTFILE_SPEC because of a moronic pigheaded
|
||||
Linuxism(glibc'ism) that was added to alpha/elf.h. */
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC FBSD_STARTFILE_SPEC
|
||||
|
||||
|
||||
/************************[ Target stuff ]***********************************/
|
||||
|
||||
/* Define the actual types of some ANSI-mandated types.
|
||||
Needs to agree with <machine/ansi.h>. GCC defaults come from c-decl.c,
|
||||
c-common.c, and config/<arch>/<arch>.h. */
|
||||
|
||||
/* alpha.h gets this wrong for FreeBSD. We use the GCC defaults instead. */
|
||||
#undef WCHAR_TYPE
|
||||
|
||||
#undef WCHAR_TYPE_SIZE
|
||||
#define WCHAR_TYPE_SIZE 32
|
||||
|
||||
/* Handle cross-compilation on 32-bits machines (such as i386) for 64-bits
|
||||
machines (Alpha in this case). */
|
||||
|
||||
#if defined(__i386__)
|
||||
#undef HOST_BITS_PER_LONG
|
||||
#define HOST_BITS_PER_LONG 32
|
||||
#undef HOST_WIDE_INT
|
||||
#define HOST_WIDE_INT long long
|
||||
#undef HOST_BITS_PER_WIDE_INT
|
||||
#define HOST_BITS_PER_WIDE_INT 64
|
||||
#endif
|
||||
|
||||
/* This is the pseudo-op used to generate a 64-bit word of data with a
|
||||
specific value in some section. */
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (FreeBSD/Alpha ELF)");
|
||||
|
||||
#define TARGET_ELF 1
|
||||
|
||||
#undef OBJECT_FORMAT_COFF
|
||||
#undef EXTENDED_COFF
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS)
|
||||
|
||||
#undef HAS_INIT_SECTION
|
||||
|
||||
/* Show that we need a GP when profiling. */
|
||||
#undef TARGET_PROFILING_NEEDS_GP
|
||||
#define TARGET_PROFILING_NEEDS_GP 1
|
||||
|
||||
/* We always use gas here, so we don't worry about ECOFF assembler problems. */
|
||||
#undef TARGET_GAS
|
||||
#define TARGET_GAS 1
|
||||
|
||||
|
||||
/************************[ Assembler stuff ]********************************/
|
||||
|
||||
|
||||
|
||||
/************************[ Debugger stuff ]*********************************/
|
||||
|
||||
/* This is the char to use for continuation (in case we need to turn
|
||||
continuation back on). */
|
||||
|
||||
#undef DBX_CONTIN_CHAR
|
||||
#define DBX_CONTIN_CHAR '?'
|
||||
|
||||
/* Don't default to pcc-struct-return, we want to retain compatibility with
|
||||
older FreeBSD releases AND pcc-struct-return may not be reentrant. */
|
||||
|
||||
#undef DEFAULT_PCC_STRUCT_RETURN
|
||||
#define DEFAULT_PCC_STRUCT_RETURN 0
|
@ -1,634 +0,0 @@
|
||||
/* CPP Library.
|
||||
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Per Bothner, 1994-95.
|
||||
Based on CCCP program by Paul Rubin, June 1986
|
||||
Adapted to ANSI C, Richard Stallman, Jan 1987
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "cpplib.h"
|
||||
#include "cpphash.h"
|
||||
#include "mkdeps.h"
|
||||
|
||||
static void init_library (void);
|
||||
static void mark_named_operators (cpp_reader *);
|
||||
static void read_original_filename (cpp_reader *);
|
||||
static void read_original_directory (cpp_reader *);
|
||||
static void post_options (cpp_reader *);
|
||||
|
||||
/* If we have designated initializers (GCC >2.7) these tables can be
|
||||
initialized, constant data. Otherwise, they have to be filled in at
|
||||
runtime. */
|
||||
#if HAVE_DESIGNATED_INITIALIZERS
|
||||
|
||||
#define init_trigraph_map() /* Nothing. */
|
||||
#define TRIGRAPH_MAP \
|
||||
__extension__ const uchar _cpp_trigraph_map[UCHAR_MAX + 1] = {
|
||||
|
||||
#define END };
|
||||
#define s(p, v) [p] = v,
|
||||
|
||||
#else
|
||||
|
||||
#define TRIGRAPH_MAP uchar _cpp_trigraph_map[UCHAR_MAX + 1] = { 0 }; \
|
||||
static void init_trigraph_map (void) { \
|
||||
unsigned char *x = _cpp_trigraph_map;
|
||||
|
||||
#define END }
|
||||
#define s(p, v) x[p] = v;
|
||||
|
||||
#endif
|
||||
|
||||
TRIGRAPH_MAP
|
||||
s('=', '#') s(')', ']') s('!', '|')
|
||||
s('(', '[') s('\'', '^') s('>', '}')
|
||||
s('/', '\\') s('<', '{') s('-', '~')
|
||||
END
|
||||
|
||||
#undef s
|
||||
#undef END
|
||||
#undef TRIGRAPH_MAP
|
||||
|
||||
/* A set of booleans indicating what CPP features each source language
|
||||
requires. */
|
||||
struct lang_flags
|
||||
{
|
||||
char c99;
|
||||
char cplusplus;
|
||||
char extended_numbers;
|
||||
char std;
|
||||
char cplusplus_comments;
|
||||
char digraphs;
|
||||
};
|
||||
|
||||
static const struct lang_flags lang_defaults[] =
|
||||
{ /* c99 c++ xnum std // digr */
|
||||
/* GNUC89 */ { 0, 0, 1, 0, 1, 1 },
|
||||
/* GNUC99 */ { 1, 0, 1, 0, 1, 1 },
|
||||
/* STDC89 */ { 0, 0, 0, 1, 0, 0 },
|
||||
/* STDC94 */ { 0, 0, 0, 1, 0, 1 },
|
||||
/* STDC99 */ { 1, 0, 1, 1, 1, 1 },
|
||||
/* GNUCXX */ { 0, 1, 1, 0, 1, 1 },
|
||||
/* CXX98 */ { 0, 1, 1, 1, 1, 1 },
|
||||
/* ASM */ { 0, 0, 1, 0, 1, 0 }
|
||||
};
|
||||
|
||||
/* Sets internal flags correctly for a given language. */
|
||||
void
|
||||
cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
|
||||
{
|
||||
const struct lang_flags *l = &lang_defaults[(int) lang];
|
||||
|
||||
CPP_OPTION (pfile, lang) = lang;
|
||||
|
||||
CPP_OPTION (pfile, c99) = l->c99;
|
||||
CPP_OPTION (pfile, cplusplus) = l->cplusplus;
|
||||
CPP_OPTION (pfile, extended_numbers) = l->extended_numbers;
|
||||
CPP_OPTION (pfile, std) = l->std;
|
||||
CPP_OPTION (pfile, trigraphs) = l->std;
|
||||
CPP_OPTION (pfile, cplusplus_comments) = l->cplusplus_comments;
|
||||
CPP_OPTION (pfile, digraphs) = l->digraphs;
|
||||
}
|
||||
|
||||
/* Initialize library global state. */
|
||||
static void
|
||||
init_library (void)
|
||||
{
|
||||
static int initialized = 0;
|
||||
|
||||
if (! initialized)
|
||||
{
|
||||
initialized = 1;
|
||||
|
||||
/* Set up the trigraph map. This doesn't need to do anything if
|
||||
we were compiled with a compiler that supports C99 designated
|
||||
initializers. */
|
||||
init_trigraph_map ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize a cpp_reader structure. */
|
||||
cpp_reader *
|
||||
cpp_create_reader (enum c_lang lang, hash_table *table)
|
||||
{
|
||||
cpp_reader *pfile;
|
||||
|
||||
/* Initialize this instance of the library if it hasn't been already. */
|
||||
init_library ();
|
||||
|
||||
pfile = xcalloc (1, sizeof (cpp_reader));
|
||||
|
||||
cpp_set_lang (pfile, lang);
|
||||
CPP_OPTION (pfile, warn_multichar) = 1;
|
||||
CPP_OPTION (pfile, discard_comments) = 1;
|
||||
CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
|
||||
CPP_OPTION (pfile, show_column) = 1;
|
||||
CPP_OPTION (pfile, tabstop) = 8;
|
||||
CPP_OPTION (pfile, operator_names) = 1;
|
||||
CPP_OPTION (pfile, warn_trigraphs) = 2;
|
||||
CPP_OPTION (pfile, warn_endif_labels) = 1;
|
||||
CPP_OPTION (pfile, warn_deprecated) = 1;
|
||||
CPP_OPTION (pfile, warn_long_long) = !CPP_OPTION (pfile, c99);
|
||||
CPP_OPTION (pfile, dollars_in_ident) = 1;
|
||||
CPP_OPTION (pfile, warn_dollars) = 1;
|
||||
|
||||
/* Default CPP arithmetic to something sensible for the host for the
|
||||
benefit of dumb users like fix-header. */
|
||||
CPP_OPTION (pfile, precision) = CHAR_BIT * sizeof (long);
|
||||
CPP_OPTION (pfile, char_precision) = CHAR_BIT;
|
||||
CPP_OPTION (pfile, wchar_precision) = CHAR_BIT * sizeof (int);
|
||||
CPP_OPTION (pfile, int_precision) = CHAR_BIT * sizeof (int);
|
||||
CPP_OPTION (pfile, unsigned_char) = 0;
|
||||
CPP_OPTION (pfile, unsigned_wchar) = 1;
|
||||
CPP_OPTION (pfile, bytes_big_endian) = 1; /* does not matter */
|
||||
|
||||
/* Default to locale/UTF-8. */
|
||||
CPP_OPTION (pfile, narrow_charset) = _cpp_default_encoding ();
|
||||
CPP_OPTION (pfile, wide_charset) = 0;
|
||||
CPP_OPTION (pfile, input_charset) = _cpp_default_encoding ();
|
||||
|
||||
/* A fake empty "directory" used as the starting point for files
|
||||
looked up without a search path. Name cannot be '/' because we
|
||||
don't want to prepend anything at all to filenames using it. All
|
||||
other entries are correct zero-initialized. */
|
||||
pfile->no_search_path.name = (char *) "";
|
||||
|
||||
/* Initialize the line map. Start at logical line 1, so we can use
|
||||
a line number of zero for special states. */
|
||||
linemap_init (&pfile->line_maps);
|
||||
pfile->line = 1;
|
||||
|
||||
/* Initialize lexer state. */
|
||||
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
|
||||
|
||||
/* Set up static tokens. */
|
||||
pfile->avoid_paste.type = CPP_PADDING;
|
||||
pfile->avoid_paste.val.source = NULL;
|
||||
pfile->eof.type = CPP_EOF;
|
||||
pfile->eof.flags = 0;
|
||||
|
||||
/* Create a token buffer for the lexer. */
|
||||
_cpp_init_tokenrun (&pfile->base_run, 250);
|
||||
pfile->cur_run = &pfile->base_run;
|
||||
pfile->cur_token = pfile->base_run.base;
|
||||
|
||||
/* Initialize the base context. */
|
||||
pfile->context = &pfile->base_context;
|
||||
pfile->base_context.macro = 0;
|
||||
pfile->base_context.prev = pfile->base_context.next = 0;
|
||||
|
||||
/* Aligned and unaligned storage. */
|
||||
pfile->a_buff = _cpp_get_buff (pfile, 0);
|
||||
pfile->u_buff = _cpp_get_buff (pfile, 0);
|
||||
|
||||
/* The expression parser stack. */
|
||||
_cpp_expand_op_stack (pfile);
|
||||
|
||||
/* Initialize the buffer obstack. */
|
||||
_obstack_begin (&pfile->buffer_ob, 0, 0,
|
||||
(void *(*) (long)) xmalloc,
|
||||
(void (*) (void *)) free);
|
||||
|
||||
_cpp_init_files (pfile);
|
||||
|
||||
_cpp_init_hashtable (pfile, table);
|
||||
|
||||
return pfile;
|
||||
}
|
||||
|
||||
/* Free resources used by PFILE. Accessing PFILE after this function
|
||||
returns leads to undefined behavior. Returns the error count. */
|
||||
void
|
||||
cpp_destroy (cpp_reader *pfile)
|
||||
{
|
||||
cpp_context *context, *contextn;
|
||||
tokenrun *run, *runn;
|
||||
|
||||
free (pfile->op_stack);
|
||||
|
||||
while (CPP_BUFFER (pfile) != NULL)
|
||||
_cpp_pop_buffer (pfile);
|
||||
|
||||
if (pfile->out.base)
|
||||
free (pfile->out.base);
|
||||
|
||||
if (pfile->macro_buffer)
|
||||
{
|
||||
free (pfile->macro_buffer);
|
||||
pfile->macro_buffer = NULL;
|
||||
pfile->macro_buffer_len = 0;
|
||||
}
|
||||
|
||||
if (pfile->deps)
|
||||
deps_free (pfile->deps);
|
||||
obstack_free (&pfile->buffer_ob, 0);
|
||||
|
||||
_cpp_destroy_hashtable (pfile);
|
||||
_cpp_cleanup_files (pfile);
|
||||
_cpp_destroy_iconv (pfile);
|
||||
|
||||
_cpp_free_buff (pfile->a_buff);
|
||||
_cpp_free_buff (pfile->u_buff);
|
||||
_cpp_free_buff (pfile->free_buffs);
|
||||
|
||||
for (run = &pfile->base_run; run; run = runn)
|
||||
{
|
||||
runn = run->next;
|
||||
free (run->base);
|
||||
if (run != &pfile->base_run)
|
||||
free (run);
|
||||
}
|
||||
|
||||
for (context = pfile->base_context.next; context; context = contextn)
|
||||
{
|
||||
contextn = context->next;
|
||||
free (context);
|
||||
}
|
||||
|
||||
linemap_free (&pfile->line_maps);
|
||||
free (pfile);
|
||||
}
|
||||
|
||||
/* This structure defines one built-in identifier. A node will be
|
||||
entered in the hash table under the name NAME, with value VALUE.
|
||||
|
||||
There are two tables of these. builtin_array holds all the
|
||||
"builtin" macros: these are handled by builtin_macro() in
|
||||
cppmacro.c. Builtin is somewhat of a misnomer -- the property of
|
||||
interest is that these macros require special code to compute their
|
||||
expansions. The value is a "builtin_type" enumerator.
|
||||
|
||||
operator_array holds the C++ named operators. These are keywords
|
||||
which act as aliases for punctuators. In C++, they cannot be
|
||||
altered through #define, and #if recognizes them as operators. In
|
||||
C, these are not entered into the hash table at all (but see
|
||||
<iso646.h>). The value is a token-type enumerator. */
|
||||
struct builtin
|
||||
{
|
||||
const uchar *name;
|
||||
unsigned short len;
|
||||
unsigned short value;
|
||||
};
|
||||
|
||||
#define B(n, t) { DSC(n), t }
|
||||
static const struct builtin builtin_array[] =
|
||||
{
|
||||
B("__TIME__", BT_TIME),
|
||||
B("__DATE__", BT_DATE),
|
||||
B("__FILE__", BT_FILE),
|
||||
B("__BASE_FILE__", BT_BASE_FILE),
|
||||
B("__LINE__", BT_SPECLINE),
|
||||
B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL),
|
||||
/* Keep builtins not used for -traditional-cpp at the end, and
|
||||
update init_builtins() if any more are added. */
|
||||
B("_Pragma", BT_PRAGMA),
|
||||
B("__STDC__", BT_STDC),
|
||||
};
|
||||
|
||||
static const struct builtin operator_array[] =
|
||||
{
|
||||
B("and", CPP_AND_AND),
|
||||
B("and_eq", CPP_AND_EQ),
|
||||
B("bitand", CPP_AND),
|
||||
B("bitor", CPP_OR),
|
||||
B("compl", CPP_COMPL),
|
||||
B("not", CPP_NOT),
|
||||
B("not_eq", CPP_NOT_EQ),
|
||||
B("or", CPP_OR_OR),
|
||||
B("or_eq", CPP_OR_EQ),
|
||||
B("xor", CPP_XOR),
|
||||
B("xor_eq", CPP_XOR_EQ)
|
||||
};
|
||||
#undef B
|
||||
|
||||
/* Mark the C++ named operators in the hash table. */
|
||||
static void
|
||||
mark_named_operators (cpp_reader *pfile)
|
||||
{
|
||||
const struct builtin *b;
|
||||
|
||||
for (b = operator_array;
|
||||
b < (operator_array + ARRAY_SIZE (operator_array));
|
||||
b++)
|
||||
{
|
||||
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
|
||||
hp->flags |= NODE_OPERATOR;
|
||||
hp->is_directive = 0;
|
||||
hp->directive_index = b->value;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the builtins table above and enter them, and language-specific
|
||||
macros, into the hash table. HOSTED is true if this is a hosted
|
||||
environment. */
|
||||
void
|
||||
cpp_init_builtins (cpp_reader *pfile, int hosted)
|
||||
{
|
||||
const struct builtin *b;
|
||||
size_t n = ARRAY_SIZE (builtin_array);
|
||||
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
n -= 2;
|
||||
|
||||
for(b = builtin_array; b < builtin_array + n; b++)
|
||||
{
|
||||
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
|
||||
hp->type = NT_MACRO;
|
||||
hp->flags |= NODE_BUILTIN | NODE_WARN;
|
||||
hp->value.builtin = b->value;
|
||||
}
|
||||
|
||||
if (CPP_OPTION (pfile, cplusplus))
|
||||
_cpp_define_builtin (pfile, "__cplusplus 1");
|
||||
else if (CPP_OPTION (pfile, lang) == CLK_ASM)
|
||||
_cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
|
||||
else if (CPP_OPTION (pfile, lang) == CLK_STDC94)
|
||||
_cpp_define_builtin (pfile, "__STDC_VERSION__ 199409L");
|
||||
else if (CPP_OPTION (pfile, c99))
|
||||
_cpp_define_builtin (pfile, "__STDC_VERSION__ 199901L");
|
||||
|
||||
if (hosted)
|
||||
_cpp_define_builtin (pfile, "__STDC_HOSTED__ 1");
|
||||
else
|
||||
_cpp_define_builtin (pfile, "__STDC_HOSTED__ 0");
|
||||
|
||||
if (CPP_OPTION (pfile, objc))
|
||||
_cpp_define_builtin (pfile, "__OBJC__ 1");
|
||||
}
|
||||
|
||||
/* Sanity-checks are dependent on command-line options, so it is
|
||||
called as a subroutine of cpp_read_main_file (). */
|
||||
#if ENABLE_CHECKING
|
||||
static void sanity_checks (cpp_reader *);
|
||||
static void sanity_checks (cpp_reader *pfile)
|
||||
{
|
||||
cppchar_t test = 0;
|
||||
size_t max_precision = 2 * CHAR_BIT * sizeof (cpp_num_part);
|
||||
|
||||
/* Sanity checks for assumptions about CPP arithmetic and target
|
||||
type precisions made by cpplib. */
|
||||
test--;
|
||||
if (test < 1)
|
||||
cpp_error (pfile, CPP_DL_ICE, "cppchar_t must be an unsigned type");
|
||||
|
||||
if (CPP_OPTION (pfile, precision) > max_precision)
|
||||
cpp_error (pfile, CPP_DL_ICE,
|
||||
"preprocessor arithmetic has maximum precision of %lu bits;"
|
||||
" target requires %lu bits",
|
||||
(unsigned long) max_precision,
|
||||
(unsigned long) CPP_OPTION (pfile, precision));
|
||||
|
||||
if (CPP_OPTION (pfile, precision) < CPP_OPTION (pfile, int_precision))
|
||||
cpp_error (pfile, CPP_DL_ICE,
|
||||
"CPP arithmetic must be at least as precise as a target int");
|
||||
|
||||
if (CPP_OPTION (pfile, char_precision) < 8)
|
||||
cpp_error (pfile, CPP_DL_ICE, "target char is less than 8 bits wide");
|
||||
|
||||
if (CPP_OPTION (pfile, wchar_precision) < CPP_OPTION (pfile, char_precision))
|
||||
cpp_error (pfile, CPP_DL_ICE,
|
||||
"target wchar_t is narrower than target char");
|
||||
|
||||
if (CPP_OPTION (pfile, int_precision) < CPP_OPTION (pfile, char_precision))
|
||||
cpp_error (pfile, CPP_DL_ICE,
|
||||
"target int is narrower than target char");
|
||||
|
||||
/* This is assumed in eval_token() and could be fixed if necessary. */
|
||||
if (sizeof (cppchar_t) > sizeof (cpp_num_part))
|
||||
cpp_error (pfile, CPP_DL_ICE,
|
||||
"CPP half-integer narrower than CPP character");
|
||||
|
||||
if (CPP_OPTION (pfile, wchar_precision) > BITS_PER_CPPCHAR_T)
|
||||
cpp_error (pfile, CPP_DL_ICE,
|
||||
"CPP on this host cannot handle wide character constants over"
|
||||
" %lu bits, but the target requires %lu bits",
|
||||
(unsigned long) BITS_PER_CPPCHAR_T,
|
||||
(unsigned long) CPP_OPTION (pfile, wchar_precision));
|
||||
}
|
||||
#else
|
||||
# define sanity_checks(PFILE)
|
||||
#endif
|
||||
|
||||
/* Add a dependency target. Can be called any number of times before
|
||||
cpp_read_main_file(). If no targets have been added before
|
||||
cpp_read_main_file(), then the default target is used. */
|
||||
void
|
||||
cpp_add_dependency_target (cpp_reader *pfile, const char *target, int quote)
|
||||
{
|
||||
if (!pfile->deps)
|
||||
pfile->deps = deps_init ();
|
||||
|
||||
deps_add_target (pfile->deps, target, quote);
|
||||
}
|
||||
|
||||
/* This is called after options have been parsed, and partially
|
||||
processed. */
|
||||
void
|
||||
cpp_post_options (cpp_reader *pfile)
|
||||
{
|
||||
sanity_checks (pfile);
|
||||
|
||||
post_options (pfile);
|
||||
|
||||
/* Mark named operators before handling command line macros. */
|
||||
if (CPP_OPTION (pfile, cplusplus) && CPP_OPTION (pfile, operator_names))
|
||||
mark_named_operators (pfile);
|
||||
}
|
||||
|
||||
/* Setup for processing input from the file named FNAME, or stdin if
|
||||
it is the empty string. Return the original filename
|
||||
on success (e.g. foo.i->foo.c), or NULL on failure. */
|
||||
const char *
|
||||
cpp_read_main_file (cpp_reader *pfile, const char *fname)
|
||||
{
|
||||
if (CPP_OPTION (pfile, deps.style) != DEPS_NONE)
|
||||
{
|
||||
if (!pfile->deps)
|
||||
pfile->deps = deps_init ();
|
||||
|
||||
/* Set the default target (if there is none already). */
|
||||
deps_add_default_target (pfile->deps, fname);
|
||||
}
|
||||
|
||||
pfile->main_file
|
||||
= _cpp_find_file (pfile, fname, &pfile->no_search_path, false, 0);
|
||||
if (_cpp_find_failed (pfile->main_file))
|
||||
return NULL;
|
||||
|
||||
_cpp_stack_file (pfile, pfile->main_file, false);
|
||||
|
||||
/* For foo.i, read the original filename foo.c now, for the benefit
|
||||
of the front ends. */
|
||||
if (CPP_OPTION (pfile, preprocessed))
|
||||
{
|
||||
read_original_filename (pfile);
|
||||
if (!pfile->map)
|
||||
return NULL;
|
||||
fname = pfile->map->to_file;
|
||||
}
|
||||
return fname;
|
||||
}
|
||||
|
||||
/* For preprocessed files, if the first tokens are of the form # NUM.
|
||||
handle the directive so we know the original file name. This will
|
||||
generate file_change callbacks, which the front ends must handle
|
||||
appropriately given their state of initialization. */
|
||||
static void
|
||||
read_original_filename (cpp_reader *pfile)
|
||||
{
|
||||
const cpp_token *token, *token1;
|
||||
|
||||
/* Lex ahead; if the first tokens are of the form # NUM, then
|
||||
process the directive, otherwise back up. */
|
||||
token = _cpp_lex_direct (pfile);
|
||||
if (token->type == CPP_HASH)
|
||||
{
|
||||
pfile->state.in_directive = 1;
|
||||
token1 = _cpp_lex_direct (pfile);
|
||||
_cpp_backup_tokens (pfile, 1);
|
||||
pfile->state.in_directive = 0;
|
||||
|
||||
/* If it's a #line directive, handle it. */
|
||||
if (token1->type == CPP_NUMBER)
|
||||
{
|
||||
_cpp_handle_directive (pfile, token->flags & PREV_WHITE);
|
||||
read_original_directory (pfile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Backup as if nothing happened. */
|
||||
_cpp_backup_tokens (pfile, 1);
|
||||
}
|
||||
|
||||
/* For preprocessed files, if the tokens following the first filename
|
||||
line is of the form # <line> "/path/name//", handle the
|
||||
directive so we know the original current directory. */
|
||||
static void
|
||||
read_original_directory (cpp_reader *pfile)
|
||||
{
|
||||
const cpp_token *hash, *token;
|
||||
|
||||
/* Lex ahead; if the first tokens are of the form # NUM, then
|
||||
process the directive, otherwise back up. */
|
||||
hash = _cpp_lex_direct (pfile);
|
||||
if (hash->type != CPP_HASH)
|
||||
{
|
||||
_cpp_backup_tokens (pfile, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
token = _cpp_lex_direct (pfile);
|
||||
|
||||
if (token->type != CPP_NUMBER)
|
||||
{
|
||||
_cpp_backup_tokens (pfile, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
token = _cpp_lex_direct (pfile);
|
||||
|
||||
if (token->type != CPP_STRING
|
||||
|| ! (token->val.str.len >= 5
|
||||
&& token->val.str.text[token->val.str.len-2] == '/'
|
||||
&& token->val.str.text[token->val.str.len-3] == '/'))
|
||||
{
|
||||
_cpp_backup_tokens (pfile, 3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pfile->cb.dir_change)
|
||||
{
|
||||
char *debugdir = alloca (token->val.str.len - 3);
|
||||
|
||||
memcpy (debugdir, (const char *) token->val.str.text + 1,
|
||||
token->val.str.len - 4);
|
||||
debugdir[token->val.str.len - 4] = '\0';
|
||||
|
||||
pfile->cb.dir_change (pfile, debugdir);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is called at the end of preprocessing. It pops the last
|
||||
buffer and writes dependency output, and returns the number of
|
||||
errors.
|
||||
|
||||
Maybe it should also reset state, such that you could call
|
||||
cpp_start_read with a new filename to restart processing. */
|
||||
int
|
||||
cpp_finish (cpp_reader *pfile, FILE *deps_stream)
|
||||
{
|
||||
/* Warn about unused macros before popping the final buffer. */
|
||||
if (CPP_OPTION (pfile, warn_unused_macros))
|
||||
cpp_forall_identifiers (pfile, _cpp_warn_if_unused_macro, NULL);
|
||||
|
||||
/* cpplex.c leaves the final buffer on the stack. This it so that
|
||||
it returns an unending stream of CPP_EOFs to the client. If we
|
||||
popped the buffer, we'd dereference a NULL buffer pointer and
|
||||
segfault. It's nice to allow the client to do worry-free excess
|
||||
cpp_get_token calls. */
|
||||
while (pfile->buffer)
|
||||
_cpp_pop_buffer (pfile);
|
||||
|
||||
/* Don't write the deps file if there are errors. */
|
||||
if (CPP_OPTION (pfile, deps.style) != DEPS_NONE
|
||||
&& deps_stream && pfile->errors == 0)
|
||||
{
|
||||
deps_write (pfile->deps, deps_stream, 72);
|
||||
|
||||
if (CPP_OPTION (pfile, deps.phony_targets))
|
||||
deps_phony_targets (pfile->deps, deps_stream);
|
||||
}
|
||||
|
||||
/* Report on headers that could use multiple include guards. */
|
||||
if (CPP_OPTION (pfile, print_include_names))
|
||||
_cpp_report_missing_guards (pfile);
|
||||
|
||||
return pfile->errors;
|
||||
}
|
||||
|
||||
static void
|
||||
post_options (cpp_reader *pfile)
|
||||
{
|
||||
/* -Wtraditional is not useful in C++ mode. */
|
||||
if (CPP_OPTION (pfile, cplusplus))
|
||||
CPP_OPTION (pfile, warn_traditional) = 0;
|
||||
|
||||
/* Permanently disable macro expansion if we are rescanning
|
||||
preprocessed text. Read preprocesed source in ISO mode. */
|
||||
if (CPP_OPTION (pfile, preprocessed))
|
||||
{
|
||||
pfile->state.prevent_expansion = 1;
|
||||
CPP_OPTION (pfile, traditional) = 0;
|
||||
}
|
||||
|
||||
if (CPP_OPTION (pfile, warn_trigraphs) == 2)
|
||||
CPP_OPTION (pfile, warn_trigraphs) = !CPP_OPTION (pfile, trigraphs);
|
||||
|
||||
if (CPP_OPTION (pfile, traditional))
|
||||
{
|
||||
CPP_OPTION (pfile, cplusplus_comments) = 0;
|
||||
|
||||
/* Traditional CPP does not accurately track column information. */
|
||||
CPP_OPTION (pfile, show_column) = 0;
|
||||
CPP_OPTION (pfile, trigraphs) = 0;
|
||||
CPP_OPTION (pfile, warn_trigraphs) = 0;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,568 +0,0 @@
|
||||
/* Specific flags and argument handling of the Fortran front-end.
|
||||
Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* This file contains a filter for the main `gcc' driver, which is
|
||||
replicated for the `g77' driver by adding this filter. The purpose
|
||||
of this filter is to be basically identical to gcc (in that
|
||||
it faithfully passes all of the original arguments to gcc) but,
|
||||
unless explicitly overridden by the user in certain ways, ensure
|
||||
that the needs of the language supported by this wrapper are met.
|
||||
|
||||
For GNU Fortran (g77), we do the following to the argument list
|
||||
before passing it to `gcc':
|
||||
|
||||
1. Make sure `-lg2c -lm' is at the end of the list.
|
||||
|
||||
2. Make sure each time `-lg2c' or `-lm' is seen, it forms
|
||||
part of the series `-lg2c -lm'.
|
||||
|
||||
#1 and #2 are not done if `-nostdlib' or any option that disables
|
||||
the linking phase is present, or if `-xfoo' is in effect. Note that
|
||||
a lack of source files or -l options disables linking.
|
||||
|
||||
This program was originally made out of gcc/cp/g++spec.c, but the
|
||||
way it builds the new argument list was rewritten so it is much
|
||||
easier to maintain, improve the way it decides to add or not add
|
||||
extra arguments, etc. And several improvements were made in the
|
||||
handling of arguments, primarily to make it more consistent with
|
||||
`gcc' itself. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "gcc.h"
|
||||
#include "intl.h"
|
||||
|
||||
#ifndef MATH_LIBRARY
|
||||
#define MATH_LIBRARY "-lm"
|
||||
#endif
|
||||
#ifndef MATH_LIBRARY_PROFILE
|
||||
#define MATH_LIBRARY_PROFILE "-lm"
|
||||
#endif
|
||||
|
||||
#ifndef FORTRAN_INIT
|
||||
#define FORTRAN_INIT "-lfrtbegin"
|
||||
#endif
|
||||
#ifndef FORTRAN_INIT_PROFILE
|
||||
#define FORTRAN_INIT_PROFILE "-lfrtbegin"
|
||||
#endif
|
||||
|
||||
#ifndef FORTRAN_LIBRARY
|
||||
#define FORTRAN_LIBRARY "-lg2c"
|
||||
#endif
|
||||
#ifndef FORTRAN_LIBRARY_PROFILE
|
||||
#define FORTRAN_LIBRARY_PROFILE "-lg2c"
|
||||
#endif
|
||||
|
||||
/* Options this driver needs to recognize, not just know how to
|
||||
skip over. */
|
||||
typedef enum
|
||||
{
|
||||
OPTION_b, /* Aka --prefix. */
|
||||
OPTION_B, /* Aka --target. */
|
||||
OPTION_c, /* Aka --compile. */
|
||||
OPTION_driver, /* Wrapper-specific option. */
|
||||
OPTION_E, /* Aka --preprocess. */
|
||||
OPTION_help, /* --help. */
|
||||
OPTION_i, /* -imacros, -include, -include-*. */
|
||||
OPTION_l,
|
||||
OPTION_L, /* Aka --library-directory. */
|
||||
OPTION_M, /* Aka --dependencies. */
|
||||
OPTION_MM, /* Aka --user-dependencies. */
|
||||
OPTION_nostdlib, /* Aka --no-standard-libraries, or
|
||||
-nodefaultlibs. */
|
||||
OPTION_o, /* Aka --output. */
|
||||
OPTION_p, /* Aka --profile. */
|
||||
OPTION_S, /* Aka --assemble. */
|
||||
OPTION_syntax_only, /* -fsyntax-only. */
|
||||
OPTION_v, /* Aka --verbose. */
|
||||
OPTION_version, /* --version. */
|
||||
OPTION_V, /* Aka --use-version. */
|
||||
OPTION_x, /* Aka --language. */
|
||||
OPTION_ /* Unrecognized or unimportant. */
|
||||
} Option;
|
||||
|
||||
/* The original argument list and related info is copied here. */
|
||||
static int g77_xargc;
|
||||
static const char *const *g77_xargv;
|
||||
static void lookup_option (Option *, int *, const char **, const char *);
|
||||
static void append_arg (const char *);
|
||||
|
||||
/* The new argument list will be built here. */
|
||||
static int g77_newargc;
|
||||
static const char **g77_newargv;
|
||||
|
||||
#ifndef SWITCH_TAKES_ARG
|
||||
#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
|
||||
#endif
|
||||
|
||||
#ifndef WORD_SWITCH_TAKES_ARG
|
||||
#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
|
||||
#endif
|
||||
|
||||
/* Assumes text[0] == '-'. Returns number of argv items that belong to
|
||||
(and follow) this one, an option id for options important to the
|
||||
caller, and a pointer to the first char of the arg, if embedded (else
|
||||
returns NULL, meaning no arg or it's the next argv).
|
||||
|
||||
Note that this also assumes gcc.c's pass converting long options
|
||||
to short ones, where available, has already been run. */
|
||||
|
||||
static void
|
||||
lookup_option (Option *xopt, int *xskip, const char **xarg, const char *text)
|
||||
{
|
||||
Option opt = OPTION_;
|
||||
int skip;
|
||||
const char *arg = NULL;
|
||||
|
||||
if ((skip = SWITCH_TAKES_ARG (text[1])))
|
||||
skip -= (text[2] != '\0'); /* See gcc.c. */
|
||||
|
||||
if (text[1] == 'B')
|
||||
opt = OPTION_B, skip = (text[2] == '\0'), arg = text + 2;
|
||||
else if (text[1] == 'b')
|
||||
opt = OPTION_b, skip = (text[2] == '\0'), arg = text + 2;
|
||||
else if ((text[1] == 'c') && (text[2] == '\0'))
|
||||
opt = OPTION_c, skip = 0;
|
||||
else if ((text[1] == 'E') && (text[2] == '\0'))
|
||||
opt = OPTION_E, skip = 0;
|
||||
else if (text[1] == 'i')
|
||||
opt = OPTION_i, skip = 0;
|
||||
else if (text[1] == 'l')
|
||||
opt = OPTION_l;
|
||||
else if (text[1] == 'L')
|
||||
opt = OPTION_L, arg = text + 2;
|
||||
else if (text[1] == 'o')
|
||||
opt = OPTION_o;
|
||||
else if ((text[1] == 'p') && (text[2] == '\0')
|
||||
|| (text[1] == 'p') && (text[2] == 'g') && (text[3] == '\0'))
|
||||
opt = OPTION_p;
|
||||
else if ((text[1] == 'S') && (text[2] == '\0'))
|
||||
opt = OPTION_S, skip = 0;
|
||||
else if (text[1] == 'V')
|
||||
opt = OPTION_V, skip = (text[2] == '\0');
|
||||
else if ((text[1] == 'v') && (text[2] == '\0'))
|
||||
opt = OPTION_v, skip = 0;
|
||||
else if (text[1] == 'x')
|
||||
opt = OPTION_x, arg = text + 2;
|
||||
else
|
||||
{
|
||||
if ((skip = WORD_SWITCH_TAKES_ARG (text + 1)) != 0) /* See gcc.c. */
|
||||
;
|
||||
else if (! strncmp (text, "-fdriver", 8)) /* Really --driver!! */
|
||||
opt = OPTION_driver; /* Never mind arg, this is unsupported. */
|
||||
else if (! strcmp (text, "-fhelp")) /* Really --help!! */
|
||||
opt = OPTION_help;
|
||||
else if (! strcmp (text, "-M"))
|
||||
opt = OPTION_M;
|
||||
else if (! strcmp (text, "-MM"))
|
||||
opt = OPTION_MM;
|
||||
else if (! strcmp (text, "-nostdlib")
|
||||
|| ! strcmp (text, "-nodefaultlibs"))
|
||||
opt = OPTION_nostdlib;
|
||||
else if (! strcmp (text, "-fsyntax-only"))
|
||||
opt = OPTION_syntax_only;
|
||||
else if (! strcmp (text, "-dumpversion"))
|
||||
opt = OPTION_version;
|
||||
else if (! strcmp (text, "-fversion")) /* Really --version!! */
|
||||
opt = OPTION_version;
|
||||
else if (! strcmp (text, "-Xlinker")
|
||||
|| ! strcmp (text, "-specs"))
|
||||
skip = 1;
|
||||
else
|
||||
skip = 0;
|
||||
}
|
||||
|
||||
if (xopt != NULL)
|
||||
*xopt = opt;
|
||||
if (xskip != NULL)
|
||||
*xskip = skip;
|
||||
if (xarg != NULL)
|
||||
{
|
||||
if ((arg != NULL)
|
||||
&& (arg[0] == '\0'))
|
||||
*xarg = NULL;
|
||||
else
|
||||
*xarg = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/* Append another argument to the list being built. As long as it is
|
||||
identical to the corresponding arg in the original list, just increment
|
||||
the new arg count. Otherwise allocate a new list, etc. */
|
||||
|
||||
static void
|
||||
append_arg (const char *arg)
|
||||
{
|
||||
static int newargsize;
|
||||
|
||||
#if 0
|
||||
fprintf (stderr, "`%s'\n", arg);
|
||||
#endif
|
||||
|
||||
if (g77_newargv == g77_xargv
|
||||
&& g77_newargc < g77_xargc
|
||||
&& (arg == g77_xargv[g77_newargc]
|
||||
|| ! strcmp (arg, g77_xargv[g77_newargc])))
|
||||
{
|
||||
++g77_newargc;
|
||||
return; /* Nothing new here. */
|
||||
}
|
||||
|
||||
if (g77_newargv == g77_xargv)
|
||||
{ /* Make new arglist. */
|
||||
int i;
|
||||
|
||||
newargsize = (g77_xargc << 2) + 20; /* This should handle all. */
|
||||
g77_newargv = xmalloc (newargsize * sizeof (char *));
|
||||
|
||||
/* Copy what has been done so far. */
|
||||
for (i = 0; i < g77_newargc; ++i)
|
||||
g77_newargv[i] = g77_xargv[i];
|
||||
}
|
||||
|
||||
if (g77_newargc == newargsize)
|
||||
fatal ("overflowed output arg list for `%s'", arg);
|
||||
|
||||
g77_newargv[g77_newargc++] = arg;
|
||||
}
|
||||
|
||||
void
|
||||
lang_specific_driver (int *in_argc, const char *const **in_argv,
|
||||
int *in_added_libraries ATTRIBUTE_UNUSED)
|
||||
{
|
||||
int argc = *in_argc;
|
||||
const char *const *argv = *in_argv;
|
||||
int i;
|
||||
int verbose = 0;
|
||||
Option opt;
|
||||
int skip;
|
||||
const char *arg;
|
||||
|
||||
/* This will be NULL if we encounter a situation where we should not
|
||||
link in libf2c. */
|
||||
const char *library = FORTRAN_LIBRARY;
|
||||
|
||||
/* 0 => -xnone in effect.
|
||||
1 => -xfoo in effect. */
|
||||
int saw_speclang = 0;
|
||||
|
||||
/* 0 => initial/reset state
|
||||
1 => last arg was -l<library>
|
||||
2 => last two args were -l<library> -lm. */
|
||||
int saw_library = 0;
|
||||
|
||||
/* 0 => initial/reset state
|
||||
1 => FORTRAN_INIT linked in */
|
||||
int use_init = 0;
|
||||
/* By default, we throw on the math library if we have one. */
|
||||
int need_math = (MATH_LIBRARY[0] != '\0');
|
||||
|
||||
/* If non-zero, the user gave us the `-p' or `-pg' flag. */
|
||||
int saw_profile_flag = 0;
|
||||
|
||||
/* The number of input and output files in the incoming arg list. */
|
||||
int n_infiles = 0;
|
||||
int n_outfiles = 0;
|
||||
|
||||
#if 0
|
||||
fprintf (stderr, "Incoming:");
|
||||
for (i = 0; i < argc; i++)
|
||||
fprintf (stderr, " %s", argv[i]);
|
||||
fprintf (stderr, "\n");
|
||||
#endif
|
||||
|
||||
g77_xargc = argc;
|
||||
g77_xargv = argv;
|
||||
g77_newargc = 0;
|
||||
g77_newargv = (const char **) argv;
|
||||
|
||||
/* First pass through arglist.
|
||||
|
||||
If -nostdlib or a "turn-off-linking" option is anywhere in the
|
||||
command line, don't do any library-option processing (except
|
||||
relating to -x). Also, if -v is specified, but no other options
|
||||
that do anything special (allowing -V version, etc.), remember
|
||||
to add special stuff to make gcc command actually invoke all
|
||||
the different phases of the compilation process so all the version
|
||||
numbers can be seen.
|
||||
|
||||
Also, here is where all problems with missing arguments to options
|
||||
are caught. If this loop is exited normally, it means all options
|
||||
have the appropriate number of arguments as far as the rest of this
|
||||
program is concerned. */
|
||||
|
||||
for (i = 1; i < argc; ++i)
|
||||
{
|
||||
if ((argv[i][0] == '+') && (argv[i][1] == 'e'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((argv[i][0] != '-') || (argv[i][1] == '\0'))
|
||||
{
|
||||
++n_infiles;
|
||||
continue;
|
||||
}
|
||||
|
||||
lookup_option (&opt, &skip, NULL, argv[i]);
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case OPTION_nostdlib:
|
||||
case OPTION_c:
|
||||
case OPTION_S:
|
||||
case OPTION_syntax_only:
|
||||
case OPTION_E:
|
||||
case OPTION_M:
|
||||
case OPTION_MM:
|
||||
/* These options disable linking entirely or linking of the
|
||||
standard libraries. */
|
||||
library = 0;
|
||||
break;
|
||||
|
||||
case OPTION_l:
|
||||
++n_infiles;
|
||||
break;
|
||||
|
||||
case OPTION_o:
|
||||
++n_outfiles;
|
||||
break;
|
||||
|
||||
case OPTION_p:
|
||||
saw_profile_flag = 1;
|
||||
library = FORTRAN_LIBRARY_PROFILE;
|
||||
break;
|
||||
|
||||
case OPTION_v:
|
||||
verbose = 1;
|
||||
break;
|
||||
|
||||
case OPTION_b:
|
||||
case OPTION_B:
|
||||
case OPTION_L:
|
||||
case OPTION_i:
|
||||
case OPTION_V:
|
||||
/* These options are useful in conjunction with -v to get
|
||||
appropriate version info. */
|
||||
break;
|
||||
|
||||
case OPTION_version:
|
||||
printf ("GNU Fortran (GCC) %s\n", version_string);
|
||||
printf ("Copyright %s 2006 Free Software Foundation, Inc.\n",
|
||||
_("(C)"));
|
||||
printf ("\n");
|
||||
printf (_("\
|
||||
GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\
|
||||
You may redistribute copies of GNU Fortran\n\
|
||||
under the terms of the GNU General Public License.\n\
|
||||
For more information about these matters, see the file named COPYING\n\
|
||||
or type the command `info -f g77 Copying'.\n\
|
||||
"));
|
||||
exit (0);
|
||||
break;
|
||||
|
||||
case OPTION_help:
|
||||
/* Let gcc.c handle this, as it has a really
|
||||
cool facility for handling --help and --verbose --help. */
|
||||
return;
|
||||
|
||||
case OPTION_driver:
|
||||
fatal ("--driver no longer supported");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is the one place we check for missing arguments in the
|
||||
program. */
|
||||
|
||||
if (i + skip < argc)
|
||||
i += skip;
|
||||
else
|
||||
fatal ("argument to `%s' missing", argv[i]);
|
||||
}
|
||||
|
||||
if ((n_outfiles != 0) && (n_infiles == 0))
|
||||
fatal ("no input files; unwilling to write output files");
|
||||
|
||||
/* If there are no input files, no need for the library. */
|
||||
if (n_infiles == 0)
|
||||
library = 0;
|
||||
|
||||
/* Second pass through arglist, transforming arguments as appropriate. */
|
||||
|
||||
append_arg (argv[0]); /* Start with command name, of course. */
|
||||
|
||||
for (i = 1; i < argc; ++i)
|
||||
{
|
||||
if (argv[i][0] == '\0')
|
||||
{
|
||||
append_arg (argv[i]); /* Interesting. Just append as is. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
|
||||
{
|
||||
/* Not a filename or library. */
|
||||
|
||||
if (saw_library == 1 && need_math) /* -l<library>. */
|
||||
append_arg (saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY);
|
||||
|
||||
saw_library = 0;
|
||||
|
||||
lookup_option (&opt, &skip, &arg, argv[i]);
|
||||
|
||||
if (argv[i][1] == '\0')
|
||||
{
|
||||
append_arg (argv[i]); /* "-" == Standard input. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (opt == OPTION_x)
|
||||
{
|
||||
/* Track input language. */
|
||||
const char *lang;
|
||||
|
||||
if (arg == NULL)
|
||||
lang = argv[i+1];
|
||||
else
|
||||
lang = arg;
|
||||
|
||||
saw_speclang = (strcmp (lang, "none") != 0);
|
||||
}
|
||||
|
||||
append_arg (argv[i]);
|
||||
|
||||
for (; skip != 0; --skip)
|
||||
append_arg (argv[++i]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* A filename/library, not an option. */
|
||||
|
||||
if (saw_speclang)
|
||||
saw_library = 0; /* -xfoo currently active. */
|
||||
else
|
||||
{ /* -lfoo or filename. */
|
||||
if (strcmp (argv[i], MATH_LIBRARY) == 0)
|
||||
{
|
||||
if (saw_library == 1)
|
||||
saw_library = 2; /* -l<library> -lm. */
|
||||
else
|
||||
{
|
||||
if (0 == use_init)
|
||||
{
|
||||
append_arg (saw_profile_flag ? FORTRAN_INIT_PROFILE
|
||||
: FORTRAN_INIT);
|
||||
use_init = 1;
|
||||
}
|
||||
append_arg (saw_profile_flag ? FORTRAN_LIBRARY_PROFILE
|
||||
: FORTRAN_LIBRARY);
|
||||
}
|
||||
}
|
||||
else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0)
|
||||
saw_library = 1; /* -l<library>. */
|
||||
else
|
||||
{ /* Other library, or filename. */
|
||||
if (saw_library == 1 && need_math)
|
||||
append_arg (saw_profile_flag ? MATH_LIBRARY_PROFILE
|
||||
: MATH_LIBRARY);
|
||||
saw_library = 0;
|
||||
}
|
||||
}
|
||||
append_arg (argv[i]);
|
||||
}
|
||||
|
||||
/* Append `-lg2c -lm' as necessary. */
|
||||
|
||||
if (library)
|
||||
{ /* Doing a link and no -nostdlib. */
|
||||
if (saw_speclang)
|
||||
append_arg ("-xnone");
|
||||
|
||||
switch (saw_library)
|
||||
{
|
||||
case 0:
|
||||
if (0 == use_init)
|
||||
{
|
||||
append_arg (saw_profile_flag ? FORTRAN_INIT_PROFILE
|
||||
: FORTRAN_INIT);
|
||||
use_init = 1;
|
||||
}
|
||||
append_arg (library);
|
||||
case 1:
|
||||
if (need_math)
|
||||
append_arg (saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SHARED_LIBGCC
|
||||
if (library)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < g77_newargc; i++)
|
||||
if (g77_newargv[i][0] == '-')
|
||||
if (strcmp (g77_newargv[i], "-static-libgcc") == 0
|
||||
|| strcmp (g77_newargv[i], "-static") == 0)
|
||||
break;
|
||||
|
||||
if (i == g77_newargc)
|
||||
append_arg ("-shared-libgcc");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (verbose
|
||||
&& g77_newargv != g77_xargv)
|
||||
{
|
||||
fprintf (stderr, "Driving:");
|
||||
for (i = 0; i < g77_newargc; i++)
|
||||
fprintf (stderr, " %s", g77_newargv[i]);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
*in_argc = g77_newargc;
|
||||
*in_argv = g77_newargv;
|
||||
}
|
||||
|
||||
/* Called before linking. Returns 0 on success and -1 on failure. */
|
||||
int lang_specific_pre_link (void) /* Not used for F77. */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Number of extra output files that lang_specific_pre_link may generate. */
|
||||
int lang_specific_extra_outfiles = 0; /* Not used for F77. */
|
||||
|
||||
/* Table of language-specific spec functions. */
|
||||
const struct spec_function lang_specific_spec_functions[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
@ -1,181 +0,0 @@
|
||||
/* Utility to pick a temporary filename prefix.
|
||||
Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the libiberty library.
|
||||
Libiberty is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
Libiberty is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with libiberty; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* May get P_tmpdir. */
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_FILE_H
|
||||
#include <sys/file.h> /* May get R_OK, etc. on some systems. */
|
||||
#endif
|
||||
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#define W_OK 2
|
||||
#define X_OK 1
|
||||
#endif
|
||||
|
||||
#include "libiberty.h"
|
||||
extern int mkstemps PARAMS ((char *, int));
|
||||
|
||||
/* '/' works just fine on MS-DOS based systems. */
|
||||
#ifndef DIR_SEPARATOR
|
||||
#define DIR_SEPARATOR '/'
|
||||
#endif
|
||||
|
||||
/* Name of temporary file.
|
||||
mktemp requires 6 trailing X's. */
|
||||
#define TEMP_FILE "ccXXXXXX"
|
||||
#define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
|
||||
|
||||
/* Subroutine of choose_tmpdir.
|
||||
If BASE is non-NULL, return it.
|
||||
Otherwise it checks if DIR is a usable directory.
|
||||
If success, DIR is returned.
|
||||
Otherwise NULL is returned. */
|
||||
|
||||
static inline const char *try PARAMS ((const char *, const char *));
|
||||
|
||||
static inline const char *
|
||||
try (dir, base)
|
||||
const char *dir, *base;
|
||||
{
|
||||
if (base != 0)
|
||||
return base;
|
||||
if (dir != 0
|
||||
&& access (dir, R_OK | W_OK | X_OK) == 0)
|
||||
return dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
|
||||
static const char usrtmp[] =
|
||||
{ DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
|
||||
static const char vartmp[] =
|
||||
{ DIR_SEPARATOR, 'v', 'a', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
|
||||
|
||||
static char *memoized_tmpdir;
|
||||
|
||||
/*
|
||||
|
||||
@deftypefn Replacement char* choose_tmpdir ()
|
||||
|
||||
Returns a pointer to a directory path suitable for creating temporary
|
||||
files in.
|
||||
|
||||
@end deftypefn
|
||||
|
||||
*/
|
||||
|
||||
char *
|
||||
choose_tmpdir ()
|
||||
{
|
||||
const char *base = 0;
|
||||
char *tmpdir;
|
||||
unsigned int len;
|
||||
|
||||
if (memoized_tmpdir)
|
||||
return memoized_tmpdir;
|
||||
|
||||
base = try (getenv ("TMPDIR"), base);
|
||||
base = try (getenv ("TMP"), base);
|
||||
base = try (getenv ("TEMP"), base);
|
||||
|
||||
#ifdef P_tmpdir
|
||||
base = try (P_tmpdir, base);
|
||||
#endif
|
||||
|
||||
/* Try /tmp, /var/tmp, then /usr/tmp. */
|
||||
base = try (tmp, base);
|
||||
base = try (vartmp, base);
|
||||
base = try (usrtmp, base);
|
||||
|
||||
/* If all else fails, use the current directory! */
|
||||
if (base == 0)
|
||||
base = ".";
|
||||
|
||||
/* Append DIR_SEPARATOR to the directory we've chosen
|
||||
and return it. */
|
||||
len = strlen (base);
|
||||
tmpdir = xmalloc (len + 2);
|
||||
strcpy (tmpdir, base);
|
||||
tmpdir[len] = DIR_SEPARATOR;
|
||||
tmpdir[len+1] = '\0';
|
||||
|
||||
memoized_tmpdir = tmpdir;
|
||||
return tmpdir;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@deftypefn Replacement char* make_temp_file (const char *@var{suffix})
|
||||
|
||||
Return a temporary file name (as a string) or @code{NULL} if unable to
|
||||
create one. @var{suffix} is a suffix to append to the file name. The
|
||||
string is @code{malloc}ed, and the temporary file has been created.
|
||||
|
||||
@end deftypefn
|
||||
|
||||
*/
|
||||
|
||||
char *
|
||||
make_temp_file (suffix)
|
||||
const char *suffix;
|
||||
{
|
||||
const char *base = choose_tmpdir ();
|
||||
char *temp_filename;
|
||||
int base_len, suffix_len;
|
||||
int fd;
|
||||
|
||||
if (suffix == 0)
|
||||
suffix = "";
|
||||
|
||||
base_len = strlen (base);
|
||||
suffix_len = strlen (suffix);
|
||||
|
||||
temp_filename = xmalloc (base_len
|
||||
+ TEMP_FILE_LEN
|
||||
+ suffix_len + 1);
|
||||
strcpy (temp_filename, base);
|
||||
strcpy (temp_filename + base_len, TEMP_FILE);
|
||||
strcpy (temp_filename + base_len + TEMP_FILE_LEN, suffix);
|
||||
|
||||
fd = mkstemps (temp_filename, suffix_len);
|
||||
/* If mkstemps failed, then something bad is happening. Maybe we should
|
||||
issue a message about a possible security attack in progress? */
|
||||
if (fd == -1)
|
||||
abort ();
|
||||
/* Similarly if we can not close the file. */
|
||||
if (close (fd))
|
||||
abort ();
|
||||
return temp_filename;
|
||||
}
|
@ -1,794 +0,0 @@
|
||||
/* Utilities to execute a program in a subprocess (possibly linked by pipes
|
||||
with other subprocesses), and wait for it.
|
||||
Copyright (C) 1996-2000 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the libiberty library.
|
||||
Libiberty is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
Libiberty is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with libiberty; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* This file exports two functions: pexecute and pwait. */
|
||||
|
||||
/* This file lives in at least two places: libiberty and gcc.
|
||||
Don't change one without the other. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifdef NEED_DECLARATION_ERRNO
|
||||
extern int errno;
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include "libiberty.h"
|
||||
#include "safe-ctype.h"
|
||||
|
||||
/* stdin file number. */
|
||||
#define STDIN_FILE_NO 0
|
||||
|
||||
/* stdout file number. */
|
||||
#define STDOUT_FILE_NO 1
|
||||
|
||||
/* value of `pipe': port index for reading. */
|
||||
#define READ_PORT 0
|
||||
|
||||
/* value of `pipe': port index for writing. */
|
||||
#define WRITE_PORT 1
|
||||
|
||||
static char *install_error_msg = "installation problem, cannot exec `%s'";
|
||||
|
||||
/* pexecute: execute a program.
|
||||
|
||||
@deftypefn Extension int pexecute (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int flags)
|
||||
|
||||
Executes a program.
|
||||
|
||||
@var{program} and @var{argv} are the arguments to
|
||||
@code{execv}/@code{execvp}.
|
||||
|
||||
@var{this_pname} is name of the calling program (i.e., @code{argv[0]}).
|
||||
|
||||
@var{temp_base} is the path name, sans suffix, of a temporary file to
|
||||
use if needed. This is currently only needed for MS-DOS ports that
|
||||
don't use @code{go32} (do any still exist?). Ports that don't need it
|
||||
can pass @code{NULL}.
|
||||
|
||||
(@code{@var{flags} & PEXECUTE_SEARCH}) is non-zero if @env{PATH} should be searched
|
||||
(??? It's not clear that GCC passes this flag correctly). (@code{@var{flags} &
|
||||
PEXECUTE_FIRST}) is nonzero for the first process in chain.
|
||||
(@code{@var{flags} & PEXECUTE_FIRST}) is nonzero for the last process
|
||||
in chain. The first/last flags could be simplified to only mark the
|
||||
last of a chain of processes but that requires the caller to always
|
||||
mark the last one (and not give up early if some error occurs).
|
||||
It's more robust to require the caller to mark both ends of the chain.
|
||||
|
||||
The result is the pid on systems like Unix where we
|
||||
@code{fork}/@code{exec} and on systems like WIN32 and OS/2 where we
|
||||
use @code{spawn}. It is up to the caller to wait for the child.
|
||||
|
||||
The result is the @code{WEXITSTATUS} on systems like MS-DOS where we
|
||||
@code{spawn} and wait for the child here.
|
||||
|
||||
Upon failure, @var{errmsg_fmt} and @var{errmsg_arg} are set to the
|
||||
text of the error message with an optional argument (if not needed,
|
||||
@var{errmsg_arg} is set to @code{NULL}), and @minus{}1 is returned.
|
||||
@code{errno} is available to the caller to use.
|
||||
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn Extension int pwait (int @var{pid}, int *@var{status}, int @var{flags})
|
||||
|
||||
Waits for a program started by @code{pexecute} to finish.
|
||||
|
||||
@var{pid} is the process id of the task to wait for. @var{status} is
|
||||
the `status' argument to wait. @var{flags} is currently unused (allows
|
||||
future enhancement without breaking upward compatibility). Pass 0 for now.
|
||||
|
||||
The result is the pid of the child reaped, or -1 for failure
|
||||
(@code{errno} says why).
|
||||
|
||||
On systems that don't support waiting for a particular child, @var{pid} is
|
||||
ignored. On systems like MS-DOS that don't really multitask @code{pwait}
|
||||
is just a mechanism to provide a consistent interface for the caller.
|
||||
|
||||
@end deftypefn
|
||||
|
||||
@undocumented pfinish
|
||||
|
||||
pfinish: finish generation of script
|
||||
|
||||
pfinish is necessary for systems like MPW where a script is generated that
|
||||
runs the requested programs. */
|
||||
|
||||
#ifdef __MSDOS__
|
||||
|
||||
/* MSDOS doesn't multitask, but for the sake of a consistent interface
|
||||
the code behaves like it does. pexecute runs the program, tucks the
|
||||
exit code away, and returns a "pid". pwait must be called to fetch the
|
||||
exit code. */
|
||||
|
||||
#include <process.h>
|
||||
|
||||
/* For communicating information from pexecute to pwait. */
|
||||
static int last_pid = 0;
|
||||
static int last_status = 0;
|
||||
static int last_reaped = 0;
|
||||
|
||||
int
|
||||
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
|
||||
const char *program;
|
||||
char * const *argv;
|
||||
const char *this_pname;
|
||||
const char *temp_base;
|
||||
char **errmsg_fmt, **errmsg_arg;
|
||||
int flags;
|
||||
{
|
||||
int rc;
|
||||
|
||||
last_pid++;
|
||||
if (last_pid < 0)
|
||||
last_pid = 1;
|
||||
|
||||
if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
|
||||
abort ();
|
||||
|
||||
#ifdef __DJGPP__
|
||||
/* ??? What are the possible return values from spawnv? */
|
||||
rc = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (P_WAIT, program, argv);
|
||||
#else
|
||||
char *scmd, *rf;
|
||||
FILE *argfile;
|
||||
int i, el = flags & PEXECUTE_SEARCH ? 4 : 0;
|
||||
|
||||
if (temp_base == 0)
|
||||
temp_base = choose_temp_base ();
|
||||
scmd = (char *) xmalloc (strlen (program) + strlen (temp_base) + 6 + el);
|
||||
rf = scmd + strlen(program) + 2 + el;
|
||||
sprintf (scmd, "%s%s @%s.gp", program,
|
||||
(flags & PEXECUTE_SEARCH ? ".exe" : ""), temp_base);
|
||||
argfile = fopen (rf, "w");
|
||||
if (argfile == 0)
|
||||
{
|
||||
int errno_save = errno;
|
||||
free (scmd);
|
||||
errno = errno_save;
|
||||
*errmsg_fmt = "cannot open `%s.gp'";
|
||||
*errmsg_arg = temp_base;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=1; argv[i]; i++)
|
||||
{
|
||||
char *cp;
|
||||
for (cp = argv[i]; *cp; cp++)
|
||||
{
|
||||
if (*cp == '"' || *cp == '\'' || *cp == '\\' || ISSPACE (*cp))
|
||||
fputc ('\\', argfile);
|
||||
fputc (*cp, argfile);
|
||||
}
|
||||
fputc ('\n', argfile);
|
||||
}
|
||||
fclose (argfile);
|
||||
|
||||
rc = system (scmd);
|
||||
|
||||
{
|
||||
int errno_save = errno;
|
||||
remove (rf);
|
||||
free (scmd);
|
||||
errno = errno_save;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
*errmsg_fmt = install_error_msg;
|
||||
*errmsg_arg = (char *)program;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Tuck the status away for pwait, and return a "pid". */
|
||||
last_status = rc << 8;
|
||||
return last_pid;
|
||||
}
|
||||
|
||||
/* Use ECHILD if available, otherwise use EINVAL. */
|
||||
#ifdef ECHILD
|
||||
#define PWAIT_ERROR ECHILD
|
||||
#else
|
||||
#define PWAIT_ERROR EINVAL
|
||||
#endif
|
||||
|
||||
int
|
||||
pwait (pid, status, flags)
|
||||
int pid;
|
||||
int *status;
|
||||
int flags;
|
||||
{
|
||||
/* On MSDOS each pexecute must be followed by it's associated pwait. */
|
||||
if (pid != last_pid
|
||||
/* Called twice for the same child? */
|
||||
|| pid == last_reaped)
|
||||
{
|
||||
errno = PWAIT_ERROR;
|
||||
return -1;
|
||||
}
|
||||
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||
Needed? */
|
||||
#ifdef __DJGPP__
|
||||
*status = (last_status >> 8);
|
||||
#else
|
||||
*status = last_status;
|
||||
#endif
|
||||
last_reaped = last_pid;
|
||||
return last_pid;
|
||||
}
|
||||
|
||||
#endif /* MSDOS */
|
||||
|
||||
#if defined (_WIN32) && ! defined (_UWIN)
|
||||
|
||||
#include <process.h>
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
|
||||
#define fix_argv(argvec) (argvec)
|
||||
|
||||
extern int _spawnv ();
|
||||
extern int _spawnvp ();
|
||||
|
||||
#else /* ! __CYGWIN__ */
|
||||
|
||||
/* This is a kludge to get around the Microsoft C spawn functions' propensity
|
||||
to remove the outermost set of double quotes from all arguments. */
|
||||
|
||||
static const char * const *
|
||||
fix_argv (argvec)
|
||||
char **argvec;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; argvec[i] != 0; i++)
|
||||
{
|
||||
int len, j;
|
||||
char *temp, *newtemp;
|
||||
|
||||
temp = argvec[i];
|
||||
len = strlen (temp);
|
||||
for (j = 0; j < len; j++)
|
||||
{
|
||||
if (temp[j] == '"')
|
||||
{
|
||||
newtemp = xmalloc (len + 2);
|
||||
strncpy (newtemp, temp, j);
|
||||
newtemp [j] = '\\';
|
||||
strncpy (&newtemp [j+1], &temp [j], len-j);
|
||||
newtemp [len+1] = 0;
|
||||
temp = newtemp;
|
||||
len++;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
argvec[i] = temp;
|
||||
}
|
||||
|
||||
for (i = 0; argvec[i] != 0; i++)
|
||||
{
|
||||
if (strpbrk (argvec[i], " \t"))
|
||||
{
|
||||
int len, trailing_backslash;
|
||||
char *temp;
|
||||
|
||||
len = strlen (argvec[i]);
|
||||
trailing_backslash = 0;
|
||||
|
||||
/* There is an added complication when an arg with embedded white
|
||||
space ends in a backslash (such as in the case of -iprefix arg
|
||||
passed to cpp). The resulting quoted strings gets misinterpreted
|
||||
by the command interpreter -- it thinks that the ending quote
|
||||
is escaped by the trailing backslash and things get confused.
|
||||
We handle this case by escaping the trailing backslash, provided
|
||||
it was not escaped in the first place. */
|
||||
if (len > 1
|
||||
&& argvec[i][len-1] == '\\'
|
||||
&& argvec[i][len-2] != '\\')
|
||||
{
|
||||
trailing_backslash = 1;
|
||||
++len; /* to escape the final backslash. */
|
||||
}
|
||||
|
||||
len += 2; /* and for the enclosing quotes. */
|
||||
|
||||
temp = xmalloc (len + 1);
|
||||
temp[0] = '"';
|
||||
strcpy (temp + 1, argvec[i]);
|
||||
if (trailing_backslash)
|
||||
temp[len-2] = '\\';
|
||||
temp[len-1] = '"';
|
||||
temp[len] = '\0';
|
||||
|
||||
argvec[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
return (const char * const *) argvec;
|
||||
}
|
||||
#endif /* __CYGWIN__ */
|
||||
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* mingw32 headers may not define the following. */
|
||||
|
||||
#ifndef _P_WAIT
|
||||
# define _P_WAIT 0
|
||||
# define _P_NOWAIT 1
|
||||
# define _P_OVERLAY 2
|
||||
# define _P_NOWAITO 3
|
||||
# define _P_DETACH 4
|
||||
|
||||
# define WAIT_CHILD 0
|
||||
# define WAIT_GRANDCHILD 1
|
||||
#endif
|
||||
|
||||
/* Win32 supports pipes */
|
||||
int
|
||||
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
|
||||
const char *program;
|
||||
char * const *argv;
|
||||
const char *this_pname;
|
||||
const char *temp_base;
|
||||
char **errmsg_fmt, **errmsg_arg;
|
||||
int flags;
|
||||
{
|
||||
int pid;
|
||||
int pdes[2], org_stdin, org_stdout;
|
||||
int input_desc, output_desc;
|
||||
int retries, sleep_interval;
|
||||
|
||||
/* Pipe waiting from last process, to be used as input for the next one.
|
||||
Value is STDIN_FILE_NO if no pipe is waiting
|
||||
(i.e. the next command is the first of a group). */
|
||||
static int last_pipe_input;
|
||||
|
||||
/* If this is the first process, initialize. */
|
||||
if (flags & PEXECUTE_FIRST)
|
||||
last_pipe_input = STDIN_FILE_NO;
|
||||
|
||||
input_desc = last_pipe_input;
|
||||
|
||||
/* If this isn't the last process, make a pipe for its output,
|
||||
and record it as waiting to be the input to the next process. */
|
||||
if (! (flags & PEXECUTE_LAST))
|
||||
{
|
||||
if (_pipe (pdes, 256, O_BINARY) < 0)
|
||||
{
|
||||
*errmsg_fmt = "pipe";
|
||||
*errmsg_arg = NULL;
|
||||
return -1;
|
||||
}
|
||||
output_desc = pdes[WRITE_PORT];
|
||||
last_pipe_input = pdes[READ_PORT];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Last process. */
|
||||
output_desc = STDOUT_FILE_NO;
|
||||
last_pipe_input = STDIN_FILE_NO;
|
||||
}
|
||||
|
||||
if (input_desc != STDIN_FILE_NO)
|
||||
{
|
||||
org_stdin = dup (STDIN_FILE_NO);
|
||||
dup2 (input_desc, STDIN_FILE_NO);
|
||||
close (input_desc);
|
||||
}
|
||||
|
||||
if (output_desc != STDOUT_FILE_NO)
|
||||
{
|
||||
org_stdout = dup (STDOUT_FILE_NO);
|
||||
dup2 (output_desc, STDOUT_FILE_NO);
|
||||
close (output_desc);
|
||||
}
|
||||
|
||||
pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
|
||||
(_P_NOWAIT, program, fix_argv(argv));
|
||||
|
||||
if (input_desc != STDIN_FILE_NO)
|
||||
{
|
||||
dup2 (org_stdin, STDIN_FILE_NO);
|
||||
close (org_stdin);
|
||||
}
|
||||
|
||||
if (output_desc != STDOUT_FILE_NO)
|
||||
{
|
||||
dup2 (org_stdout, STDOUT_FILE_NO);
|
||||
close (org_stdout);
|
||||
}
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
*errmsg_fmt = install_error_msg;
|
||||
*errmsg_arg = program;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* MS CRTDLL doesn't return enough information in status to decide if the
|
||||
child exited due to a signal or not, rather it simply returns an
|
||||
integer with the exit code of the child; eg., if the child exited with
|
||||
an abort() call and didn't have a handler for SIGABRT, it simply returns
|
||||
with status = 3. We fix the status code to conform to the usual WIF*
|
||||
macros. Note that WIFSIGNALED will never be true under CRTDLL. */
|
||||
|
||||
int
|
||||
pwait (pid, status, flags)
|
||||
int pid;
|
||||
int *status;
|
||||
int flags;
|
||||
{
|
||||
#ifdef __CYGWIN__
|
||||
return wait (status);
|
||||
#else
|
||||
int termstat;
|
||||
|
||||
pid = _cwait (&termstat, pid, WAIT_CHILD);
|
||||
|
||||
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||
Needed? */
|
||||
|
||||
/* cwait returns the child process exit code in termstat.
|
||||
A value of 3 indicates that the child caught a signal, but not
|
||||
which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
|
||||
report SIGABRT. */
|
||||
if (termstat == 3)
|
||||
*status = SIGABRT;
|
||||
else
|
||||
*status = (((termstat) & 0xff) << 8);
|
||||
|
||||
return pid;
|
||||
#endif /* __CYGWIN__ */
|
||||
}
|
||||
|
||||
#endif /* _WIN32 && ! _UWIN */
|
||||
|
||||
#ifdef OS2
|
||||
|
||||
/* ??? Does OS2 have process.h? */
|
||||
extern int spawnv ();
|
||||
extern int spawnvp ();
|
||||
|
||||
int
|
||||
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
|
||||
const char *program;
|
||||
char * const *argv;
|
||||
const char *this_pname;
|
||||
const char *temp_base;
|
||||
char **errmsg_fmt, **errmsg_arg;
|
||||
int flags;
|
||||
{
|
||||
int pid;
|
||||
|
||||
if ((flags & PEXECUTE_ONE) != PEXECUTE_ONE)
|
||||
abort ();
|
||||
/* ??? Presumably 1 == _P_NOWAIT. */
|
||||
pid = (flags & PEXECUTE_SEARCH ? spawnvp : spawnv) (1, program, argv);
|
||||
if (pid == -1)
|
||||
{
|
||||
*errmsg_fmt = install_error_msg;
|
||||
*errmsg_arg = program;
|
||||
return -1;
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
int
|
||||
pwait (pid, status, flags)
|
||||
int pid;
|
||||
int *status;
|
||||
int flags;
|
||||
{
|
||||
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||
Needed? */
|
||||
int pid = wait (status);
|
||||
return pid;
|
||||
}
|
||||
|
||||
#endif /* OS2 */
|
||||
|
||||
#ifdef MPW
|
||||
|
||||
/* MPW pexecute doesn't actually run anything; instead, it writes out
|
||||
script commands that, when run, will do the actual executing.
|
||||
|
||||
For example, in GCC's case, GCC will write out several script commands:
|
||||
|
||||
cpp ...
|
||||
cc1 ...
|
||||
as ...
|
||||
ld ...
|
||||
|
||||
and then exit. None of the above programs will have run yet. The task
|
||||
that called GCC will then execute the script and cause cpp,etc. to run.
|
||||
The caller must invoke pfinish before calling exit. This adds
|
||||
the finishing touches to the generated script. */
|
||||
|
||||
static int first_time = 1;
|
||||
|
||||
int
|
||||
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
|
||||
const char *program;
|
||||
char * const *argv;
|
||||
const char *this_pname;
|
||||
const char *temp_base;
|
||||
char **errmsg_fmt, **errmsg_arg;
|
||||
int flags;
|
||||
{
|
||||
char tmpprogram[255];
|
||||
char *cp, *tmpname;
|
||||
int i;
|
||||
|
||||
mpwify_filename (program, tmpprogram);
|
||||
if (first_time)
|
||||
{
|
||||
printf ("Set Failed 0\n");
|
||||
first_time = 0;
|
||||
}
|
||||
|
||||
fputs ("If {Failed} == 0\n", stdout);
|
||||
/* If being verbose, output a copy of the command. It should be
|
||||
accurate enough and escaped enough to be "clickable". */
|
||||
if (flags & PEXECUTE_VERBOSE)
|
||||
{
|
||||
fputs ("\tEcho ", stdout);
|
||||
fputc ('\'', stdout);
|
||||
fputs (tmpprogram, stdout);
|
||||
fputc ('\'', stdout);
|
||||
fputc (' ', stdout);
|
||||
for (i=1; argv[i]; i++)
|
||||
{
|
||||
fputc ('\'', stdout);
|
||||
/* See if we have an argument that needs fixing. */
|
||||
if (strchr(argv[i], '/'))
|
||||
{
|
||||
tmpname = (char *) xmalloc (256);
|
||||
mpwify_filename (argv[i], tmpname);
|
||||
argv[i] = tmpname;
|
||||
}
|
||||
for (cp = argv[i]; *cp; cp++)
|
||||
{
|
||||
/* Write an Option-d escape char in front of special chars. */
|
||||
if (strchr("'+", *cp))
|
||||
fputc ('\266', stdout);
|
||||
fputc (*cp, stdout);
|
||||
}
|
||||
fputc ('\'', stdout);
|
||||
fputc (' ', stdout);
|
||||
}
|
||||
fputs ("\n", stdout);
|
||||
}
|
||||
fputs ("\t", stdout);
|
||||
fputs (tmpprogram, stdout);
|
||||
fputc (' ', stdout);
|
||||
|
||||
for (i=1; argv[i]; i++)
|
||||
{
|
||||
/* See if we have an argument that needs fixing. */
|
||||
if (strchr(argv[i], '/'))
|
||||
{
|
||||
tmpname = (char *) xmalloc (256);
|
||||
mpwify_filename (argv[i], tmpname);
|
||||
argv[i] = tmpname;
|
||||
}
|
||||
if (strchr (argv[i], ' '))
|
||||
fputc ('\'', stdout);
|
||||
for (cp = argv[i]; *cp; cp++)
|
||||
{
|
||||
/* Write an Option-d escape char in front of special chars. */
|
||||
if (strchr("'+", *cp))
|
||||
fputc ('\266', stdout);
|
||||
fputc (*cp, stdout);
|
||||
}
|
||||
if (strchr (argv[i], ' '))
|
||||
fputc ('\'', stdout);
|
||||
fputc (' ', stdout);
|
||||
}
|
||||
|
||||
fputs ("\n", stdout);
|
||||
|
||||
/* Output commands that arrange to clean up and exit if a failure occurs.
|
||||
We have to be careful to collect the status from the program that was
|
||||
run, rather than some other script command. Also, we don't exit
|
||||
immediately, since necessary cleanups are at the end of the script. */
|
||||
fputs ("\tSet TmpStatus {Status}\n", stdout);
|
||||
fputs ("\tIf {TmpStatus} != 0\n", stdout);
|
||||
fputs ("\t\tSet Failed {TmpStatus}\n", stdout);
|
||||
fputs ("\tEnd\n", stdout);
|
||||
fputs ("End\n", stdout);
|
||||
|
||||
/* We're just composing a script, can't fail here. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
pwait (pid, status, flags)
|
||||
int pid;
|
||||
int *status;
|
||||
int flags;
|
||||
{
|
||||
*status = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write out commands that will exit with the correct error code
|
||||
if something in the script failed. */
|
||||
|
||||
void
|
||||
pfinish ()
|
||||
{
|
||||
printf ("\tExit \"{Failed}\"\n");
|
||||
}
|
||||
|
||||
#endif /* MPW */
|
||||
|
||||
/* include for Unix-like environments but not for Dos-like environments */
|
||||
#if ! defined (__MSDOS__) && ! defined (OS2) && ! defined (MPW) \
|
||||
&& ! (defined (_WIN32) && ! defined (_UWIN))
|
||||
|
||||
extern int execv ();
|
||||
extern int execvp ();
|
||||
|
||||
int
|
||||
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
|
||||
const char *program;
|
||||
char * const *argv;
|
||||
const char *this_pname;
|
||||
const char *temp_base ATTRIBUTE_UNUSED;
|
||||
char **errmsg_fmt, **errmsg_arg;
|
||||
int flags;
|
||||
{
|
||||
int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
|
||||
int pid;
|
||||
int pdes[2];
|
||||
int input_desc, output_desc;
|
||||
int retries, sleep_interval;
|
||||
/* Pipe waiting from last process, to be used as input for the next one.
|
||||
Value is STDIN_FILE_NO if no pipe is waiting
|
||||
(i.e. the next command is the first of a group). */
|
||||
static int last_pipe_input;
|
||||
|
||||
/* If this is the first process, initialize. */
|
||||
if (flags & PEXECUTE_FIRST)
|
||||
last_pipe_input = STDIN_FILE_NO;
|
||||
|
||||
input_desc = last_pipe_input;
|
||||
|
||||
/* If this isn't the last process, make a pipe for its output,
|
||||
and record it as waiting to be the input to the next process. */
|
||||
if (! (flags & PEXECUTE_LAST))
|
||||
{
|
||||
if (pipe (pdes) < 0)
|
||||
{
|
||||
*errmsg_fmt = "pipe";
|
||||
*errmsg_arg = NULL;
|
||||
return -1;
|
||||
}
|
||||
output_desc = pdes[WRITE_PORT];
|
||||
last_pipe_input = pdes[READ_PORT];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Last process. */
|
||||
output_desc = STDOUT_FILE_NO;
|
||||
last_pipe_input = STDIN_FILE_NO;
|
||||
}
|
||||
|
||||
/* Fork a subprocess; wait and retry if it fails. */
|
||||
sleep_interval = 1;
|
||||
pid = -1;
|
||||
for (retries = 0; retries < 4; retries++)
|
||||
{
|
||||
pid = fork ();
|
||||
if (pid >= 0)
|
||||
break;
|
||||
sleep (sleep_interval);
|
||||
sleep_interval *= 2;
|
||||
}
|
||||
|
||||
switch (pid)
|
||||
{
|
||||
case -1:
|
||||
*errmsg_fmt = "fork";
|
||||
*errmsg_arg = NULL;
|
||||
return -1;
|
||||
|
||||
case 0: /* child */
|
||||
/* Move the input and output pipes into place, if necessary. */
|
||||
if (input_desc != STDIN_FILE_NO)
|
||||
{
|
||||
close (STDIN_FILE_NO);
|
||||
dup (input_desc);
|
||||
close (input_desc);
|
||||
}
|
||||
if (output_desc != STDOUT_FILE_NO)
|
||||
{
|
||||
close (STDOUT_FILE_NO);
|
||||
dup (output_desc);
|
||||
close (output_desc);
|
||||
}
|
||||
|
||||
/* Close the parent's descs that aren't wanted here. */
|
||||
if (last_pipe_input != STDIN_FILE_NO)
|
||||
close (last_pipe_input);
|
||||
|
||||
/* Exec the program. */
|
||||
(*func) (program, argv);
|
||||
|
||||
fprintf (stderr, "%s: ", this_pname);
|
||||
fprintf (stderr, install_error_msg, program);
|
||||
fprintf (stderr, ": %s\n", xstrerror (errno));
|
||||
_exit (-1);
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
|
||||
default:
|
||||
/* In the parent, after forking.
|
||||
Close the descriptors that we made for this child. */
|
||||
if (input_desc != STDIN_FILE_NO)
|
||||
close (input_desc);
|
||||
if (output_desc != STDOUT_FILE_NO)
|
||||
close (output_desc);
|
||||
|
||||
/* Return child's process number. */
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pwait (pid, status, flags)
|
||||
int pid;
|
||||
int *status;
|
||||
int flags ATTRIBUTE_UNUSED;
|
||||
{
|
||||
/* ??? Here's an opportunity to canonicalize the values in STATUS.
|
||||
Needed? */
|
||||
#ifdef VMS
|
||||
pid = waitpid (-1, status, 0);
|
||||
#else
|
||||
pid = wait (status);
|
||||
#endif
|
||||
return pid;
|
||||
}
|
||||
|
||||
#endif /* ! __MSDOS__ && ! OS2 && ! MPW && ! (_WIN32 && ! _UWIN) */
|
Loading…
Reference in New Issue
Block a user