commit ce5d851a7caa59e8c909bdd222bf4f8f35980a6d
parent 823a5e4e7d69b5f93b57c21eff6a3db8e5558924
Author: Jacob R. Edwards <n/a>
Date: Mon, 28 Nov 2022 21:58:58 -0600
Add awk libraries
I had written some useful, general purpose functions for awk(1)
some time ago and never put them anywhere.
The most useful is exec.awk. It contains functions for building
sh(1) commands using awk arrays--Works like execlp(3), except you
cannot specify argv[0] separate from the executable file.
Also very useful, although cumbersome to use due to an oversight
in awk (or rather, me wanting to use awk in a way it shouldn't be),
is getopt.awk. It provides a getopt(3)-like command line interface,
caveat being that awk want's to process arguments in the same way.
One solution to this problem is to execute the script using a wrapper
which alters arguments, i.e.:
#!/bin/sh
exec awk -f script -- "$@"
Diffstat:
3 files changed, 82 insertions(+), 0 deletions(-)
diff --git a/local/Makefile b/local/Makefile
@@ -1,6 +1,7 @@
lib = ../lib
dest = ${HOME}
mods =\
+ awk\
bin\
dillo\
git\
diff --git a/local/awk/lib/exec.awk b/local/awk/lib/exec.awk
@@ -0,0 +1,28 @@
+# Copyright 2022 Jacob R. Edwards
+# Awk exec function
+#
+# The shquote() function quotes a string for sh(1).
+#
+# The getcmd() function concatnates the given argument array on
+# space after quoting each one for sh(1) using shquote().
+#
+# The exec() function executes the command returned by getcmd()
+# using the system() builtin.
+
+function shquote(arg) {
+ if (!match(arg, "[|&;<>()$`\\\"' \n*?[#~=%]"))
+ return arg;
+ gsub("'", "'\\''", arg);
+ return "'" arg "'";
+}
+
+function getcmd(argv, _) {
+ _ = shquote(argv[1]);
+ for (i = 2; argv[i]; ++i)
+ _ = _ " " shquote(argv[i]);
+ return _;
+}
+
+function exec(argv) {
+ return system(getcmd(argv));
+}
diff --git a/local/awk/lib/getopt.awk b/local/awk/lib/getopt.awk
@@ -0,0 +1,53 @@
+# Copyright 2021 Jacob R. Edwards
+# License: GPLv3
+# Awk shift and getopt functions
+#
+# Shift shifts ARGV to the left by one and updates ARGC.
+#
+# Getopt returns zero on success and an error of the form 'offending
+# character: error message' on failure. Options are accessed with the
+# global hash-map opts, where opts[char] is either true or the given
+# argument.
+
+function shift()
+{
+ for (i = 2; i <= ARGC; ++i)
+ ARGV[i - 1] = ARGV[i];
+ --ARGC;
+}
+
+# Only optstr is required, the others are overwritten anyway.
+function getopt(optstr, chars, len)
+{
+ for (; ARGV[1]; shift()) {
+ len = split(ARGV[1], chars, "");
+ if (chars[1] != "-")
+ return 0;
+ if (len == 2 && chars[2] == "-") {
+ shift();
+ return 0;
+ }
+
+ for (i = 2; i <= len; ++i) {
+ if (index(optstr, chars[i] ":")) {
+ if (i < len) {
+ opts[chars[i]] = substr(ARGV[1], i + 1);
+ break;
+ } else if (ARGV[2]) {
+ opts[chars[i]] = ARGV[2];
+ shift();
+ } else {
+ return chars[i] ": Requires an argument";
+ }
+ } else if (index(optstr, chars[i])) {
+ opts[chars[i]] = 1;
+ } else {
+ return chars[i] ": Not an option";
+ }
+ }
+
+ shift();
+ }
+
+ return 0;
+}