merge from gcc

This commit is contained in:
DJ Delorie
2006-04-12 18:42:01 +00:00
parent 01d3a6ce13
commit 3db2e6ddf6
11 changed files with 387 additions and 51 deletions

View File

@@ -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. */