@dram reported a build failure in FreeBSD at https://github.com/davidgiven/ack/issues/1#issuecomment-273668299 Linux manual for getopt(3) says: > If the first character of optstring is '-', then each nonoption > argv-element is handled as if it were the argument of an option with > character code 1.... > > The use of '+' and '-' in optstring is a GNU extension. GNU/Linux and OpenBSD handle '-' in this special way, but FreeBSD seems not to. If '-' is not special, then em_ego can't find its input file, so the build must fail. This commit stops using '-' in both em_b and em_ego, but doesn't change mcg. Also fix em_ego -O3 to not act like -O4.
		
			
				
	
	
		
			446 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			446 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id$ */
 | 
						|
 | 
						|
/* Driver program for the global optimizer. It might even become the global
 | 
						|
   optimizer itself one day ...
 | 
						|
*/
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdbool.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/wait.h>
 | 
						|
#include <string.h>
 | 
						|
#include "em_path.h"
 | 
						|
#include "system.h"
 | 
						|
#include "print.h"
 | 
						|
 | 
						|
enum
 | 
						|
{
 | 
						|
	NONE = 0,
 | 
						|
	IC,
 | 
						|
	CF,
 | 
						|
	IL,
 | 
						|
	CS,
 | 
						|
	SR,
 | 
						|
	UD,
 | 
						|
	LV,
 | 
						|
	RA,
 | 
						|
	SP,
 | 
						|
	BO,
 | 
						|
	CJ,
 | 
						|
	CA
 | 
						|
};
 | 
						|
 | 
						|
static const struct
 | 
						|
{
 | 
						|
	const char* name;
 | 
						|
	bool needsdescr;
 | 
						|
 | 
						|
} phase_data[] = {
 | 
						|
	{},
 | 
						|
	{ "ic" },
 | 
						|
	{ "cf" },
 | 
						|
	{ "il" },
 | 
						|
	{ "cs", true },
 | 
						|
	{ "sr" },
 | 
						|
	{ "ud", true },
 | 
						|
	{ "lv" },
 | 
						|
	{ "ra" },
 | 
						|
	{ "sp" },
 | 
						|
	{ "bo" },
 | 
						|
	{ "cj" },
 | 
						|
	{ "ca" },
 | 
						|
};
 | 
						|
 | 
						|
#define MAXUPHASES 64 /* max # of phases to be run */
 | 
						|
#define MAXARGS 1024 /* mar # of args */
 | 
						|
#define NTEMPS 4 /* # of temporary files; not tunable */
 | 
						|
 | 
						|
static char tmpbase[] = TMP_DIR "/ego.XXXXXX";
 | 
						|
static char ddump[128] = TMP_DIR; /* data label dump file */
 | 
						|
static char pdump[128] = TMP_DIR; /* procedure name dump file */
 | 
						|
static char tmpbufs[NTEMPS * 2][128] = {
 | 
						|
	TMP_DIR
 | 
						|
};
 | 
						|
 | 
						|
static int O2phases[] = { /* Passes for -O2 */
 | 
						|
	CJ, BO, SP, 0
 | 
						|
};
 | 
						|
 | 
						|
static int O3phases[] = { /* Passes for -O3 */
 | 
						|
	CS, SR, CJ, BO, SP, UD, LV, RA, 0
 | 
						|
};
 | 
						|
 | 
						|
static int O4phases[] = { /* Passes for -O4 */
 | 
						|
	IL, CF, CS, SR, CJ, BO, SP, UD, LV, RA, 0
 | 
						|
};
 | 
						|
 | 
						|
static int* Ophase = &O2phases[0]; /* default : -O2 */
 | 
						|
 | 
						|
static int nuphases; /* # of phases specified by user */
 | 
						|
static int uphases[MAXUPHASES + 1]; /* phases to be run */
 | 
						|
 | 
						|
static int nfiles = NTEMPS * 2 + 1; /* leave space for tempfilenames */
 | 
						|
static char* phargs[MAXARGS + 1];
 | 
						|
 | 
						|
static int keeptemps = 0;
 | 
						|
 | 
						|
static char** phase_args;
 | 
						|
static int nphase_args;
 | 
						|
 | 
						|
static const char* descr_file;
 | 
						|
static const char* opt_dir;
 | 
						|
static const char* prog_name;
 | 
						|
 | 
						|
static int v_flag;
 | 
						|
 | 
						|
static void
 | 
						|
