~mcf/cproc

driver: Make stage selection flags order-independent v1 PROPOSED

Lassi Pulkkinen: 2
 driver: Make stage selection flags order-independent
 driver: Pass default -MT and -MF explicitly to cpp when -o is used

 2 files changed, 47 insertions(+), 11 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~mcf/cproc/patches/52801/mbox | git am -3
Learn more about email & git

[PATCH 1/2] driver: Make stage selection flags order-independent Export this patch

When multiple of -E, -M, -emit-qbe, -S and -c are specified, always
select the one corresponding to the earliest build stage. This matches
GCC and Clang behavior, and makes it impossible to get the driver to
pass -M output to the compiler. Well, except for -MD -MF -, but the only
thing that could reasonably be done about that is displaying a better
error message, and cproc will eventually stop using an external
preprocessor anyway.
---
 driver.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/driver.c b/driver.c
index 853c20e..4f82644 100644
--- a/driver.c
+++ b/driver.c
@@ -431,7 +431,8 @@ main(int argc, char *argv[])
		} else if (strcmp(arg, "-static") == 0) {
			arrayaddptr(&stages[LINK].cmd, arg);
		} else if (strcmp(arg, "-emit-qbe") == 0) {
			last = COMPILE;
			if (last > COMPILE)
				last = COMPILE;
		} else if (strcmp(arg, "-include") == 0 || strcmp(arg, "-idirafter") == 0 || strcmp(arg, "-isystem") == 0 || strcmp(arg, "-iquote") == 0) {
			if (!--argc)
				usage(NULL);
@@ -455,14 +456,16 @@ main(int argc, char *argv[])
				usage(NULL);
			switch (arg[1]) {
			case 'c':
				last = ASSEMBLE;
				if (last > ASSEMBLE)
					last = ASSEMBLE;
				break;
			case 'D':
				arrayaddptr(&stages[PREPROCESS].cmd, "-D");
				arrayaddptr(&stages[PREPROCESS].cmd, nextarg(&argv));
				break;
			case 'E':
				last = PREPROCESS;
				if (last > PREPROCESS)
					last = PREPROCESS;
				break;
			case 'g':
				/* ignore */
@@ -485,7 +488,8 @@ main(int argc, char *argv[])
			case 'M':
				if (strcmp(arg, "-M") == 0 || strcmp(arg, "-MM") == 0) {
					arrayaddptr(&stages[PREPROCESS].cmd, arg);
					last = PREPROCESS;
					if (last > PREPROCESS)
						last = PREPROCESS;
				} else if (strcmp(arg, "-MD") == 0 || strcmp(arg, "-MMD") == 0) {
					arrayaddptr(&stages[PREPROCESS].cmd, arg);
				} else if (strcmp(arg, "-MT") == 0 || strcmp(arg, "-MF") == 0) {
@@ -507,7 +511,8 @@ main(int argc, char *argv[])
				arrayaddptr(&stages[PREPROCESS].cmd, "-P");
				break;
			case 'S':
				last = CODEGEN;
				if (last > CODEGEN)
					last = CODEGEN;
				break;
			case 's':
				arrayaddptr(&stages[LINK].cmd, "-s");
-- 
2.45.0

[PATCH 2/2] driver: Pass default -MT and -MF explicitly to cpp when -o is used Export this patch

So that cproc -MD -c a.c -o obj/a.o produces obj/a.d instead of a.d.

A weird edge case is cproc -MD a.c b.c -o bin, which will create a bin.d
containing the deps for a.c, then overwrite it with the deps for only
b.c. Turns out that GCC and Clang behave the same way.
---
 driver.c | 43 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/driver.c b/driver.c
index 4f82644..32533cf 100644
--- a/driver.c
+++ b/driver.c
@@ -104,6 +104,17 @@ detectfiletype(const char *name)
	return OBJ;
}

static const char *
stripdir(const char *name)
{
	const char *slash;

	slash = strrchr(name, '/');
	if (slash)
		name = slash + 1;
	return name;
}

static char *
changeext(const char *name, const char *ext)
{
@@ -112,9 +123,9 @@ changeext(const char *name, const char *ext)
	size_t baselen;

	slash = strrchr(name, '/');
	if (slash)
		name = slash + 1;
	dot = strrchr(name, '.');
	if (dot < slash)
		dot = NULL;
	baselen = dot ? (size_t)(--dot - name + 1) : strlen(name);
	result = xmalloc(baselen + strlen(ext) + 2);
	memcpy(result, name, baselen);
@@ -238,11 +249,11 @@ buildobj(struct input *input, char *output)
		if (strcmp(output, "-") == 0)
			output = NULL;
	} else if (input->stages & 1<<ASSEMBLE) {
		output = changeext(input->name, "o");
		output = changeext(stripdir(input->name), "o");
	} else if (input->stages & 1<<CODEGEN) {
		output = changeext(input->name, "s");
		output = changeext(stripdir(input->name), "s");
	} else if (input->stages & 1<<COMPILE) {
		output = changeext(input->name, "qbe");
		output = changeext(stripdir(input->name), "qbe");
	}
	if (strcmp(input->name, "-") == 0)
		input->name = NULL;
@@ -371,6 +382,7 @@ main(int argc, char *argv[])
	enum stage last = LINK;
	enum filetype filetype = 0;
	char *arg, *end, *output = NULL, *arch, *qbearch;
	bool mtauto = false, mfauto = false, mtoverride = false, mfoverride = false;
	struct array inputs = {0}, *cmd;
	struct input *input;
	size_t i;
@@ -490,13 +502,23 @@ main(int argc, char *argv[])
					arrayaddptr(&stages[PREPROCESS].cmd, arg);
					if (last > PREPROCESS)
						last = PREPROCESS;
					mtauto = true;
				} else if (strcmp(arg, "-MD") == 0 || strcmp(arg, "-MMD") == 0) {
					arrayaddptr(&stages[PREPROCESS].cmd, arg);
				} else if (strcmp(arg, "-MT") == 0 || strcmp(arg, "-MF") == 0) {
					mtauto = true;
					mfauto = true;
				} else if (strcmp(arg, "-MT") == 0) {
					if (!--argc)
						usage(NULL);
					arrayaddptr(&stages[PREPROCESS].cmd, arg);
					arrayaddptr(&stages[PREPROCESS].cmd, *++argv);
					mtoverride = true;
				} else if (strcmp(arg, "-MF") == 0) {
					if (!--argc)
						usage(NULL);
					arrayaddptr(&stages[PREPROCESS].cmd, arg);
					arrayaddptr(&stages[PREPROCESS].cmd, *++argv);
					mfoverride = true;
				} else {
					usage(NULL);
				}
@@ -567,6 +589,15 @@ main(int argc, char *argv[])
		}
	}

	if (output && mtauto && !mtoverride) {
		arrayaddptr(&stages[PREPROCESS].cmd, "-MT");
		arrayaddptr(&stages[PREPROCESS].cmd, output);
	}
	if (output && mfauto && !mfoverride) {
		arrayaddptr(&stages[PREPROCESS].cmd, "-MF");
		arrayaddptr(&stages[PREPROCESS].cmd, changeext(output, "d"));
	}

	for (i = 0; i < LEN(stages); ++i)
		stages[i].cmdbase = stages[i].cmd.len;
	if (inputs.len == 0)
-- 
2.45.0