Pete,
I translated the French parts of my program into English.
My secret goal is that someone smart will find it so ugly and so fragile
that he'll feel challenged to write a nice version for all of us ;-)
It doesn't handle very well Rob's example (well, my brain doesn't handle
it neither ^^), but it was useful to understand a few crazy pipelines I
came across.
It reads a file consisting of a single line, containing your pipeline
just before it runs (without the rexx quotes or rexx comas).
Email me if you've got a problem with it.
Hope it can help.
Michaël
/*------------------------------------------------------------------*/
/* Analyses a ready-to-run pipeline (without quotes, comas) to */
/* create a "dot" file, ready to use for the PC program Graphviz. */
/* The pipeline must be on one line. */
/*------------------------------------------------------------------*/
arg fnIn ftIn fmIn
call analysePipeline
call createDotFile
exit 0
/*
*------------------------------------------------------------------
* Split the pipeline in its parts, ...
*------------------------------------------------------------------
*/
analysePipeline :
pipelineOnOneLine = fnIn ftIn fmIn
tempFile = "PIPE2DOT TEMPO A"
outputFile = fnIn "DOT A"
"ERASE "tempFile
/* The pipeline must be on a single line for the current program */
allTheFile.0 = 0
'pipe < 'pipelineOnOneLine,
'| stem allTheFile.'
if (RC <> 0) then exit RC
if (allTheFile.0 <> 1) then exit -1
thePipeline = allTheFile.1
/* Neutralizes the things I don't know how to treat */
'pipe var thePipeline',
'| change /(/ ( /', /* To make options readable more quickly */
'| change /)/ ) /', /* Idem */
'| change /*:/_PIPELINE_EXTREMITY_/',
'| change /*.output./_PIPELINE_OUTPUT_/',
'| var allThePipeline'
if (RC <> 0) then exit RC
parse value allThePipeline with word1 word2 .
/* Default separator and endchar characters */
theSepCharacter = "|"
theEndCharacter = ""
/* If there are options (SEPARATOR or ENDCHAR) , parses them */
if (substr(word2,1,1) = "(") then do
parse value allThePipeline with word1 restOfPipeline
begOfOptions = pos("(", restOfPipeline) + 1
endOfOptions = pos(")", restOfPipeline) - 1
lgtOfOptions = endOfOptions - begOfOptions + 1
theOptions = substr(restOfPipeline, begOfOptions, lgtOfOptions)
do i=1 to words(theOptions)
theWord = word(theOptions, i)
upper theWord
if (1 = abbrev('SEPARATOR',theWord,3)) then do
theSepCharacter = word(theOptions, i+1)
end
else if (1 = abbrev('ENDCHAR',theWord,3)) then do
theEndCharacter = word(theOptions, i+1)
end
end
restOfPipeline = substr(restOfPipeline, endOfOptions + 2)
restOfPipeline = strip(restOfPipeline)
end
else do
restOfPipeline = subword(allThePipeline, 2)
end
/* Splits on the endchar if there is one, or done otherwise */
if (theEndCharacter <> "") then do
arrayOfPipelines.0 = 0
'pipe var restOfPipeline',
'| split at str /'theEndCharacter'/',
'| strip',
'| stem arrayOfPipelines.'
if (RC <> 0) then exit RC
end
else do
arrayOfPipelines.0 = 1
arrayOfPipelines.1 = restOfPipeline
end
return
/*
*------------------------------------------------------------------
* Creates the file for Graphviz
*------------------------------------------------------------------
*/
createDotFile :
call initColorNames
begOfDotOptions = ' [label = "'
endOfDotOptions = '"]'
/* Graphviz "dot" format beginning */
"pipe strliteral /digraph g {/ | >> "tempFile
/*
* For each ex-endchar-separated part, split on the sep character,
* to get each stage
*/
do i=1 to arrayOfPipelines.0
thePart = arrayOfPipelines.i
theColor = getColorName(i)
'pipe (stagesep % endchar €)',
' var thePart',
'% split at str /'theSepCharacter'/',
'% strip',
'% i1: if pick substr -1;-1 of w1 == /:/',
'% i2: if pick w2 == //',
'% spec /STAGE_/ n substr 1;-2 of w1 n',
'% i2:',
'% spec /STAGE_/ n substr 1;-2 of w1 n ',
'/'begOfDotOptions'/ n 1-* n /'endOfDotOptions'/ n',
'% i2:',
'% i1:',
'% spec /STAGE_'i'_/ n recno strip n ',
'/'begOfDotOptions'/ n 1-* n /'endOfDotOptions'/ n',
'% i1:',
'% OUT: fanout',
'% spec 1-* 1 /;/ n',
'% IN: faninany',
'% >> 'tempFile,
'€',
' OUT:',
'% spec w1 1',
'% FIRST: take first',
'% IN_1: faninany',
'% IN_2: faninany',
'% join 1 / -> /',
'% spec 1-* 1 / [color='theColor'];/ n',
'% IN:',
'€',
' FIRST:',
'% LAST: drop last',
'% duplicate 1',
'% IN_1:',
'€',
' LAST:',
'% IN_2:'
if (RC <> 0) then exit RC
end
/* Graphviz "dot" format ending */
"pipe strliteral /}/ | >> "tempFile
/* 1. Quickly and dirtily removes spaces */
/* 2. Changes characters badly transfered by Filezilla */
"pipe < "tempFile,
"| change /[/ xAD",
"| change /]/ xBD",
"| change /{/ xC0",
"| change /}/ xD0",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| change / / / /",
"| > "outputFile
if (RC <> 0) then exit RC
"ERASE "tempFile
return
/*
*------------------------------------------------------------------
* We can use only a finite number of colors, so some lines
* will have to have the same colors.
* Maths note :
* The "-1" and "+1" are here because the rank I want (realRank)
* is not proportionnal to the rank I give (colorRank).
* But "realRank - 1" IS proportional to "colorRank - 1"
*------------------------------------------------------------------
*/
getColorName :
arg colorRank
realRank = (colorRank - 1) // arrayColors.0 + 1
return arrayColors.realRank
/*
*------------------------------------------------------------------
* Uses only a small number of colors (because anyway, some other
* colors are difficult to differentiate
*------------------------------------------------------------------
*/
initColorNames :
i=0
i=i+1;arrayColors.i = "red"
i=i+1;arrayColors.i = "blue"
i=i+1;arrayColors.i = "green"
i=i+1;arrayColors.i = "magenta"
i=i+1;arrayColors.i = "black"
i=i+1;arrayColors.i = "brown"
i=i+1;arrayColors.i = "dimgray"
i=i+1;arrayColors.i = "darkorange"
i=i+1;arrayColors.i = "darkturquoise"
i=i+1;arrayColors.i = "violet"
i=i+1;arrayColors.i = "forestgreen"
i=i+1;arrayColors.i = "firebrick"
i=i+1;arrayColors.i = "crimson"
i=i+1;arrayColors.i = "blueviolet"
arrayColors.0 = i
return