/* 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 */