mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 01:28:46 +00:00
merge from gcc
This commit is contained in:
@@ -67,6 +67,7 @@ pex_init_common (int flags, const char *pname, const char *tempbase,
|
||||
obj->status = NULL;
|
||||
obj->time = NULL;
|
||||
obj->number_waited = 0;
|
||||
obj->input_file = NULL;
|
||||
obj->read_output = NULL;
|
||||
obj->remove_count = 0;
|
||||
obj->remove = NULL;
|
||||
@@ -91,6 +92,56 @@ pex_add_remove (struct pex_obj *obj, const char *name, int allocated)
|
||||
obj->remove[obj->remove_count - 1] = add;
|
||||
}
|
||||
|
||||
/* Generate a temporary file name based on OBJ, FLAGS, and NAME.
|
||||
Return NULL if we were unable to reserve a temporary filename.
|
||||
|
||||
If non-NULL, the result is either allocated with malloc, or the
|
||||
same pointer as NAME. */
|
||||
static char *
|
||||
temp_file (struct pex_obj *obj, int flags, char *name)
|
||||
{
|
||||
if (name == NULL)
|
||||
{
|
||||
if (obj->tempbase == NULL)
|
||||
{
|
||||
name = make_temp_file (NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
int len = strlen (obj->tempbase);
|
||||
int out;
|
||||
|
||||
if (len >= 6
|
||||
&& strcmp (obj->tempbase + len - 6, "XXXXXX") == 0)
|
||||
name = xstrdup (obj->tempbase);
|
||||
else
|
||||
name = concat (obj->tempbase, "XXXXXX", NULL);
|
||||
|
||||
out = mkstemps (name, 0);
|
||||
if (out < 0)
|
||||
{
|
||||
free (name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This isn't obj->funcs->close because we got the
|
||||
descriptor from mkstemps, not from a function in
|
||||
obj->funcs. Calling close here is just like what
|
||||
make_temp_file does. */
|
||||
close (out);
|
||||
}
|
||||
}
|
||||
else if ((flags & PEX_SUFFIX) != 0)
|
||||
{
|
||||
if (obj->tempbase == NULL)
|
||||
name = make_temp_file (name);
|
||||
else
|
||||
name = concat (obj->tempbase, name, NULL);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Run a program. */
|
||||
|
||||
const char *
|
||||
@@ -111,6 +162,17 @@ pex_run (struct pex_obj *obj, int flags, const char *executable,
|
||||
outname = (char *) orig_outname;
|
||||
outname_allocated = 0;
|
||||
|
||||
/* If the user called pex_input_file, close the file now. */
|
||||
if (obj->input_file)
|
||||
{
|
||||
if (fclose (obj->input_file) == EOF)
|
||||
{
|
||||
errmsg = "closing pipeline input file";
|
||||
goto error_exit;
|
||||
}
|
||||
obj->input_file = NULL;
|
||||
}
|
||||
|
||||
/* Set IN. */
|
||||
|
||||
if (obj->next_input_name != NULL)
|
||||
@@ -161,49 +223,16 @@ pex_run (struct pex_obj *obj, int flags, const char *executable,
|
||||
}
|
||||
else if ((obj->flags & PEX_USE_PIPES) == 0)
|
||||
{
|
||||
if (outname == NULL)
|
||||
{
|
||||
if (obj->tempbase == NULL)
|
||||
{
|
||||
outname = make_temp_file (NULL);
|
||||
outname_allocated = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int len = strlen (obj->tempbase);
|
||||
outname = temp_file (obj, flags, outname);
|
||||
if (! outname)
|
||||
{
|
||||
*err = 0;
|
||||
errmsg = "could not create temporary file";
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (len >= 6
|
||||
&& strcmp (obj->tempbase + len - 6, "XXXXXX") == 0)
|
||||
outname = xstrdup (obj->tempbase);
|
||||
else
|
||||
outname = concat (obj->tempbase, "XXXXXX", NULL);
|
||||
|
||||
outname_allocated = 1;
|
||||
|
||||
out = mkstemps (outname, 0);
|
||||
if (out < 0)
|
||||
{
|
||||
*err = 0;
|
||||
errmsg = "could not create temporary output file";
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* This isn't obj->funcs->close because we got the
|
||||
descriptor from mkstemps, not from a function in
|
||||
obj->funcs. Calling close here is just like what
|
||||
make_temp_file does. */
|
||||
close (out);
|
||||
out = -1;
|
||||
}
|
||||
}
|
||||
else if ((flags & PEX_SUFFIX) != 0)
|
||||
{
|
||||
if (obj->tempbase == NULL)
|
||||
outname = make_temp_file (outname);
|
||||
else
|
||||
outname = concat (obj->tempbase, outname, NULL);
|
||||
outname_allocated = 1;
|
||||
}
|
||||
if (outname != orig_outname)
|
||||
outname_allocated = 1;
|
||||
|
||||
if ((obj->flags & PEX_SAVE_TEMPS) == 0)
|
||||
{
|
||||
@@ -290,6 +319,87 @@ pex_run (struct pex_obj *obj, int flags, const char *executable,
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
/* Return a FILE pointer for a temporary file to fill with input for
|
||||
the pipeline. */
|
||||
FILE *
|
||||
pex_input_file (struct pex_obj *obj, int flags, const char *in_name)
|
||||
{
|
||||
char *name = (char *) in_name;
|
||||
FILE *f;
|
||||
|
||||
/* This must be called before the first pipeline stage is run, and
|
||||
there must not have been any other input selected. */
|
||||
if (obj->count != 0
|
||||
|| (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
|
||||
|| obj->next_input_name)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name = temp_file (obj, flags, name);
|
||||
if (! name)
|
||||
return NULL;
|
||||
|
||||
f = fopen (name, (flags & PEX_BINARY_OUTPUT) ? "wb" : "w");
|
||||
if (! f)
|
||||
{
|
||||
free (name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj->input_file = f;
|
||||
obj->next_input_name = name;
|
||||
obj->next_input_name_allocated = (name != in_name);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Return a stream for a pipe connected to the standard input of the
|
||||
first stage of the pipeline. */
|
||||
FILE *
|
||||
pex_input_pipe (struct pex_obj *obj, int binary)
|
||||
{
|
||||
int p[2];
|
||||
FILE *f;
|
||||
|
||||
/* You must call pex_input_pipe before the first pex_run or pex_one. */
|
||||
if (obj->count > 0)
|
||||
goto usage_error;
|
||||
|
||||
/* You must be using pipes. Implementations that don't support
|
||||
pipes clear this flag before calling pex_init_common. */
|
||||
if (! (obj->flags & PEX_USE_PIPES))
|
||||
goto usage_error;
|
||||
|
||||
/* If we have somehow already selected other input, that's a
|
||||
mistake. */
|
||||
if ((obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
|
||||
|| obj->next_input_name)
|
||||
goto usage_error;
|
||||
|
||||
if (obj->funcs->pipe (obj, p, binary != 0) < 0)
|
||||
return NULL;
|
||||
|
||||
f = obj->funcs->fdopenw (obj, p[WRITE_PORT], binary != 0);
|
||||
if (! f)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
obj->funcs->close (obj, p[READ_PORT]);
|
||||
obj->funcs->close (obj, p[WRITE_PORT]);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj->next_input = p[READ_PORT];
|
||||
|
||||
return f;
|
||||
|
||||
usage_error:
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return a FILE pointer for the output of the last program
|
||||
executed. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user