How to get gvpr's preprocessor to work?

@smattr wrote:

gvpr does support the C pre-processor (#include). It will even interpret the #line directives left by the pre-processor.

I’ve tried to get the preprocessor to work, but I’ve failed.

I wrote and ran this program:

#!/bin/bash

echo 'N { print("I see a node!"); }' > /tmp/program1.gvpr
echo 'E { print("I see an edge!"); }' >> /tmp/program1.gvpr

echo 'N { print("I see a node!"); }' > /tmp/nodes.gvpr
echo 'E { print("I see an edge!"); }' > /tmp/edges.gvpr
(
  echo '#include "/tmp/nodes.gvpr"'
  echo '#include "/tmp/edges.gvpr"'
) > /tmp/program2.gvpr

echo 'void printGreeting() { print("Hello!"); }' > /tmp/printGreeting.gvpr
echo '
BEGIN {
#include "/tmp/printGreeting.gvpr"
  printGreeting();
}
' > /tmp/program3.gvpr

echo Running /tmp/program1.gvpr:
echo
echo 'digraph { a -> b }' | gvpr -f /tmp/program1.gvpr
echo

echo Running /tmp/program2.gvpr:
echo
echo 'digraph { a -> b }' | gvpr -f /tmp/program2.gvpr
echo

echo Running /tmp/program3.gvpr:
echo
gvpr -f /tmp/program3.gvpr
echo

rm -f /tmp/program1.gvpr
rm -f /tmp/nodes.gvpr
rm -f /tmp/edges.gvpr
rm -f /tmp/program2.gvpr
rm -f /tmp/program3.gvpr
rm -f /tmp/printGreeting.gvpr

When I run that program, it gives the following output:

Running /tmp/program1.gvpr:

I see a node!
I see an edge!
I see a node!

Running /tmp/program2.gvpr:


Running /tmp/program3.gvpr:

gvpr: "/tmp/program3.gvpr", line 4: printGreeting(<<< 
 -- syntax error

If inclusion worked, I would expect to see output (other than error messages) from /tmp/program2.gvpr and /tmp/program3.gvpr.

UPDATE (JULY 25, 2024)

Program was slightly erroneous, so I corrected it (and its output).

I should have said: I’m using Graphviz 12.0.0.

gvpr does not come with a preprocessor, but you can use the C preprocessor (cleverly named cpp) with gvpr. Installing cpp is pretty easy on a Linux box, I’m less sure about windows or Mac.

Linux command line (probably easily improved):

P=RClayout21a.gvpr;cpp -nostdinc -C -w -P $P >/tmp/$P;T=svg;f=RC_test_squareCells.gv;F=${f%.%}; dot ...

The first few lines of a gvpr program:

#include "cppInclude.gvpr"
#undef     README  cpp -nostdinc -C -w -P thisfile  |cpp -nostdinc -C -w -P

#define ERRORMSG(ESTRING)    doErrs(ESTRING+"");  
#define WARNMSG(ESTRING)    doErrs(ESTRING+"");  
...  lots of gvpr code ...
  DEBUG_PRINT("// setMinMax : ", subG.name, "  node: ", aNode.name, "  ",aNode.pos);
... lots more ...
   IFHASATTR(aNode, peripheries){

and here is the included file


#undef     README  cpp -nostdinc -C -w -P thisfile  |cpp -nostdinc -C -w -P
#if 1 == 1  //  use this if you want to print 
  #define DEBUG_PRINT print
  #define noDEBUG_PRINT #undef JuNk z
#else       //  use this if you DO NOT want to print 
  #define DEBUG_PRINT #undef JuNk z
  #define noDEBUG_PRINT #undef JuNk z
#endif

#define ERRORMSG(ESTRING)    estr=ESTRING; doErrs(estr);
#define existAttr(OBJ, ATT)  (hasAttr(OBJ, #ATT))  // pound causes quotes
#define hasValue(OBJ, ATT)   (OBJ.ATT!="")
#define ISTRUE(OBJ, ATT)     (istrue(OBJ.ATT)==1)
#define ISFALSE(OBJ, ATT)    (isfalse(OBJ.ATT)==1)
#define HASATTR(OBJ, ATT)    existAttr(OBJ, ATT) && hasValue(OBJ, ATT)
#define notHASATTR(OBJ, ATT) (!(existAttr(OBJ, ATT) && hasValue(OBJ, ATT)))
#define ATTRTRUE(OBJ, ATT)   (existAttr(OBJ, ATT) && ISTRUE(OBJ, ATT))

This is a bit OT, but I find it peculiar that the C pre processor gets repurposed so often. I’ve seen it used in hundreds of places, similar to how it’s used in gvpr. M4 is a much more powerful and general pre processor that can be applied to any language, even one that doesn’t anticipate pre processing. Yet somehow CPP is only the hammer people seem to know.

A couple of years ago, I tried using cpp “for real”, but never got comfy with it. Admittedly my C experience with cpp was in the last century!
My guess is that cpp would help .gv files more as a stylesheet / css stand-in

gvpr does not come with a preprocessor

Thanks for the confirmation, @steveroush.

I don’t think I’ll use a preprocessor as a separate program. It doesn’t provide
enough value to justify the bother.

I think the learning curve for cpp is not as steep as that for M4.