1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
## 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`.
The `cppawk` `man` page has the invocation and usage 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.
## Roadmap
`cppawk` is been carefully developed, and has a regression test suite.
Nearly every feature and fix was developed by first writing one or more
failing tests and getting them to pass. The script is stable and nearly
feature-complete, since it is out of the project scope to modify Awk
or the C preprocessor. The remaining work is likely solving portability
issues, like using with different implementations of the C preprocessor.
Among future directions for `cppawk` is the development of a small
library of useful standard headers. The foundation has been laid for
this because when `#include <...>` is used (angle bracket include), it looks in
a subdirectory called `cppawk-include` which is in the same directory as
itself. For instance if `cppawk` is `/usr/bin/cppawk`, it looks in
`/usr/bin/cppawk-include`. This library directory is currently empty.
## Why?
* Why not?
* You know Awk. You know C preprocessing inside out. Now use two things
that you know, together, in obvious ways.
* Awks other than GNU Awk have poor support for making a program out of
multiple files. No compile meta-programming, or conditional selection
of code.
* Other minor benefits: Awk has no comments other than from a `#`
character to the end of the line. You get `/* ... */` comments
with `cppawk`, and also `#if 0` ... `#endif` for temporarily
disabling code.
## But GNU Awk has `@include`?
* GNU Awk's `@include` isn't a full preprocessor. There are no conditional
expressions, and no macros.
* It is only implemented in GNU Awk.
* It provides no way to capture all the included output.
* The way `@include` searches for files is inferior to `cpp`. GNU Awk's
include search is driven by the `AWKPATH` variable which brings in all the
disadvantages shared by shared by `PATH`-like variables. In contrast `cpp`
implements the familiar behavior that an `#include "..."` directive is
resolved relative to the directory of the file which contains that
`#include` directive. No configuration is required for a program to find
all of its included pieces.
## I use `awk` on embedded systems with no `cpp`!
Though packaged that way, `cppawk` doesn't have to be used as an interpreter
which preprocesses and runs the code. Preprocessed code can be captured with
the `--prepro-only` option, and then transferred to a target system for
execution with its Awk.
**Tip**: it may be a good idea to tweak `cppawk` so that it doesn't define the
`__gawk__` symbol, if your target system's Awk isn't GNU Awk.
|