aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-03-22 15:07:03 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-03-22 15:07:03 -0700
commit127fd1981aa50beac05b1e2348c70d690e4e4070 (patch)
tree64b1c07aa6e34d10e7767e79e3871bcbe5eee639
parent86a3448b554e2c9963eed87a43b2db2a8156f842 (diff)
downloadcppawk-127fd1981aa50beac05b1e2348c70d690e4e4070.tar.gz
cppawk-127fd1981aa50beac05b1e2348c70d690e4e4070.tar.bz2
cppawk-127fd1981aa50beac05b1e2348c70d690e4e4070.zip
Add markdown README.
-rw-r--r--README.md93
1 files changed, 93 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..571ff7b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,93 @@
+## What is `cppawk`?
+
+`cppawk` is a tiny shell script that is used like `awk`. It invokes
+the C preprocessor (GNU `cpp`) on the Awk code and calls `gawk`.
+
+`cppawk` understands the basic Awk options like `-F` and `-v`, and also
+understand common `cpp` options like `-I` and `-Dmacro=value`.
+
+There is a `man` page with all the details.
+
+For instance, if we define a file called `awkloop.h` which has these contents
+
+ :::c
+ #define awkloop(file) for (; getline < file || (close(file) && 0); )
+ #define nextrec continue
+ #define rule(cond) if (cond)
+
+Then this sort of code is possible:
+
+ ::c
+ #include "awkloop.h"
+
+ function main()
+ {
+ awkloop ("/proc/mounts") {
+ rule ($3 != "ext4") { nextrec }
+ rule ($2 == "/") { print $1 }
+ }
+ }
+
+ BEGIN {
+ main()
+ }
+
+We have implemented a facsimile of an Awk input scanning loop inside a function
+with a bit of syntactic sugar.
+
+If you know C and the C preprocessor, and if you know Awk, the utility
+and applications for this should be obvious; you may skip the next section
+and go get it!
+
+## Why or who might use `cppawk`?
+
+0. Why not? It's just a tiny shell script.
+
+1. You know how to use the C preprocessor, and are doing work on a system or
+ situation where you can count on it being installed, such as build
+ scripts or continuous integration. Make use of what you know.
+
+2. It makes some things easy, like making a program out of multiple
+ files, which easily find each other in the same directory or relative
+ path. Or macros, for some syntactic sugars.
+
+3. Though GNU Awk has `@include`, that feature provides no preprocessor
+ features and works with GNU Awk only. `cppawk` calls `gawk`, but can
+ easily be tweaked to target any Awk; any Awk can have file inclusion.
+ There is the possibility of using `#ifdef` to make code
+ work on different Awks from one file. (The default cppawk installation uses
+ gawk, and also defines `__gawk__` as 1, which you can test for.)
+
+4. Comments. Awk has no comments that don't end at the end of
+ the line; `cppawk` gives you `/*...*/`.
+
+5. Temporarily disabling code with `#if 0` ... `#endif` rather than
+ fiddling with hash marks.
+
+6. Exploration: Awk is syntactically C like, but not C: what
+ implications does that have for writing macros? You can discover some
+ new-ish techniques, though it won't be earth-shattering.
+
+7. Weird access to some host attributes intended for C:
+
+ $ cppawk '#include <limits.h>
+ BEGIN { print PATH_MAX, ULONG_MAX }'
+ 4096 214748364701
+
+ this sort of thing can be useful in devops land.
+
+## How about systems that have `awk` but no `cpp`?
+
+`cppawk` is used directly on systems that have `cpp`, as if
+it were an Awk implementation.
+
+`cppawk --prepro-only` will generate the preprocessed Awk code,
+which can be captured and transferred to a system that has no
+preprocessor installed, such as an embedded board that has
+BusyBox Awk.
+
+Of course, capturing the preprocessed output has other uses.
+It's possible to generate different versions of an Awk program
+by using `cppawk --prepro-only` in conjunction with conditional
+preprocessing which reacts to different values of a macro defined
+on the command line via `-D`.