*参照元 [#k36921b1]
#backlinks

*説明 [#z23f58d0]
-パス: [[linux-4.4.1/]]

-FIXME: これは何?
--説明


**引数 [#k628c198]
-
--

**返り値 [#na102ad6]
-
--

**参考 [#e7886444]


*実装 [#i0faf42f]
 /* Execute the command specified by the arguments on the current line of spec.
    When using pipes, this includes several piped-together commands
    with `|' between them.
 
    Return 0 if successful, -1 if failed.  */
 
 static int
 execute (void)
 {
   int i;
   int n_commands;		/* # of command.  */
   char *string;
   struct pex_obj *pex;
   struct command
   {
     const char *prog;		/* program name.  */
     const char **argv;		/* vector of args.  */
   };
   const char *arg;
 
   struct command *commands;	/* each command buffer with above info.  */
 
   gcc_assert (!processing_spec_function);
 
   if (wrapper_string)
     {
       string = find_a_file (&exec_prefixes,
 			    argbuf[0], X_OK, false);
       if (string)
 	argbuf[0] = string;
       insert_wrapper (wrapper_string);
     }
 
   /* Count # of piped commands.  */
   for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
     if (strcmp (arg, "|") == 0)
       n_commands++;
 
   /* Get storage for each command.  */
   commands = (struct command *) alloca (n_commands * sizeof (struct command));
 
   /* Split argbuf into its separate piped processes,
      and record info about each one.
      Also search for the programs that are to be run.  */
 
   argbuf.safe_push (0);
 
   commands[0].prog = argbuf[0]; /* first command.  */
   commands[0].argv = argbuf.address ();
 
   if (!wrapper_string)
     {
       string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
       commands[0].argv[0] = (string) ? string : commands[0].argv[0];
     }
 
   for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
     if (arg && strcmp (arg, "|") == 0)
       {				/* each command.  */
 #if defined (__MSDOS__) || defined (OS2) || defined (VMS)
 	fatal_error (input_location, "-pipe not supported");
 #endif
 	argbuf[i] = 0; /* Termination of
 						     command args.  */
 	commands[n_commands].prog = argbuf[i + 1];
 	commands[n_commands].argv
 	  = &(argbuf.address ())[i + 1];
 	string = find_a_file (&exec_prefixes, commands[n_commands].prog,
 			      X_OK, false);
 	if (string)
 	  commands[n_commands].argv[0] = string;
 	n_commands++;
       }
 
   /* If -v, print what we are about to do, and maybe query.  */
 
   if (verbose_flag)
     {
       /* For help listings, put a blank line between sub-processes.  */
       if (print_help_list)
 	fputc ('\n', stderr);
 
       /* Print each piped command as a separate line.  */
       for (i = 0; i < n_commands; i++)
 	{
 	  const char *const *j;
 
 	  if (verbose_only_flag)
 	    {
 	      for (j = commands[i].argv; *j; j++)
 		{
 		  const char *p;
 		  for (p = *j; *p; ++p)
 		    if (!ISALNUM ((unsigned char) *p)
 			&& *p != '_' && *p != '/' && *p != '-' && *p != '.')
 		      break;
 		  if (*p || !*j)
 		    {
 		      fprintf (stderr, " \"");
 		      for (p = *j; *p; ++p)
 			{
 			  if (*p == '"' || *p == '\\' || *p == '$')
 			    fputc ('\\', stderr);
 			  fputc (*p, stderr);
 			}
 		      fputc ('"', stderr);
 		    }
 		  /* If it's empty, print "".  */
 		  else if (!**j)
 		    fprintf (stderr, " \"\"");
 		  else
 		    fprintf (stderr, " %s", *j);
 		}
 	    }
 	  else
 	    for (j = commands[i].argv; *j; j++)
 	      /* If it's empty, print "".  */
 	      if (!**j)
 		fprintf (stderr, " \"\"");
 	      else
 		fprintf (stderr, " %s", *j);
 
 	  /* Print a pipe symbol after all but the last command.  */
 	  if (i + 1 != n_commands)
 	    fprintf (stderr, " |");
 	  fprintf (stderr, "\n");
 	}
       fflush (stderr);
       if (verbose_only_flag != 0)
         {
 	  /* verbose_only_flag should act as if the spec was
 	     executed, so increment execution_count before
 	     returning.  This prevents spurious warnings about
 	     unused linker input files, etc.  */
 	  execution_count++;
 	  return 0;
         }
 #ifdef DEBUG
       fnotice (stderr, "\nGo ahead? (y or n) ");
       fflush (stderr);
       i = getchar ();
       if (i != '\n')
 	while (getchar () != '\n')
 	  ;
 
       if (i != 'y' && i != 'Y')
 	return 0;
 #endif /* DEBUG */
     }
 
 #ifdef ENABLE_VALGRIND_CHECKING
   /* Run the each command through valgrind.  To simplify prepending the
      path to valgrind and the option "-q" (for quiet operation unless
      something triggers), we allocate a separate argv array.  */
 
   for (i = 0; i < n_commands; i++)
     {
       const char **argv;
       int argc;
       int j;
 
       for (argc = 0; commands[i].argv[argc] != NULL; argc++)
 	;
 
       argv = XALLOCAVEC (const char *, argc + 3);
 
       argv[0] = VALGRIND_PATH;
       argv[1] = "-q";
       for (j = 2; j < argc + 2; j++)
 	argv[j] = commands[i].argv[j - 2];
       argv[j] = NULL;
 
       commands[i].argv = argv;
       commands[i].prog = argv[0];
     }
 #endif
 
   /* Run each piped subprocess.  */
 
   pex = pex_init (PEX_USE_PIPES | ((report_times || report_times_to_file)
 				   ? PEX_RECORD_TIMES : 0),
 		  progname, temp_filename);
   if (pex == NULL)
     fatal_error (input_location, "pex_init failed: %m");
 
   for (i = 0; i < n_commands; i++)
     {
       const char *errmsg;
       int err;
       const char *string = commands[i].argv[0];
 int kkk;
 
 printf("\n------------------------------\n");
 for (kkk = 0; commands[i].argv[kkk]; kkk++)
 	printf("%s ", commands[i].argv[kkk]);
 printf("\n------------------------------\n");
 
       errmsg = pex_run (pex,
 			((i + 1 == n_commands ? PEX_LAST : 0)
 			 | (string == commands[i].prog ? PEX_SEARCH : 0)),
 			string, CONST_CAST (char **, commands[i].argv),
 			NULL, NULL, &err);
       if (errmsg != NULL)
 	{
 	  if (err == 0)
 	    fatal_error (input_location, errmsg);
 	  else
 	    {
 	      errno = err;
 	      pfatal_with_name (errmsg);
 	    }
 	}
 
       if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
   execution_count++;
 
   /* Wait for all the subprocesses to finish.  */
 
   {
     int *statuses;
     struct pex_time *times = NULL;
     int ret_code = 0;
 
     statuses = (int *) alloca (n_commands * sizeof (int));
     if (!pex_get_status (pex, n_commands, statuses))
       fatal_error (input_location, "failed to get exit status: %m");
 
     if (report_times || report_times_to_file)
       {
 	times = (struct pex_time *) alloca (n_commands * sizeof (struct pex_time));
 	if (!pex_get_times (pex, n_commands, times))
 	  fatal_error (input_location, "failed to get process times: %m");
       }
 
     pex_free (pex);
 
     for (i = 0; i < n_commands; ++i)
       {
 	int status = statuses[i];
 
 	if (WIFSIGNALED (status))
 	  switch (WTERMSIG (status))
 	    {
 	    case SIGINT:
 	    case SIGTERM:
 	      /* SIGQUIT and SIGKILL are not available on MinGW.  */
 #ifdef SIGQUIT
 	    case SIGQUIT:
 #endif
 #ifdef SIGKILL
 	    case SIGKILL:
 #endif
 	      /* The user (or environment) did something to the
 		 inferior.  Making this an ICE confuses the user into
 		 thinking there's a compiler bug.  Much more likely is
 		 the user or OOM killer nuked it.  */
 	      fatal_error (input_location,
 			   "%s signal terminated program %s",
 			   strsignal (WTERMSIG (status)),
 			   commands[i].prog);
 	      break;
 
 #ifdef SIGPIPE
 	    case SIGPIPE:
 	      /* SIGPIPE is a special case.  It happens in -pipe mode
 		 when the compiler dies before the preprocessor is
 		 done, or the assembler dies before the compiler is
 		 done.  There's generally been an error already, and
 		 this is just fallout.  So don't generate another
 		 error unless we would otherwise have succeeded.  */
 	      if (signal_count || greatest_status >= MIN_FATAL_STATUS)
 		{
 		  signal_count++;
 		  ret_code = -1;
 		  break;
 		}
 #endif
 	      /* FALLTHROUGH */
 
 	    default:
 	      /* The inferior failed to catch the signal.  */
 	      internal_error_no_backtrace ("%s signal terminated program %s",
 					   strsignal (WTERMSIG (status)),
 					   commands[i].prog);
 	    }
 	else if (WIFEXITED (status)
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
 	  {
 	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
 	       reproducible or not.  */
 	    const char *p;
 	    if (flag_report_bug
 		&& WEXITSTATUS (status) == ICE_EXIT_CODE
 		&& i == 0
 		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
 		&& ! strncmp (p + 1, "cc1", 3))
 	      try_generate_repro (commands[0].argv);
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
 	  }
 
 	if (report_times || report_times_to_file)
 	  {
 	    struct pex_time *pt = &times[i];
 	    double ut, st;
 
 	    ut = ((double) pt->user_seconds
 		  + (double) pt->user_microseconds / 1.0e6);
 	    st = ((double) pt->system_seconds
 		  + (double) pt->system_microseconds / 1.0e6);
 
 	    if (ut + st != 0)
 	      {
 		if (report_times)
 		  fnotice (stderr, "# %s %.2f %.2f\n",
 			   commands[i].prog, ut, st);
 
 		if (report_times_to_file)
 		  {
 		    int c = 0;
 		    const char *const *j;
 
 		    fprintf (report_times_to_file, "%g %g", ut, st);
 
 		    for (j = &commands[i].prog; *j; j = &commands[i].argv[++c])
 		      {
 			const char *p;
 			for (p = *j; *p; ++p)
 			  if (*p == '"' || *p == '\\' || *p == '$'
 			      || ISSPACE (*p))
 			    break;
 
 			if (*p)
 			  {
 			    fprintf (report_times_to_file, " \"");
 			    for (p = *j; *p; ++p)
 			      {
 				if (*p == '"' || *p == '\\' || *p == '$')
 				  fputc ('\\', report_times_to_file);
 				fputc (*p, report_times_to_file);
 			      }
 			    fputc ('"', report_times_to_file);
 			  }
 			else
 			  fprintf (report_times_to_file, " %s", *j);
 		      }
 
 		    fputc ('\n', report_times_to_file);
 		  }
 	      }
 	  }
       }
 
    if (commands[0].argv[0] != commands[0].prog)
      free (CONST_CAST (char *, commands[0].argv[0]));
 
     return ret_code;
   }
 }


*コメント [#d35e01e9]



トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS