~sircmpwn/ctools

echo: Improve POSIX compliance v1 PROPOSED

Haelwenn (lanodan) Monnier
Haelwenn (lanodan) Monnier: 2
 echo: Improve POSIX compliance
 echo: Improve POSIX compliance

 4 files changed, 48 insertions(+), 64 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/~sircmpwn/ctools/patches/9627/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH] echo: Improve POSIX compliance Export this patch

Haelwenn (lanodan) Monnier
* `--` is to be treated as a string so getopt() can’t be used
* -n is to be treated as a string in XSI
* escape codes do not seem to need -n in XSI
* Add simple non-XSI code
---
 src/echo.c | 38 +++++++++-----------------------------
 test/echo  | 18 +++++++++++++++---
 2 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/src/echo.c b/src/echo.c
index fcd33df..585d3c6 100644
--- a/src/echo.c
+++ b/src/echo.c
@@ -1,36 +1,17 @@
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static void
usage(void)
{
	fprintf(stderr, "usage: echo [-n] [string...]");
}

int
main(int argc, char *argv[])
{
	int nflag = 0;
	char opt;

	while ((opt = getopt(argc, argv, "n")) != -1) {
		switch (opt) {
		case 'n':
			nflag = 1;
			break;
		default:
			usage();
			return 1;
		}
	}

	for (int i = optind; i < argc; ++i) {
#ifndef _XOPEN_SOURCE
	// Note: Outside of XSI -n is implementation defined, treat as string
	for (int i = 1; i < argc; ++i) {
		printf(argv[i]);
#else
	for (int i = 1; i < argc; ++i) {
		char *arg = NULL;
		for (arg = argv[i]; *arg; arg++) {
			if (arg[0] == '\\' && nflag) {
			if (arg[0] == '\\') {
				switch (arg[1]) {
				case 'a':
					putchar('\a');
@@ -80,8 +61,7 @@ main(int argc, char *argv[])
			putchar(' ');
		}
	}
#endif

	if (!nflag) {
		putchar('\n');
	}
	putchar('\n');
}
diff --git a/test/echo b/test/echo
index 61f5fbf..f518e5f 100644
--- a/test/echo
+++ b/test/echo
@@ -13,17 +13,29 @@ should_handle_two_string() (
)

should_handle_tab_char() (
	ct="$(./echo -n "\tthis is a test string")"
	ct="$(./echo "\tthis is a test string")"
	[ "$ct" = '	this is a test string' ]
)

should_handle_c_escape_char() (
	ct="$(./echo -n "this is a \ctest string")"
	ct="$(./echo "this is a \ctest string")"
	[ "$ct" = "this is a " ]
)

should_not_handle_double_dash() {
	ct="$(./echo -- "this is a test string")"
	[ "$ct" = "-- this is a test string" ]
}

should_not_handle_dash_n() {
	ct="$(./echo -n "this is a test string")"
	[ "$ct" = "-n this is a test string" ]
}

runtests \
	should_handle_one_string \
	should_handle_two_string \
	should_handle_tab_char \
	should_handle_c_escape_char
	should_handle_c_escape_char \
	should_not_handle_double_dash \
	should_not_handle_dash_n
-- 
2.24.1
Haelwenn (lanodan) Monnier
Sorry just found a bug in the non-XSI version (lacks spaces between args).

Will send a V2.

[PATCH v2] echo: Improve POSIX compliance Export this patch

Haelwenn (lanodan) Monnier
* `--` is to be treated as a string so getopt() can’t be used
* -n is to be treated as a string in XSI
* escape codes do not seem to need -n in XSI
* Add simple non-XSI code
---
 src/echo.c | 38 +++++++++-----------------------------
 test/echo  | 18 +++++++++++++++---
 2 files changed, 24 insertions(+), 32 deletions(-)

diff --git a/src/echo.c b/src/echo.c
index fcd33df..65a9027 100644
--- a/src/echo.c
+++ b/src/echo.c
@@ -1,36 +1,17 @@
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static void
usage(void)
{
	fprintf(stderr, "usage: echo [-n] [string...]");
}

int
main(int argc, char *argv[])
{
	int nflag = 0;
	char opt;

	while ((opt = getopt(argc, argv, "n")) != -1) {
		switch (opt) {
		case 'n':
			nflag = 1;
			break;
		default:
			usage();
			return 1;
		}
	}

	for (int i = optind; i < argc; ++i) {
#ifndef _XOPEN_SOURCE
	// Note: Outside of XSI -n is implementation defined, treat as string
	for (int i = 1; i < argc; ++i) {
		printf("%s ", argv[i]);
#else
	for (int i = 1; i < argc; ++i) {
		char *arg = NULL;
		for (arg = argv[i]; *arg; arg++) {
			if (arg[0] == '\\' && nflag) {
			if (arg[0] == '\\') {
				switch (arg[1]) {
				case 'a':
					putchar('\a');
@@ -80,8 +61,7 @@ main(int argc, char *argv[])
			putchar(' ');
		}
	}
#endif

	if (!nflag) {
		putchar('\n');
	}
	putchar('\n');
}
diff --git a/test/echo b/test/echo
index 61f5fbf..f518e5f 100644
--- a/test/echo
+++ b/test/echo
@@ -13,17 +13,29 @@ should_handle_two_string() (
)

should_handle_tab_char() (
	ct="$(./echo -n "\tthis is a test string")"
	ct="$(./echo "\tthis is a test string")"
	[ "$ct" = '	this is a test string' ]
)

should_handle_c_escape_char() (
	ct="$(./echo -n "this is a \ctest string")"
	ct="$(./echo "this is a \ctest string")"
	[ "$ct" = "this is a " ]
)

should_not_handle_double_dash() {
	ct="$(./echo -- "this is a test string")"
	[ "$ct" = "-- this is a test string" ]
}

should_not_handle_dash_n() {
	ct="$(./echo -n "this is a test string")"
	[ "$ct" = "-n this is a test string" ]
}

runtests \
	should_handle_one_string \
	should_handle_two_string \
	should_handle_tab_char \
	should_handle_c_escape_char
	should_handle_c_escape_char \
	should_not_handle_double_dash \
	should_not_handle_dash_n
-- 
2.24.1