cleanup()
 | 
						|
{
 | 
						|
	/*	Cleanup temporaries */
 | 
						|
 | 
						|
	if (!keeptemps)
 | 
						|
	{
 | 
						|
		register int i;
 | 
						|
 | 
						|
		for (i = NTEMPS * 2; i > 0; i--)
 | 
						|
		{
 | 
						|
			const char* f = phargs[i];
 | 
						|
			if (f != 0 && *f != '\0' && *f != '-')
 | 
						|
				(void)unlink(f);
 | 
						|
		}
 | 
						|
		if (ddump[0] != '\0')
 | 
						|
			(void)unlink(ddump);
 | 
						|
		if (pdump[0] != '\0')
 | 
						|
			(void)unlink(pdump);
 | 
						|
	}
 | 
						|
 | 
						|
	(void)unlink(tmpbase);
 | 
						|
}
 | 
						|
 | 
						|
/*VARARGS1*/
 | 
						|
static void
 | 
						|
    fatal(s, s2) char* s;
 | 
						|
char* s2;
 | 
						|
{
 | 
						|
	/*	A fatal error occurred; exit gracefully */
 | 
						|
 | 
						|
	fprint(STDERR, "%s: ", prog_name);
 | 
						|
	fprint(STDERR, s, s2);
 | 
						|
	fprint(STDERR, "\n");
 | 
						|
	cleanup();
 | 
						|
	sys_stop(S_EXIT);
 | 
						|
	/*NOTREACHED*/
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
    add_file(s) char* s;
 | 
						|
{
 | 
						|
	/*	Add an input file to the list */
 | 
						|
 | 
						|
	if (nfiles >= MAXARGS)
 | 
						|
		fatal("too many files");
 | 
						|
	phargs[nfiles++] = s;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
    add_uphase(p) int p;
 | 
						|
{
 | 
						|
	/*	Add an optimizer phase to the list of phases to run */
 | 
						|
 | 
						|
	if (nuphases >= MAXUPHASES)
 | 
						|
		fatal("too many phases");
 | 
						|
	uphases[nuphases++] = p;
 | 
						|
}
 | 
						|
 | 
						|
static void catch ()
 | 
						|
{
 | 
						|
	/*	Catch interrupts and exit gracefully */
 | 
						|
 | 
						|
	cleanup();
 | 
						|
	sys_stop(S_EXIT);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
old_infiles()
 | 
						|
{
 | 
						|
	/*	Remove old input files unless we have to keep them around. */
 | 
						|
 | 
						|
	register int i;
 | 
						|
 | 
						|
	if (phargs[1] == pdump || keeptemps)
 | 
						|
		return;
 | 
						|
 | 
						|
	for (i = 1; i <= NTEMPS; i++)
 | 
						|
		(void)unlink(phargs[i]);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
get_infiles()
 | 
						|
{
 | 
						|
	/*	Make output temps from previous phase input temps of next phase. */
 | 
						|
 | 
						|
	register int i;
 | 
						|
	char** dst = &phargs[1];
 | 
						|
	char** src = &phargs[NTEMPS + 1];
 | 
						|
 | 
						|
	for (i = 1; i <= NTEMPS; i++)
 | 
						|
	{
 | 
						|
		*dst++ = *src++;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
new_outfiles()
 | 
						|
{
 | 
						|
	static int tmpindex = 0;
 | 
						|
	static int Bindex = 0;
 | 
						|
	static char dig1 = '1';
 | 
						|
	static char dig2 = '0';
 | 
						|
	register int i;
 | 
						|
	char** dst = &phargs[NTEMPS + 1];
 | 
						|
 | 
						|
	if (!Bindex)
 | 
						|
		Bindex = strlen(tmpbufs[0]) - 2;
 | 
						|
 | 
						|
	for (i = 1; i <= NTEMPS; i++)
 | 
						|
	{
 | 
						|
		*dst = tmpbufs[tmpindex];
 | 
						|
		(*dst)[Bindex - 1] = dig2;
 | 
						|
		(*dst)[Bindex] = dig1;
 | 
						|
		tmpindex++;
 | 
						|
		dst++;
 | 
						|
	}
 | 
						|
	if (tmpindex >= 2 * NTEMPS)
 | 
						|
		tmpindex = 0;
 | 
						|
	if (++dig1 > '9')
 | 
						|
	{
 | 
						|
		++dig2;
 | 
						|
		dig1 = '0';
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
    run_phase(phase) int phase;
 | 
						|
{
 | 
						|
	/*	Run one phase of the global optimizer; special cases are
 | 
						|
	IC and CA.
 | 
						|
  */
 | 
						|
	static int flags_added;
 | 
						|
	register int argc;
 | 
						|
	register int i;
 | 
						|
	char buf[256];
 | 
						|
	int pid, status;
 | 
						|
 | 
						|
	/* Skip this phase if it requires a descr file and one hasn't been
 | 
						|
	 * provided. */
 | 
						|
 | 
						|
	if (phase_data[phase].needsdescr && !descr_file)
 | 
						|
		return;
 | 
						|
 | 
						|
	phargs[0] = buf;
 | 
						|
	(void)strcpy(buf, opt_dir);
 | 
						|
	(void)strcat(buf, "/");
 | 
						|
	(void)strcat(buf, phase_data[phase].name);
 | 
						|
 | 
						|
	switch (phase)
 | 
						|
	{
 | 
						|
		case IC:
 | 
						|
			/* always first */
 | 
						|
			phargs[1] = pdump;
 | 
						|
			phargs[2] = ddump;
 | 
						|
			for (i = 3; i <= NTEMPS; i++)
 | 
						|
				phargs[i] = "-";
 | 
						|
			new_outfiles();
 | 
						|
			argc = nfiles;
 | 
						|
			phargs[argc] = 0;
 | 
						|
			break;
 | 
						|
 | 
						|
		case CA:
 | 
						|
			/* always last */
 | 
						|
			old_infiles();
 | 
						|
			get_infiles();
 | 
						|
			phargs[NTEMPS + 1] = pdump;
 | 
						|
			phargs[NTEMPS + 2] = ddump;
 | 
						|
			for (i = NTEMPS + 3; i <= 2 * NTEMPS; i++)
 | 
						|
				phargs[i] = "-";
 | 
						|
			argc = 2 * NTEMPS + 1;
 | 
						|
			phargs[argc] = 0;
 | 
						|
			break;
 | 
						|
 | 
						|
		default:
 | 
						|
		{
 | 
						|
			old_infiles();
 | 
						|
			get_infiles();
 | 
						|
			new_outfiles();
 | 
						|
 | 
						|
			argc = 2 * NTEMPS + 1;
 | 
						|
			if (descr_file)
 | 
						|
			{
 | 
						|
				phargs[argc++] = "-M";
 | 
						|
				phargs[argc++] = descr_file;
 | 
						|
			}
 | 
						|
 | 
						|
			for (i=0; i<nphase_args; i++)
 | 
						|
				phargs[argc++] = phase_args[i];
 | 
						|
 | 
						|
			phargs[argc] = NULL;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ((pid = fork()) < 0)
 | 
						|
	{
 | 
						|
		fatal("Could not fork");
 | 
						|
	}
 | 
						|
	else if (pid == 0)
 | 
						|
	{
 | 
						|
		if (v_flag)
 | 
						|
		{
 | 
						|
			register int i = 0;
 | 
						|
 | 
						|
			while (phargs[i])
 | 
						|
			{
 | 
						|
				fprint(STDERR, "%s ", phargs[i]);
 | 
						|
				i++;
 | 
						|
			}
 | 
						|
			fprint(STDERR, "\n");
 | 
						|
		}
 | 
						|
		(void)execv(phargs[0], phargs);
 | 
						|
		fatal("Could not exec %s", phargs[0]);
 | 
						|
		sys_stop(S_EXIT);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		while (wait(&status) != pid) /* nothing */
 | 
						|
			;
 | 
						|
		if ((status & 0177) != 0)
 | 
						|
		{
 | 
						|
			fatal("%s got a unix signal", phargs[0]);
 | 
						|
		}
 | 
						|
		if (((status >> 8) & 0377) != 0)
 | 
						|
		{
 | 
						|
			cleanup();
 | 
						|
			sys_stop(S_EXIT);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int main(int argc, char* argv[])
 | 
						|
{
 | 
						|
	int opt;
 | 
						|
	int i;
 | 
						|
 | 
						|
	if (signal(SIGHUP, catch) == SIG_IGN)
 | 
						|
		(void)signal(SIGHUP, SIG_IGN);
 | 
						|
	if (signal(SIGQUIT, catch) == SIG_IGN)
 | 
						|
		(void)signal(SIGQUIT, SIG_IGN);
 | 
						|
	if (signal(SIGINT, catch) == SIG_IGN)
 | 
						|
		(void)signal(SIGINT, SIG_IGN);
 | 
						|
	prog_name = argv[0];
 | 
						|
 | 
						|
	nphase_args = 0;
 | 
						|
	phase_args = &argv[1];
 | 
						|
 | 
						|
	opterr = 0;
 | 
						|
	for (;;)
 | 
						|
	{
 | 
						|
		int opt = getopt(argc, argv, "M:P:O:vt");
 | 
						|
		if (opt == -1)
 | 
						|
			break;
 | 
						|
 | 
						|
		switch (opt)
 | 
						|
		{
 | 
						|
			case 'M':
 | 
						|
				descr_file = optarg;
 | 
						|
				break;
 | 
						|
 | 
						|
			case 'P':
 | 
						|
				opt_dir = optarg;
 | 
						|
				break;
 | 
						|
 | 
						|
			case 'O':
 | 
						|
			{
 | 
						|
				int o = atoi(optarg);
 | 
						|
				if (o <= 2)
 | 
						|
					Ophase = &O2phases[0];
 | 
						|
				else if (o == 3)
 | 
						|
					Ophase = &O3phases[0];
 | 
						|
				else
 | 
						|
					Ophase = &O4phases[0];
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
			case 't':
 | 
						|
				keeptemps = 1;
 | 
						|
				goto addopt;
 | 
						|
 | 
						|
			case 'v':
 | 
						|
				v_flag = 1;
 | 
						|
				goto addopt;
 | 
						|
 | 
						|
			case '?':
 | 
						|
			addopt:
 | 
						|
				phase_args[nphase_args++] = argv[optind - 1];
 | 
						|
				break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	for (i = optind; i < argc; i++)
 | 
						|
		add_file(argv[i]);
 | 
						|
 | 
						|
	phase_args[nphase_args] = 0;
 | 
						|
	if (nuphases)
 | 
						|
		Ophase = uphases;
 | 
						|
 | 
						|
	if (nfiles == 2 * NTEMPS + 1)
 | 
						|
	{
 | 
						|
		/* 2*NTEMPS+1 was the starting value; nothing to do */
 | 
						|
		sys_stop(S_END);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!opt_dir)
 | 
						|
	{
 | 
						|
		fatal("no correct -P flag given");
 | 
						|
	}
 | 
						|
 | 
						|
	close(mkstemp(tmpbase));
 | 
						|
	strcpy(ddump, tmpbase);
 | 
						|
	strcpy(pdump, tmpbase);
 | 
						|
	strcpy(tmpbufs[0], tmpbase);
 | 
						|
 | 
						|
	if (keeptemps)
 | 
						|
	{
 | 
						|
		(void)strcpy(ddump, ".");
 | 
						|
		(void)strcpy(pdump, ".");
 | 
						|
		(void)strcpy(tmpbufs[0], ".");
 | 
						|
	}
 | 
						|
	(void)strcat(ddump, "dd");
 | 
						|
	(void)strcat(pdump, "pd");
 | 
						|
 | 
						|
	(void)strcat(tmpbufs[0], "A.BB");
 | 
						|
	for (i=1; i<(2 * NTEMPS); i++)
 | 
						|
		(void)strcpy(tmpbufs[i], tmpbufs[0]);
 | 
						|
 | 
						|
	i = strlen(tmpbufs[0]) - 4;
 | 
						|
	tmpbufs[0][i] = 'p';
 | 
						|
	tmpbufs[NTEMPS + 0][i] = 'p';
 | 
						|
	tmpbufs[1][i] = 'd';
 | 
						|
	tmpbufs[NTEMPS + 1][i] = 'd';
 | 
						|
	tmpbufs[2][i] = 'l';
 | 
						|
	tmpbufs[NTEMPS + 2][i] = 'l';
 | 
						|
	tmpbufs[3][i] = 'b';
 | 
						|
	tmpbufs[NTEMPS + 3][i] = 'b';
 | 
						|
 | 
						|
	run_phase(IC);
 | 
						|
	run_phase(CF);
 | 
						|
	while (*Ophase)
 | 
						|
	{
 | 
						|
		run_phase(*Ophase++);
 | 
						|
	}
 | 
						|
	run_phase(CA);
 | 
						|
	cleanup();
 | 
						|
	sys_stop(S_END);
 | 
						|
	/*NOTREACHED*/
 | 
						|
}
 |