GNU Awk has a switch statement.
In cppawk I made a case statement which translates to GNU Awk switch,
but supports non-GNU Awk.
Check this out:
#include <case.h>
{
case ($0) {
of ("foo") {
print "** foo case: fallthrough!"
}
of ("bar", "xyzzy") {
print "** bar/xyzzy case"
cbreak;
}
matching (/x/) {
print "** /x/ case"
cbreak;
}
otherwise {
print "** default"
}
}
}
Translate for GNU Awk:
$ ./cppawk --prepro-only -f case.cwk
# 1 "<stdin>"
[ snip ]
# 33 "./cppawk-include/case.h" 2
# 2 "case.cwk" 2
{
switch ($0) {
case "foo": {
print "** foo case: fallthrough!"
}
case "bar": case "xyzzy": {
print "** bar/xyzzy case"
break;
}
case /x/: {
print "** /x/ case"
break;
}
default: {
print "** default"
}
}
}
Translate for Mawk:
$ ./cppawk --prepro-only --awk=mawk -f case.cwk
# 1 "<stdin>"
[snip]
# 33 "./cppawk-include/case.h" 2
# 2 "case.cwk" 2
{
for ((__once = 1) && (__pass = 0) || (__val = $0); __once; __once = 0) {
if (__pass || ((__val == ("foo"))) && (__pass = 1)) {
print "** foo case: fallthrough!"
}
if (__pass || ((__val == ("bar")) || (__val == ("xyzzy"))) && (__pass = 1)) {
print "** bar/xyzzy case"
break;
}
if (__pass || ((__val ~ (/x/))) && (__pass = 1)) {
print "** /x/ case"
break;
}
if (__pass = 1) {
print "** default"
}
}
}
The temporary variables are a bit ugly. In a function you can declare them like
this:
function fun(arg1, arg2,
local_var, case_temps)
case_temps expands to __val, __once, __pass for that implementation.
Some test cases and tweaking is needed to get the construct to work if nested with itself.
I may switch it (pun intended) to have no fallthough by default between cases.
Perhaps a fallthrough statement can request it explicitly. A good way to
do that when targetting the Gawk switch is not obvious.
On 3/28/2022 2:09 AM, Kaz Kylheku wrote:
GNU Awk has a switch statement.
In cppawk I made a case statement which translates to GNU Awk switch,
but supports non-GNU Awk.
If I want portable code why wouldn't I simply write portable code?
s = $0
if (s == "foo") {
print "** foo case: fallthrough!"
}
if ( (s == "bar") || (s == "xyzzy") ) {
print "** bar/xyzzy case"
}
With "cppawk" you seem to be solving a problem that doesn't exist by
creating a real problem - introducing a private tool that'd be required
to parse the code and the necessity for people to have to look up ".h"
files to figure out what the language constructs in the code mean and
the potential for the tokens in the .h files to clash with variables or
other language constructs used in the script.
On 2022-03-28, Ed Morton <mortonspam@gmail.com> wrote:
On 3/28/2022 2:09 AM, Kaz Kylheku wrote:
GNU Awk has a switch statement.
In cppawk I made a case statement which translates to GNU Awk switch,
but supports non-GNU Awk.
If I want portable code why wouldn't I simply write portable code?
My use case is that what I *have* is nonportable code, and I want
GNU Awk to keep seeing more or less that same nonportable code while
I make it run on another implementation also.
Furthermore, I have reached a more or less final version of the macro
which is safer to use than switch: each clause must explicitly break, fall-through or return from the surrounding function. This is now a
syntax error:
case (state) {
of (1, 2, 3)
state++
of (4)
return 0
}
it has to be:
case (state) {
of (1, 2, 3)
state++
cbreak # explicit cbreak, cfall or cret() required
of (4)
cret (0)
}
The syntax error isn't something nice (just unbalanced braces), but it's better than silence.
s = $0
if (s == "foo") {
print "** foo case: fallthrough!"
}
if ( (s == "bar") || (s == "xyzzy") ) {
print "** bar/xyzzy case"
}
This translation doesn't preserve the fallthrough;
portable code now, it has succumbed to human error.
I will make fewer conversion mistakes with a macro whose features
closely mimic switch, and which can be separately validated by its own
test cases.
With "cppawk" you seem to be solving a problem that doesn't exist by
creating a real problem - introducing a private tool that'd be required
I released this to the public, under a BSD license. It relies on other commonly available and installed public tools.
to parse the code and the necessity for people to have to look up ".h"
files to figure out what the language constructs in the code mean and
That could be a problem in a project without documentation.
Oh, look; good thing I have that!
$ man -l cppawk-case.1
CPPAWK-CASE(1) Case Macro CPPAWK-CASE(1)
NAME
case - macro for portable switch statement
SYNOPSIS
#include <case.h>
[...]
the potential for the tokens in the .h files to clash with variables or
other language constructs used in the script.
While it's certainly possible to make a dog's breakfast of this, I'm consciously following best practices for header file hygiene, because
that is super important in a tool like this. I'm hardly a beginner.
The error was just in my understanding of what your code does, not in my >writing code to do what I intended it to do.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 546 |
Nodes: | 16 (2 / 14) |
Uptime: | 27:39:52 |
Calls: | 10,390 |
Calls today: | 1 |
Files: | 14,064 |
Messages: | 6,417,072 |