During some research for my day job, I was pointed to a utility written by Guillaume Dargaud that converts LabWindows/CVI user interface files (.uir) over to HTML so they can run in a web browser instead of as a Windows UI app. The program, written in C, can be found here:
https://www.gdargaud.net/Hack/PanelToCgi.html
https://gitlab.com/dargaud/PanelToForm
But that is not really what this post is about. Instead, it is about seeing lines in his code (originally created in 2000) like this:
Active = Mode!=VAL_INDICATOR and Visible and !Dimmed;
if (Fmin<-1e30 and Fmax>1e30) {
if (Dmin<-1e30 and Dmax>1e30) {
That looked more like Visual BASIC or something than C to me. “and”? Shouldn’t that be “&&” in C for a logical and?
I mentioned this in the forum post where I learned of this utility, and received this response:
“It’s been standard C since the introduction of #include <iso646.h> in the 90s. I always found it more readable this way.”
– gdargaud, via https://forums.ni.com/t5/LabWindows-CVI/LabWindows-UI-to-ncurses-Linux-macOS-terminal/m-p/4472028
iso646.h
This one is new to me. Wikipedia has a page about it:
https://en.wikipedia.org/wiki/C_alternative_tokens
Here is what that header file looks like on the Microchip MPLAB PIC24 compiler:
#ifndef _ISO646_H
#define _ISO646_H
#ifndef __cplusplus
#define and &&
#define and_eq &=
#define bitand &
#define bitor |
#define compl ~
#define not !
#define not_eq !=
#define or ||
#define or_eq |=
#define xor ^
#define xor_eq ^=
#endif
#endif
Have you ever seen this used in the wild? I was surprised to see it even supported in a non-mainstream compiler, like that one.
Looking at the list, this line could have been changed further:
Active = Mode not_eq VAL_INDICATOR and Visible and not Dimmed;
And indeed, that works:
#include <stdio.h>
#include <iso646.h>
// #define and &&
// #define and_eq &=
// #define bitand &
// #define bitor |
// #define compl ~
// #define not !
// #define not_eq !=
// #define or ||
// #define or_eq |=
// #define xor ^
// #define xor_eq ^=
#define VAL_INDICATOR 1
int main()
{
int Active = 0;
int Mode = (VAL_INDICATOR + 1);
int Visible = 1; // Visible
int Dimmed = 1; // Dimmed
printf ("Mode: %d Visible: %d Dimmed: %d\n", Mode, Visible, Dimmed);
Active = Mode not_eq VAL_INDICATOR and Visible and not Dimmed;
printf ("Active: %d\n", Active);
Mode = (VAL_INDICATOR + 1);
Visible = 1; // Visible
Dimmed = 0; // NOT Dimmed
printf ("Mode: %d Visible: %d Dimmed: %d\n", Mode, Visible, Dimmed);
Active = Mode not_eq VAL_INDICATOR and Visible and not Dimmed;
printf ("Active: %d\n", Active);
return 0;
}
Coding standards such as the BARR-C Embedded Coding Standard specifically say not do do things like this since it makes the code harder to figure out since the user has to go look up what those defines are really set to. Imagine how the code might look fine, but be complete wrong, if a define were messed ;-)
Have you seen this? Do you do this? Leave a comment…
