/*
Date: 23 Oct 2015 16:01:05
Update: 31 Oct 2015 03:52:53 - Handle filespec and var substitution
Update: 11 Jul 2016 03:35:20 - Improvee Help prose. Thanks to Walter Pachl
Update: 11 Jul 2016 22:02:50 - Fix for whole file and start to eof
Update: 12 Jul 2016 09:49:54 - Catch not enough args. Remove 'interpret'
leftover from attempt at Regina compat.
Update: 12 Jul 2016 17:49:14 - Cleanup some dead code
Update: 14 Jul 2016 00:36:10 - Document double-quote "Do not substitute"
Display HELP subroutine as part of Help
Update: 14 Jul 2016 15:35:35 - Add options trigger ':' for NOSHOW, QUIET
Update: 15 Jul 2016 17:08:05 - Add NOQUIET to 'valids' Thanks Walter!
Update: 15 Jul 2016 23:33:07 - Allow NOSHOW and QUIET from cmdline
Update: 16 Jul 2016 00:25:19 - Add NOTEPAD option for cmdline testing
Update: 16 Jul 2016 06:54:02 - Show abbrev of options. Walter
Update: 16 Jul 2016 16:48:52 - Allow Help keywords from cmdline
Update: 17 Jul 2016 15:30:09 - Show that the Help keywords are optional
Update: 18 Jul 2016 14:46:26 - Use Seek in GetFile subroutine (Walter)
Update: 25 Jul 2016 16:34:34 - Comment code for testers (Rony Flatcher)
Update: 26 Jul 2016 14:00:12 - Use the modern lower case name
Update: 5 Aug 2016 06:08:54 - Use .context~name Fix example Add comments
Update: 12 Aug 2016 09:29:11 - Use single-quotes in first example
*/ beghelp=thisline()+1 /*
showit.rex: See "Purpose", below
Copyright (C) 2015 Leslie L. Koehler
This is free software. See "Notice:" at the bottom of
&this file.
Author: Les Koehler vmrexx@tampabay.rr.com
Purpose: Display the data items passed. Items can be a stem, a file
(or a piece of one), a literal string or the definition of
a variable that will be used for substituting its occurrences
in lines from stems, literal strings, and/or files. For example:
'&varname=txt' or '&varname='value
As many items as needed can be used.
A string that starts with ':' triggers Options processing.
Valid options to change the defaults are:
NOShow - Don't display the output file
Quiet - Skip the Exit message when NOSHOW is used
NOTepad - Allow testers to use NotePad
Any number of Options lines can be used and any option can be
negated by starting it with 'NO' (or not) as needed.
Syntax: Call &lcsme .context~name , [output fileid] , item [, item ...]
The output fileid defaults to the caller appended with '_help.txt'
Example: Call &lcsme 'C:\MyRexxStuff\test.rex' , -- Caller
, 'C:\Reports\Symposium.txt' , -- Output fle (optional)
, 'Financial Data Report' , -- Literal string
, stema. , stemb. , -- Stems
, '1 5 C:\Sigs\Lesk.txt' , -- Lines 1-5 of a file
, '1 * C:\temp\junk.txt' , -- The whole file
, '7 eof C:\temp\test.txt' , -- Line 7 to end-of-file
, ':quiet noshow' , -- Options
, '&lcme='lcme -- Variable definition
Help: &lcsme [&helps]
Here's a real example, in the file &fullme:
*/
endhelp=thisline()-2
Call Parse_source
Parse Arg args
Call Parse_args args
If Arg()<3 Then Call Exit 12 'At least 3 args are required'
--call dump
argarray = Arg(1,'a')
--say argarray~last 'items to process'
gothim?=0
gotfile?=0
outarray=.array~new /* We'll collect the lines to write, here */
outfile=''
ampersands.0=0
--trace r
Do i = 1 To argArray~last
Arg = argArray[i]
Select
When arg~isA(.stem) Then Do
-- Say 'Arg' i 'is a stem'
Call handlestem(Arg)
End
When arg~isA(.string) Then Do
-- say 'Arg' i 'is a string:' Arg
Call Handlestring Arg
End
When Arg=.nil Then Call Handledefaultfile
Otherwise Say 'Arg' i 'is' Arg '(not handled)'
End /* select */
End /* DO */
If outarray~last=.nil Then Do
Call Exit 12 'There is no data to do variable substitution against.'
End
If ampersands.0>0 Then Do /* Look for var substitution */
Do l=1 To outarray~last
line=outarray[l]
If Pos('&',line)>0 Then Do /* Need one here? */
Do a=1 To ampersands.0 /* Yes. Walk down the list */
Parse Var ampersands.a ampername'='val
hit=Pos('&',line)
If hit>1 Then Do /* Room to test for double-quote? */
If Substr(line,hit-1,1)='"' Then Iterate a /* Skip if there */
End
If Pos(ampername,line)>0 Then Do /* Substitute if there */
line=Changestr(ampername,line,val)
End
End
outarray[l]=line /* Replace the line */
End
End
End
Call Sysfiledelete outfile
outobject = .stream~new(outfile)
--outObject~open("WRITE")
--If outobject~open('WRITE REPLACE') \= 'READY:'
If outobject~open('WRITE') \= 'READY:'
Then Call Exit 12 'Can''t open file:' outfile '('mystream~description')'
outobject~arrayout(outarray,"LINES")
outobject~close()
--call dump
If show? Then Do
Parse Upper Source os .
If Left(os,7)='WINDOWS' Then Do
uid=Word(Userid(),1)
Select /* Give testers their favorite editot */
When uid='Les' & \notepad? Then ,
'cmd.exe /c start /max c:\the\thec.exe "'outfile'"'
When uid='Walter' & \notepad? Then ,
'cmd.exe /c start /max ked "'outfile'"'
Otherwise /* Everyone else gets NotePad */
'cmd.exe /c start /max notepad.exe "'outfile'"'
End
End
Else 'cat "'outfile'" | more' /* Must be Linux type */
End
Else If \quiet? Then Call Exit 0 'created:' outfile
Call Exit
Exit
/* ============================================= */
HANDLESTEM: Procedure Expose outarray
use Arg stem.
If stem.0~datatype('w') Then Do i = 1 To stem.0
outarray~append(stem.i)
End
Else Do ind over stem.~allIndexes
outarray~append(stem.ind)
End
Return
/* ============================================= */
HANDLESTRING: Procedure Expose gothim? fullhim i outfile ,
gotfile? ampersands. outarray (exposes) ucvalids abbrev ,
keyword_parms? flags unknown? unknowns quiet? notepad? help?
--Say arg(1)
If \gothim? & i=1 Then Do
fullhim=Arg(1)
gothim?=1
End
If \gotfile? & i=2 Then Do
If Arg(1)\='' Then Do
If Arg(1)\=fullhim Then Do
outfile=Arg(1)
gotfile?=1
End
End
End
If i>2 Then Do
Select
When Datatype(Word(Arg(1),1),'W') Then Do
Call Getfile Arg(1)
End
When Left(Arg(1),1)=':' Then Call Validate Substr(Arg(1),2)
When Left(Arg(1),1)='&' Then Call Next 'ampersands',Arg(1)
Otherwise outarray~append(Arg(1))
End
End
Return
HANDLEDEFAULTFILE: Procedure Expose fullhim i outfile gotfile?
If \gotfile? & i=2 Then Do
-- say 'Arg 2 is .nil setting the default:'
outfile=fullhim||'_help.txt'
-- say ' 'outfile
gotfile?=1
End
Return
GETFILE: Procedure Expose (exposes) outarray i /* Thanks to Jon Wolfers! */
Parse Arg start last filename
mystream = .stream~new(filename)
If myStream~open('read') \= 'READY:'
Then Call Exit 12 'Can''t open file:' filename '('mystream~description')'
myStream~seek(start 'LINE') /* Position READ pointer to start point */
myarray = myStream~arrayIn /* Read in the file, from 'start' to eof */
If myStream~close \= 'READY:'
Then Call Exit 12 'Can''t close file:' filename '('myStream~description')'
If Datatype(last,'W') Then , /* Pick out our piece of MyArray */
mysection = myArray~section(1, last+1 - start)
Else ,
mysection = myArray~section(1) /* The whole thing! */
outarray = outArray~union(mysection)
Return
GETFILE: Procedure Expose outarray /* Fails for multiple calls */
Parse Arg start last filename
outArray~appendAll(.stream~new(filename)~arrayIn~section(start, last+1 - start))
Return
PARSE_SOURCE:
Parse Source whatos how fullme
Parse Value Reverse(fullme) With ext'.' em '\' mypath
me=Translate(Reverse(em))':'
sme=Substr(me,1,Length(me)-1)
pad=Copies(' ',Length(sme))
lcsme=Lower(sme)
mypath=Reverse(mypath)'\'
logfile=mypath||Lower(sme)'.log'
ext=Translate(Reverse(ext))
the?=ext='THE'
rex?=\the?
Parse version whatrexx rexxlevel rexx_release_date
oorexx?=Pos('ooRexx',whatrexx)>0
regina?=Pos('REGINA',Translate(whatrexx))>0
If regina? Then Do
Call Exit 99 'Sorry, Regina is not supported. ooRexx only.'
End
args=''
opts=''
If the? Then Do
c='command'
cn='command nomsg'
m='macro'
End
Return
PARSE_ARGS:
Call Init_vars
If Words(args)=0 | how='COMMAND' Then Call Help
Else Return
VALIDATE:
--trace r --call dump --trace r
wds=Words(Arg(1))
ucargs=Translate(Arg(1))
Do w=1 To wds
wd=Word(ucargs,w)
ok?=0
Do v=1 To Words(ucvalids)
If Abbrev(Word(ucvalids,v),wd,Word(abbrev,v)) Then Do
ok?=1
Leave v
End
End
If ok? Then Do
ucwd=Word(ucvalids,v)
z=Word(flags,v) /* Set flags indirectly */
If z='notepad?' Then Do
If Left(ucwd,2)\='NONO' Then Do
Call Value z'.'w,1 /* Set positional flag */
Call Value z,1 /* Set arg flag */
End
Else Do
Call Value z'.'w,0 /* Set positional flag */
Call Value z,0 /* Set arg flag */
End
End
Else Do
If Left(ucwd,2)\='NO' Then Do
Call Value z'.'w,1 /* Set positional flag */
Call Value z,1 /* Set arg flag */
End
Else Do
Call Value z'.'w,0 /* Set positional flag */
Call Value z,0 /* Set arg flag */
End
End
argix.wd=ucwd
End
Else Do
Call Value 'unknown?.'w,1
unknown?=1
unknowns=unknowns wd
End
End
--all dump
If help? Then Call Help
If unknown? & keyword_parms? Then Do /* Allow parms after keywords */
kwdptrs=''
kwds=''
Do u=1 To wds /* Get the kwds in left to right order */
wd=Word(ucargs,u)
If \unknown?.u Then Do /* Found a keyword */
kwdptrs=kwdptrs u
kwds=kwds wd
End
End
kwdctr=Words(kwdptrs)
Do p=1 To kwdctr /* Get the parms for each kwd */
pix=Word(kwdptrs,p) /* Index into args */
If pix+1<wds & p<kwdctr Then Do /* Another kwd later */
piy=Word(kwdptrs,p+1) /* Ptr to next kwd */
If piy\='' Then Do
piy=piy-1 /* Back up to prev word */
pwords=piy-pix /* Number of words between kwds */
End
Else Do
Iterate
End
End
Else Do /* TAILOR TO SUIT! Last keyword */
If pix<wds Then Do /* Something follows it */
-- If Word(ucargs,p)='FILE' Then pwords=wds-pix /* Get all of it */
If Wordpos(Word(ucargs,p),keyword_parms)>0 Then ,
pwords=wds-pix /* Get all of it */
Else pwords=1 /* Just one word */
End
Else pwords=0
End
Do u=pix+1 To pix+pwords /* Reset unknown?. flags */
Call Value 'unknown?.'u,0 /* For parms that go with kwds */
End
vname=Word(kwds,p) /* Name of the var */
vname=argix.vname
vval=Subword(args,pix+1,pwords) /* Value of the var */
Call Value vname,vval /* Set it */
End
unknowns='' /* Reset */
unknown?=0
Do u=1 To wds /* Accumulate any args that are still unknown */
If unknown?.u Then unknowns=unknowns Word(args,u)
End
End
unknown?=unknowns\=''
-- Call dump
If unknown? Then Call Exit 8 'Unknown option(s):' unknowns
Return
INIT_VARS:
valids='? /? -? Help /Help -Help --Help' /* Keywords */
abbrev='1 2 2 1 2 2 3 ' /* Minimum abbreviation */
flags=Copies('Help? ',Words(valids)) /* Flag to set for keyword */
helps=valids
valids=valids 'SHOW NOSHOW QUIET NOQUIET NOTEPAD' --< your keywords
abbrev=abbrev '1 3 1 3 3' --< your abbreviations
flags=flags 'show? show? quiet? quiet? notepad?' --< your flagnames
flags=flags 'Unknown? Keyword_parms?' /* Always the last ones */
Do f=1 To Words(flags)
v=Word(flags,f)
Call Value v'.'f,0 /* Initialize positional flag */
Call Value v,0 /* Initialize arg flag */
End
show?=1
last=Words(helps)
hhelp=''
Do h=1 To last /* Build the Helps line variable */
If h\=last Then hhelp=hhelp || Word(helps,h) '| '
Else hhelp=hhelp||Word(helps,h)
End
helps=hhelp
unknowns=''
unknown?.=0
ucvalids=Translate(valids)
-- msg.0=0
keyword_parms?=0
-- keyword_parms='TO FILE PATH'
-- Parse Value '' With file path To
-- msg.0=0
exposes='sme lcsme me msg. c cn m myrc pad quiet? notepad?' ,
'help? mypath log? the? rex? logfile oorexx? regina? show? fullme',
'beghelp endhelp helps'
Return
MSG: Procedure Expose sme me rex? the?
If rex? Then Say me Arg(1)
Else 'msg' me Arg(1)
Return
EMSG: Procedure Expose sme me emsg rex? the?
If rex? Then Say me Arg(1)
Else 'emsg' me Arg(1)
Return
NEXT:
Parse Arg !stem,!val
If \Datatype(Value(!stem'.0'),'W') Then Call Value !stem'.0',0
!ix=Value(!stem'.0')+1
Call Value !stem'.0',!ix
Call Value !stem'.'||!ix ,!val
Return
THISLINE:
Return sigl
DUMP:
the?=0
If the? Then Do
-- Interpret dumpvars('K')
-- Interpret dumpvars('K','zz')
Interpret oodumpvars(,'zz')
Interpret zz
End
Else Do
-- Interpret oodumpvars('K')
-- Interpret oodumpvars('K','zz')
Interpret oodumpvars(,'zz')
Interpret zz
End
Exit
VALUEOF:
Arg !_!label
Signal Value !_!label
Return
HELP:
xmpstart=thisline()-1
xmpend=thisline()+9
more=''
if symbol('ARGS')='VAR' then more=':'args /* Allow options */
outvar=beghelp endhelp fullme /* startline endline & file to extract from */
Call Showit fullme ,, outvar , /* Caller , data to show */
,more , /* Allow options to be tested from a command window */
,"&lcsme="lcsme , '&sme='sme , '&this file.='fullme , /* Substitutions */
,"&helps="helps , '&fullme='fullme , xmpstart xmpend fullme
-- Note that the above 2 lines are NOT substituted when &sme displays them.
-- That's because of the double-quote before the first '&'.
Call Exit
EXIT: Procedure Expose sme me sigl msg emsg rex? the?
Parse Arg myrc mymsg
mysigl=sigl
If myrc='' Then myrc=0
If myrc\=0 & mymsg\='' Then Do
Call Emsg mymsg
Call Msg 'Enter' sme 'HELP for help'
Call Emsg 'Rc='myrc
End
Else If myrc=0 & mymsg\='' Then Call Msg mymsg
If myrc\=0 Then Call Msg 'Exit called from line' mysigl
Exit myrc
LOGIT: Procedure Expose (exposes) sigl
--trace r
mysigl=sigl
Parse Arg logargs
If logargs='' Then logargs=Sourceline(mysigl+1)
Parse Value Right(Space(Date(),0),9,0) Time('L') With ds ts
logline=ds ts logargs
If Arg(2,'E') & Arg(2)\='' Then Do
Parse Value Arg(2) With his_sigl him
logline=logline '>' him '@' his_sigl
End
Else logline=logline '@' mysigl
logfile=mypath||Lower(sme)'.log'
If oorexx? Then Do
.stream~new(logfile)~~lineout(logline)~close
-- writeline='.stream~new("'logfile'")~~lineout("'logline'")~close'
-- Interpret writeline /* Bypass Regina prescan */
End
Else Do
Call Stream logfile, 'C', 'OPEN WRITE APPEND'
Call Lineout logfile,logline
Call Stream logfile,'C', 'CLOSE'
End
Return
/* --- End of skeleton code --- Put subroutines below: */
/* Notice:
This program is free software: you can redistribute it and/or modify
it under the terms of the EPL (Eclipse Public License) as published by
the Open Source Initiative, either version 1.0 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
EPL for more details.
You should have received a copy of the EPL along with this program.
If not, see:
http://www.opensource.org/licenses/eclipse-1.0.php
*/