Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

cppawk: portable case statement.

18 views
Skip to first unread message

Kaz Kylheku

unread,
Mar 28, 2022, 3:09:44 AM3/28/22
to
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.

Ed Morton

unread,
Mar 28, 2022, 8:45:06 AM3/28/22
to
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"
}
else if (s ~ /x/) {
print "** /x/ case"
}
else {
print "** default"
}
}

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.

Ed.

Kaz Kylheku

unread,
Mar 28, 2022, 6:52:59 PM3/28/22
to
On 2022-03-28, Ed Morton <morto...@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; so while we have
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.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Ed Morton

unread,
Mar 29, 2022, 8:19:34 AM3/29/22
to
Yeah, looks like I forgot how a "fallthrough" worked and thought the
next condition would be tested before the associated action was
executed. It's been a long time since I wrote such code.

so while we have
> portable code now, it has succumbed to human error.

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.

Ed.

Kenny McCormack

unread,
Mar 29, 2022, 8:27:08 AM3/29/22
to
In article <t1utgk$s11$1...@dont-email.me>,
A raving lunatic <morto...@gmail.com> wrote:
...
>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.

Said every buggy programmer ever.

--
People who want to share their religious views with you
almost never want you to share yours with them. -- Dave Barry
0 new messages