Created
May 30, 2026 03:23
-
-
Save steveroush/a5d1e9332f4f0ef5a5ea9cc0442cbd15 to your computer and use it in GitHub Desktop.
gvEd.gvpr - a partial macro feature for Graphviz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /******************************************************************** | |
| gvEd.gvpr - edit Graphviz attributes | |
| gvEd.gvpr provides a partial macro-like capability to Graphviz | |
| - a pseudo attribute/macro can be defined and then referenced | |
| in the value component of later attribute references | |
| usage: | |
| gvpr -cf gvEd.gvpr | |
| gvpr -a "Pxx" -cf gvEd.gvpr myfile.gv # macro names must begin with xx | |
| ********************************************************************/ | |
| BEGIN{ | |
| graph_t Root; | |
| int i, j; | |
| string editedStr, attName1, attVal1, attName2, attVal2, objType; | |
| string attsN[], attsE[], attsG[], attsThisOType[]; | |
| string lbltype[int], oType, aName, Prefix; | |
| string help; | |
| help=" USAGE: | |
| gvpr -cf gvEd.gvpr # report & reformatted input | |
| gvpr -a 'Pxx' -cf gvEd.gvpr myfile.gv # macronames must begin with xx | |
| "; | |
| int legalName[]; | |
| legalName["Damping"] = 1; | |
| legalName["K"] = 1; | |
| legalName["TBbalance"] = 1; | |
| legalName["URL"] = 1; | |
| legalName["Attributes"] = 1; | |
| legalName["area"] = 1; | |
| legalName["arrowhead"] = 1; | |
| legalName["arrowsize"] = 1; | |
| legalName["arrowtail"] = 1; | |
| legalName["_background"] = 1; | |
| legalName["bb"] = 1; | |
| legalName["beautify"] = 1; | |
| legalName["bgcolor"] = 1; | |
| legalName["center"] = 1; | |
| legalName["charset"] = 1; | |
| legalName["class"] = 1; | |
| legalName["cluster"] = 1; | |
| legalName["clusterrank"] = 1; | |
| legalName["color"] = 1; | |
| legalName["colorscheme"] = 1; | |
| legalName["comment"] = 1; | |
| legalName["compound"] = 1; | |
| legalName["concentrate"] = 1; | |
| legalName["constraint"] = 1; | |
| legalName["decorate"] = 1; | |
| legalName["defaultdist"] = 1; | |
| legalName["dim"] = 1; | |
| legalName["dimen"] = 1; | |
| legalName["dir"] = 1; | |
| legalName["diredgeconstraints"] = 1; | |
| legalName["distortion"] = 1; | |
| legalName["dpi"] = 1; | |
| legalName["edgeURL"] = 1; | |
| legalName["edgehref"] = 1; | |
| legalName["edgetarget"] = 1; | |
| legalName["edgetooltip"] = 1; | |
| legalName["epsilon"] = 1; | |
| legalName["esep"] = 1; | |
| legalName["fillcolor"] = 1; | |
| legalName["fixedsize"] = 1; | |
| legalName["fontcolor"] = 1; | |
| legalName["fontname"] = 1; | |
| legalName["fontnames"] = 1; | |
| legalName["fontpath"] = 1; | |
| legalName["fontsize"] = 1; | |
| legalName["forcelabels"] = 1; | |
| legalName["gradientangle"] = 1; | |
| legalName["group"] = 1; | |
| legalName["headURL"] = 1; | |
| legalName["head_lp"] = 1; | |
| legalName["headclip"] = 1; | |
| legalName["headhref"] = 1; | |
| legalName["headlabel"] = 1; | |
| legalName["headport"] = 1; | |
| legalName["headtarget"] = 1; | |
| legalName["headtooltip"] = 1; | |
| legalName["height"] = 1; | |
| legalName["href"] = 1; | |
| legalName["id"] = 1; | |
| legalName["image"] = 1; | |
| legalName["imagepath"] = 1; | |
| legalName["imagepos"] = 1; | |
| legalName["imagescale"] = 1; | |
| legalName["inputscale"] = 1; | |
| legalName["label"] = 1; | |
| legalName["labelURL"] = 1; | |
| legalName["label_scheme"] = 1; | |
| legalName["labelangle"] = 1; | |
| legalName["labeldistance"] = 1; | |
| legalName["labelfloat"] = 1; | |
| legalName["labelfontcolor"] = 1; | |
| legalName["labelfontname"] = 1; | |
| legalName["labelfontsize"] = 1; | |
| legalName["labelhref"] = 1; | |
| legalName["labeljust"] = 1; | |
| legalName["labelloc"] = 1; | |
| legalName["labeltarget"] = 1; | |
| legalName["labeltooltip"] = 1; | |
| legalName["landscape"] = 1; | |
| legalName["layer"] = 1; | |
| legalName["layerlistsep"] = 1; | |
| legalName["layers"] = 1; | |
| legalName["layerselect"] = 1; | |
| legalName["layersep"] = 1; | |
| legalName["layout"] = 1; | |
| legalName["len"] = 1; | |
| legalName["levels"] = 1; | |
| legalName["levelsgap"] = 1; | |
| legalName["lhead"] = 1; | |
| legalName["lheight"] = 1; | |
| legalName["linelength"] = 1; | |
| legalName["lp"] = 1; | |
| legalName["ltail"] = 1; | |
| legalName["lwidth"] = 1; | |
| legalName["margin"] = 1; | |
| legalName["maxiter"] = 1; | |
| legalName["mclimit"] = 1; | |
| legalName["mindist"] = 1; | |
| legalName["minlen"] = 1; | |
| legalName["mode"] = 1; | |
| legalName["model"] = 1; | |
| legalName["newrank"] = 1; | |
| legalName["nodesep"] = 1; | |
| legalName["nojustify"] = 1; | |
| legalName["normalize"] = 1; | |
| legalName["notranslate"] = 1; | |
| legalName["nslimit"] = 1; | |
| legalName["nslimit1"] = 1; | |
| legalName["oneblock"] = 1; | |
| legalName["ordering"] = 1; | |
| legalName["orientation"] = 1; | |
| legalName["outputorder"] = 1; | |
| legalName["overlap"] = 1; | |
| legalName["overlap_scaling"] = 1; | |
| legalName["overlap_shrink"] = 1; | |
| legalName["pack"] = 1; | |
| legalName["packmode"] = 1; | |
| legalName["pad"] = 1; | |
| legalName["page"] = 1; | |
| legalName["pagedir"] = 1; | |
| legalName["pencolor"] = 1; | |
| legalName["penwidth"] = 1; | |
| legalName["peripheries"] = 1; | |
| legalName["pin"] = 1; | |
| legalName["pos"] = 1; | |
| legalName["quadtree"] = 1; | |
| legalName["quantum"] = 1; | |
| legalName["rank"] = 1; | |
| legalName["rankdir"] = 1; | |
| legalName["ranksep"] = 1; | |
| legalName["ratio"] = 1; | |
| legalName["rects"] = 1; | |
| legalName["regular"] = 1; | |
| legalName["remincross"] = 1; | |
| legalName["repulsiveforce"] = 1; | |
| legalName["resolution"] = 1; | |
| legalName["root"] = 1; | |
| legalName["rotate"] = 1; | |
| legalName["rotation"] = 1; | |
| legalName["samehead"] = 1; | |
| legalName["sametail"] = 1; | |
| legalName["samplepoints"] = 1; | |
| legalName["scale"] = 1; | |
| legalName["searchsize"] = 1; | |
| legalName["sep"] = 1; | |
| legalName["shape"] = 1; | |
| legalName["shapefile"] = 1; | |
| legalName["showboxes"] = 1; | |
| legalName["sides"] = 1; | |
| legalName["size"] = 1; | |
| legalName["skew"] = 1; | |
| legalName["smoothing"] = 1; | |
| legalName["sortv"] = 1; | |
| legalName["splines"] = 1; | |
| legalName["start"] = 1; | |
| legalName["style"] = 1; | |
| legalName["stylesheet"] = 1; | |
| legalName["tailURL"] = 1; | |
| legalName["tail_lp"] = 1; | |
| legalName["tailclip"] = 1; | |
| legalName["tailhref"] = 1; | |
| legalName["taillabel"] = 1; | |
| legalName["tailport"] = 1; | |
| legalName["tailtarget"] = 1; | |
| legalName["tailtooltip"] = 1; | |
| legalName["target"] = 1; | |
| legalName["tooltip"] = 1; | |
| legalName["truecolor"] = 1; | |
| legalName["vertices"] = 1; | |
| legalName["viewport"] = 1; | |
| legalName["voro_margin"] = 1; | |
| legalName["weight"] = 1; | |
| legalName["width"] = 1; | |
| legalName["xdotversion"] = 1; | |
| legalName["xlabel"] = 1; | |
| legalName["xlp"] = 1; | |
| legalName["z"] = 1; | |
| lbltype[0]="label"; | |
| lbltype[1]="xlabel"; | |
| lbltype[2]="taillabel"; | |
| lbltype[3]="headlabel"; | |
| ////////////////////////////////////////////////////////////////////// | |
| void editObj(obj_t thisO){ | |
| int isHTML; | |
| objType=kindOf(thisO); | |
| print(" editObj thisO: ", thisO, " (", objType,")"); | |
| unset(attsThisOType); | |
| // string attsN[], attsE[], attsG[], attsThisOType[]; | |
| if (objType=="N"){ | |
| for (attsN[i]) | |
| attsThisOType[i]=attsN[i]; | |
| }else if (objType=="E"){ | |
| for (attsE[i]) | |
| attsThisOType[i]=attsE[i]; | |
| }else{ | |
| for (attsG[i]) | |
| attsThisOType[i]=attsG[i]; | |
| } | |
| for (attsThisOType[i]){ | |
| attName1=attsThisOType[i]; | |
| print(" checking attribute: ", attName1); | |
| if (legalName[attName1]==1) { | |
| print(" defined ATTR (skip) >", attName1, "<"); | |
| } else if (index(attName1,Prefix)!=0) { | |
| print(" missing Prefix ATTR (skip) >", attName1, "< >",Prefix,"<"); | |
| } else { // possible macro | |
| if (hasAttr(thisO, attName1)) { // does not help or hurt?? | |
| attVal1=aget(thisO, attName1); | |
| print(" macro ATTR >", attName1, "< >", attVal1, "<"); | |
| if (attVal1!="xxxxxxxxxxx") { // if macro has a value != "" | |
| for (attsThisOType[j]){ | |
| attName2=attsThisOType[j]; | |
| if (legalName[attName2]==1) { | |
| if (hasAttr(thisO, attName2)) { // does not help or hurt?? | |
| attVal2=aget(thisO, attName2); | |
| Root.WorkStr=aget(thisO, attName2); | |
| attVal2=Root.WorkStr; | |
| isHTML=ishtml(Root.WorkStr); // NOTE: ishtml(attVal2) fails !!?? | |
| print(" Root.WorkStr ishtml: ", isHTML, " ", Root.WorkStr); | |
| print(" ATTR edit >", attName2,"< >", attName1,"< ++", attVal2, "++"); | |
| if (isHTML!=0) | |
| print(" HTML ", attVal2); | |
| else | |
| print(" not HTML", attVal2); | |
| //if (attVal1 != "" && index(attVal2, attName1)>=0) { | |
| if (index(attVal2, attName1)>=0) { | |
| print(" MATCH : ", attVal2, " ", attName1); | |
| editedStr=gsub(attVal2, attName1, attVal1); | |
| print(" EDITED >", editedStr,"<"); | |
| print(" html check:", attVal2); | |
| if (isHTML) { | |
| print(" treat as HTML"); | |
| Root.htmlWrk2=html(Root, editedStr); | |
| aset(thisO, attName2, Root.htmlWrk2); | |
| }else{ | |
| aset(thisO, attName2, editedStr); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| ////////////////////////////////////////////////////////////////////// | |
| graph_t graphTraverse(graph_t thisGraph) { | |
| graph_t aGraph; | |
| editObj(thisGraph); | |
| for (aGraph = fstsubg(thisGraph); aGraph; aGraph = nxtsubg(aGraph)) { | |
| editObj(aGraph); | |
| } | |
| return thisGraph; | |
| } | |
| } // END OF BEGIN | |
| BEG_G{ | |
| Root=$G; | |
| print("/***********************************************************************"); | |
| print("gvEd.gvpr output:"); | |
| print(""); | |
| print(" debugging:"); | |
| ///////////////////////////////////////////////////////////////////////////////////////////////// | |
| oType="G"; | |
| i=0; | |
| for (aName = fstAttr(Root, oType); aName != ""; aName = nxtAttr(Root, oType, aName)) | |
| attsG[i++]=aName; | |
| oType="N"; | |
| i=0; | |
| for (aName = fstAttr(Root, oType); aName != ""; aName = nxtAttr(Root, oType, aName)) | |
| attsN[i++]=aName; | |
| oType="E"; | |
| i=0; | |
| for (aName = fstAttr(Root, oType); aName != ""; aName = nxtAttr(Root, oType, aName)) | |
| attsE[i++]=aName; | |
| ///////////////////////////////////////////////////////////////////////////////////////////////// | |
| i=0; | |
| Prefix=""; | |
| while (i<ARGC) { | |
| print(" ARG >", ARGV[i],"<"); | |
| if (ARGV[i]=="P") { | |
| Prefix=ARGV[++i]; | |
| } else if (ARGV[i]=="P*") { | |
| Prefix=substr(ARGV[i],1); | |
| } else { | |
| printf(2, help); | |
| exit (1); | |
| } | |
| print(" Prefix >",Prefix,"<"); | |
| i++; | |
| } | |
| graphTraverse($G); | |
| } | |
| N{ | |
| editObj($); | |
| } | |
| E{ | |
| editObj($); | |
| } | |
| END_G{ | |
| print(" end of debugging output"); | |
| print("*******************************************************************/"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment