Menu

#13 regular expressions

open
nobody
None
5
2006-10-06
2006-10-06
richard
No

regular expressions are great. But, it looks like
only the expression is possible, not any flags.
My question, how would I specify the LOCATE command
for these grep arguments: -i '\<word\>'

Discussion

  • deanpark1929

    deanpark1929 - 2006-10-07

    Logged In: YES
    user_id=1614411

    are you trying to do a mixed case search? if so, at the
    command line you can enter the following to search for "word":

    set case m i
    /word

    I have the "set case" statement set permanently in my .therc
    profile so the editor is automatically in mixed case mode.
    (set case will take additional parameters - depending upon
    what you might want to do - check out the docs).

     
  • richard

    richard - 2006-10-09

    Logged In: YES
    user_id=1587066

    Not as simple as a mixed case search for some string of
    characters. Rather, a mixed case search for a string of
    characters delimited by white space or any non-word
    characters (comma, quote, dash, whatever 'start word'
    and 'end word' controls the left-angle and right-angle
    indicate. But in general, LOCATE takes regular
    expressions, and I suppose in this case I could contrive a
    regular expression that indicates the 4 characters 'word'
    could be any case. But, if the flag '-i' were legal, it
    would be so much easier. Another way to pute it, Regular
    expressions are necessary but not sufficient.

     
  • deanpark1929

    deanpark1929 - 2006-10-09

    Logged In: YES
    user_id=1614411

    hmmm ... ok, sounds non-trivial. example? how bout writing a
    macro to programmatically do what you want i.e. loop/extract
    curline and then process via rexx parse or a custom filter.

     
  • richard

    richard - 2006-10-09

    Logged In: YES
    user_id=1587066

    Sure, I've done so in the past.
    delims = '~`@#$%^&*()_-+={}[]:";'<>?,./'
    do s = 1 to length(delims)
    start = substr(delims,s,1)
    do e = 1 to length...
    end = substr...
    look for start || word || end
    blah blah blah

    I could program all regular expressions in REXX.
    What I hoped for is more grep-style capabilities so *I*
    don't need to code such things in REXX.
    And, of course, that capability would be desired in
    anything that used locate target expressions, like ALL, or
    CLOCATE (although I've never coded a CLOCATE in 20 years of
    XEDIT/KEDIT usage), or FIND.
    There isn't a COUNT command, but ALL -c RE/.../ might be an
    alternative, although this might be a bit of a stretch.
    I don't see many grep flags that I'd say would be *really*
    useful, but -i seems like a really good one.

     
  • Robert A "Bob" Cruz

    Logged In: YES
    user_id=371416

    As I see it, this RE searches for the next occurrance of a "word"
    which is not a substring of some other word. This is a useful
    capability. For example, variables in a programming language fall
    under this definition of "word". The MVS ISPF Editor even has a
    keyword option on its FIND (equivalent of LOCATE) command to restrict
    searches in this manner.

    A goodly time ago, I decided that I needed this capability in the
    XEDIT environment (where there are no regular expressions). So I
    wrote a macro named ALLVAR (All occurrances of a given variable
    name). This macro accepts a single operand, which is the word
    (variable name) to be searched for. It operates like the ALL
    command.

    I have attached a copy. Feel free to use it as-is, or adapt it to
    your needs. I have also attached INCLUDE.THE, which is used by
    ALLVAR.THE.

     
  • Robert A "Bob" Cruz

    Logged In: YES
    user_id=371416

    I'm sorry, but I don't see how to attach a file here, so I'll just cut-
    and-paste them. Feel free to e-mail me at bobcruz-at-pacbell-dot-com
    if this doesn't work for you. (Note that a third required macro,
    GETARGET.THE is also included).

    /*REXX ALLVAR.THE routine to find all occurrances of a variable */
    /* whose name might be a substring of another variable name. */
    OPTIONS NOEXT_COMMANDS_AS_FUNCS /* for Regina */ /*0.04*/

    /* HISTORY: */
    /* Ver? Who? When? What? */
    /* ---- ---- ------- ----------------------------------------------- */
    /* 0.01 RAC 28Apr00 Fixed bug where identifier which started at 0.01*/
    /* the left margin or ended at the right 0.01*/
    /* margin would not be found. 0.01*/
    /* Fixed bug where identifiers longer than 5 0.01*/
    /* characters would cause the generated XEDIT 0.01*/
    /* search command to exceed 250 characters, so 0.01*/
    /* the command would be truncated and yield 0.01*/
    /* incorrect results. 0.01*/
    /* Added tests for excess parameters and 0.01*/
    /* unsupported options. 0.01*/
    /* Added tests for identifier too long and 0.01*/
    /* zone too narrow. 0.01*/
    /* 0.02 RAC 26Oct00 Modified to run as .KEX as well as XEDIT; 0.02*/
    /* Also improved error handling. 0.02*/
    /* 0.03 RAC 19Feb02 Fixed bug when no records found 0.03*/
    /* 0.04 RAC 12Nov02 Created Regina/THE version 0.04*/
    /* 0.05 RAC 16Mar04 Changed message environment from 'XEDIT' 0.05*/
    /* to <environ>; added "Case N" comments. 0.05*/
    /* */
    /* REQUIRES: */
    /* INCLUDE.THE -- add line(s) to those shown */
    /* 0.01*/
    /*********************************************************************/

    SIGNAL ON NOVALUE

    globals = 'zone.' /* Original ZONE settings 0.02*/
    globals = globals 'msgmode.' /* Original MSGMODE 0.02*/
    globals = globals 'linend.' /* Original LINEND settings 0.02*/
    globals = globals 'arbchar.' /* Original ARBCHAR settings 0.02*/
    globals = globals 'cc' /* Completion code of this cmd 0.02*/
    globals = globals 'identifier' /* Identifier to search for 0.02*/
    globals = globals 'nn' /* number of occurrances 0.02*/
    nn = '?unknown?' /* just in case used before set 0.02*/

    environ = ADDRESS() /*0.05*/

    PARSE ARG identifier xs '(' options

    IF identifier = ''
    THEN EXIT ErrMsg('ALLVAR001T Identifier missing -- Abending!', ,
    environ ) /*0.05*/

    IF xs <> '' /*0.01*/
    THEN EXIT ErrMsg('ALLVAR002T Excess parameters, "'xs'" --
    Abending!', , environ ) /*0.05*/

    IF options <> '' /*0.01*/
    THEN EXIT ErrMsg('ALLVAR003T Options, "'options'", not supported --
    Abending!', , environ ) /*0.05*/

    IF LENGTH( identifier ) > 234 /*0.01*/
    THEN EXIT ErrMsg('ALLVAR004T
    Identifier, "'identifier
    ,
    || '", is too long (exceeds 234 characters) --
    Abending!', , environ ) /*0.05*/

    'COMMAND EXTRACT/ZONE/' /*0.01*/
    IF zone.2 - zone.1 + 1 < LENGTH( identifier ) /*0.01*/
    THEN EXIT ErrMsg('ALLVAR104T
    Identifier, "'identifier
    ,
    || '", is too long to fit within zone' zone.1
    zone.2 '-- Abending!', , environ ) /*0.05*/

    msgmode. = '' /* For KEXX */ /*0.02*/
    'COMMAND EXTRACT/MSGMODE/' /* Preserve MSGMODE setting */
    'COMMAND SET MSGMODE OFF'

    'COMMAND EXTRACT/LINEND/' /* Preserve LINEND setting 0.02*/
    'COMMAND SET LINEND OFF' /*0.02*/

    'COMMAND EXTRACT/ARBCHAR/' /* Preserve ARBCHAR setting 0.02*/
    'COMMAND SET ARBCHAR OFF' /*0.02*/

    /* NOTE: A refinement would be to assign these next three */
    /* strings depending on the language (filetype). */
    leading_delimiters = " ^&*("")-+%=|\;:'<>,./?{}[]~" /*no "!" 0.02*/
    trailing_delimiters = " ^&*("")-+%=|\;:'<>,./?{}[]~" /*no "!" 0.04*/
    dlm = "`" /*0.02*/

    /* A further refinement would be to first remove literals and
    comments 0.01*/

    search_cmd = ''
    cc = 2 /* no lines found (yet) */

    /*----------------------------------------------------------------*/
    /* Case 1: the zone is at least two columns wider than */
    /* <old_symbol>, so that the identifier may appear */
    /* with both a leading and trailing delimiter. */
    /*----------------------------------------------------------------*/

    /* Note: KEDIT has a limit of 12 items in a LOCATE (or ALL) 0.02*/
    /* The variable <count> is used to insure that no more 0.02*/
    /* than 12 items are in any one search command. 0.02*/

    zone_width = zone.2 - zone.1 + 1
    IF zone_width >= LENGTH( identifier ) + 2
    THEN DO /*0.01*/
    /* zone is wide enough for identifier plus both leading and
    trailing characters 0.01*/

    /* Step 1: find all occurrances of the variable within */
    /* left margin + 1 to right margin - 1 */

    DO ii = 1 TO LENGTH( leading_delimiters );

    prefix = dlm || SUBSTR( leading_delimiters, ii, 1 ) /*0.02*/
    suffix = SUBSTR( trailing_delimiters, 1, 1 ) || dlm /* first
    one 0.02*/
    target = prefix || identifier || suffix
    count = 1 /*0.02*/

    DO jj = 2 TO LENGTH( trailing_delimiters )

    suffix = SUBSTR( trailing_delimiters, jj, 1 ) ||
    dlm /*0.02*/
    addl_target = prefix || identifier || suffix /*0.01*/

    IF LENGTH( target ) + LENGTH( addl_target ) + 1 > 238 |
    count = 12 /*0.02*/
    THEN DO /*0.01*/
    CALL Search_For target /*0.01*/
    count = 0 /*0.02*/
    target = addl_target /*0.01*/
    END /*0.01*/
    ELSE target = target'|'addl_target /*0.01*/

    count = count + 1 /*0.02*/

    END jj

    CALL Search_For target

    END ii

    END /* zone is wide enough for identifier plus both leading and
    trailing characters 0.01*/

    /*----------------------------------------------------------------*/
    /* Cases 2 & 3: the zone is at least one column wider than */
    /* <old_symbol>, so that either the left or right */
    /* margin can act as a delimiter. */
    /*----------------------------------------------------------------*/

    IF zone_width >= LENGTH( identifier ) + 1 /*0.01*/
    THEN DO
    /* zone is wide enough for identifier plus either leading or
    trailing character 0.01*/

    /* Step 2: find all occurrances of the variable with a 0.01*/
    /* suffix between left margin 0.01*/
    /* and ( left margin + variable length + 1 ) 0.01*/
    /* In this case, the left margin acts as a delimiter. 0.04*/

    left_mar = zone.1 /*0.01*/
    right_mar = left_mar + LENGTH( identifier ) /*0.01*/
    'COMMAND SET ZONE' left_mar right_mar /*0.01*/

    prefix = dlm /*0.01*/
    suffix = SUBSTR( trailing_delimiters, 1, 1 ) || dlm /*0.01*/
    target = prefix || identifier || suffix /*0.01*/
    count = 1 /*0.02*/

    DO jj = 2 TO LENGTH( trailing_delimiters ); /*0.01*/

    suffix = SUBSTR( trailing_delimiters, jj, 1 ) || dlm /*0.01*/
    addl_target = prefix || identifier || suffix /*0.01*/

    IF LENGTH( target ) + LENGTH( addl_target ) + 1 > 238 |
    count = 12 /*0.02*/
    THEN DO /*0.01*/
    CALL Search_For target /*0.01*/
    count = 0 /*0.02*/
    target = addl_target /*0.01*/
    END /*0.01*/
    ELSE target = target'|'addl_target /*0.01*/

    count = count + 1 /*0.02*/

    END jj /*0.01*/

    CALL Search_For target /*0.01*/

    /* Step 3: find all occurrances of the variable with a 0.01*/
    /* prefix between ( right margin - identifier length ) 0.01*/
    /* and right margin 0.01*/
    /* In this case, the right margin acts as a delimiter. 0.04*/

    right_mar = zone.2 /*0.01*/
    left_mar = right_mar - LENGTH( identifier ) /*0.01*/
    'COMMAND SET ZONE' left_mar right_mar /*0.01*/

    suffix = dlm /*0.02*/
    prefix = dlm || SUBSTR( leading_delimiters, 1, 1 ) /*0.02*/
    target = prefix || identifier || suffix /*0.01*/
    count = 1 /*0.02*/

    DO ii = 2 TO LENGTH( leading_delimiters ); /*0.01*/

    prefix = dlm || SUBSTR( leading_delimiters, ii, 1 ) /*0.02*/
    addl_target = prefix || identifier || suffix /*0.01*/

    IF LENGTH( target ) + LENGTH( addl_target ) + 1 > 238 |
    count = 12 /*0.02*/
    THEN DO /*0.01*/
    CALL Search_For target /*0.01*/
    count = 0 /*0.02*/
    target = addl_target /*0.01*/
    END /*0.01*/
    ELSE target = target'|'addl_target /*0.01*/

    count = count + 1 /*0.02*/
    END ii /*0.01*/
    CALL Search_For target /*0.01*/

    END /* zone is wide enough for identifier plus either leading or
    trailing character 0.01*/

    /*----------------------------------------------------------------*/
    /* Case 4: the zone is exactly as wide as <old_symbol>, so that */
    /* the left and right margins both act as delimiters. */
    /*----------------------------------------------------------------*/

    IF zone_width = LENGTH( identifier ) THEN DO /*0.01*/
    /* zone is wide enough for identifier only */ /*0.01*/

    /* Step 4: find all occurrances of the variable without 0.01*/
    /* suffix or prefix between left and right margins 0.01*/

    left_mar = zone.1 /*0.01*/
    right_mar = zone.2 /*0.01*/
    'COMMAND SET ZONE' left_mar right_mar /*0.01*/

    prefix = dlm /*0.02*/
    suffix = dlm /* first one */ /*0.02*/
    target = prefix || identifier || suffix /*0.01*/
    CALL Search_For target /*0.01*/

    END /* zone is wide enough for identifier only */ /*0.01*/

    nn = 0 /*0.03*/

    IF cc = 0 /*0.01*/
    THEN DO /* Count # lines found */ /*0.01*/

    '-*' /*0.01*/

    DO nn = 1 BY 1 UNTIL RC <> 0 /*0.01*/
    '+1' /*0.01*/
    END nn /*0.01*/

    nn = nn - 1
    '-* +1' /* position to first line shown */ /*0.01*/

    END /*0.01*/

    Terminate:
    'COMMAND SET ZONE' zone.1 zone.2 /* Restore original ZONE settings
    0.01*/
    'COMMAND SET MSGMODE' msgmode.1 msgmode.2
    'COMMAND SET LINEND' linend.1 /*0.02*/
    'COMMAND SET ARBCHAR' arbchar.1 /*0.02*/
    IF cc = 2
    THEN 'EMSG DMSXCD546E Target not found' /*0.01*/
    ELSE
    IF cc = 0
    THEN 'MSG ALLVAR209I Identifier "'identifier'" found on'
    nn 'lines' /*0.01*/

    EXIT cc

    /*********************************************************************/
    /* */
    /* Search_For: search for ALL target(s) within unselected lines */
    /* */
    /*********************************************************************/

    Search_For: PROCEDURE EXPOSE search_cmd sigl (globals) /*0.02*/

    called_from = sigl /*0.02*/

    edit_cmd = search_cmd 'ALL' ARG(1) /*0.02*/
    ''edit_cmd /*0.02*/

    IF RC = 2 THEN /* target not found */ NOP /*0.02*/
    ELSE DO /*0.02*/
    IF RC = 0 THEN /* target has been acquired */ DO
    IF search_cmd = '' THEN DO
    cc = 0
    search_cmd = 'INCLUDE'
    END
    END /* target has been acquired */
    ELSE /* Processing Error */ DO /*0.02*/
    cc = RC
    'MSGMODE ON' /*0.02*/
    CALL ERRMSG 'ALLVAR291T Unexpected return code' cc 'in line'
    called_from 'from "'edit_cmd'"!' /*0.02*/
    SIGNAL Terminate /*0.02*/
    END /*0.02*/

    END /*0.02*/

    RETURN
    /* _______________________ END OF ALLVAR.THE _______________________ */

    /* REXX INCLUDE.THE -- Adds lines to the set produced by ALL */
    OPTIONS NOEXT_COMMANDS_AS_FUNCS /* for Regina */

    /* Syntax: */
    /* INCLUDE { /? | ? | HELP } */
    /* INCLUDE { FIRST [ ] } searchtarget */
    /* { PRIOR [ ( _1_ | count ) ] } */
    /* { NEXT [ ] } */
    /* { LAST [ ] } */
    /* { ALL } */
    /* { TO limitarget [ ( _*_ | count ) ] } */
    /* Where: */
    /* ALL -- specifies that all lines within the current range */
    /* which match the search <target> will be included */
    /* */
    /* FIRST -- specifies that up to <count> line(s) immediately */
    /* following the top of the current range which match */
    /* the <searchtarget> will be included. */
    /* Searching is begun at the top of the current range, */
    /* and proceeds downward, possibly as far as the bottom */
    /* of the current range. */
    /* A parenthesized <count> or <target> may follow, */
    /* otherwise a default count of 1 is used for FIRST. */
    /* */
    /* PRIOR -- specifies that up to <count> lines preceeding the */
    /* current line, within the current range, which match */
    /* the search <target> will be excluded. */
    /* A parenthesized <count> or <target> may follow, */
    /* otherwise a default count of 1 is used for PRIOR. */
    /* Searching is begun at the top of the current range, */
    /* and proceeds downward, possibly as far as the bottom */
    /* of the current range. */
    /* The setting of WRAP is ignored. */
    /* */
    /* NEXT -- specifies that up to <count> lines following the */
    /* current line, within the current range, which match */
    /* the search <target> will be included. */
    /* A parenthesized <count> or <target> may follow, */
    /* otherwise a default count of 1 is used for NEXT. */
    /* Searching is begun at the current line, and proceeds */
    /* downward, possibly as far as the bottom of the */
    /* current range. The setting of WRAP is ignored. */
    /* */
    /* LAST -- specifies that up to <count> line(s) immediately */
    /* preceeding the bottom of the current range which */
    /* match the search <target> will be included. */
    /* A parenthesized <count> or <target> may follow, */
    /* otherwise a count of 1 is used for LAST. */
    /* Searching is begun at the bottom of the current */
    /* range, and proceeds upward, possibly as far as the */
    /* top of the current range. */
    /* */
    /* Note: if <count> is specified, it must be enclosed in parentheses*/
    /* */
    /* TO limitarget -- specifies that following line(s) which match */
    /* the search target will be included, until <limitarget>*/
    /* is reached. If <limitarget> is not found, no lines */
    /* will be included. */
    /* */
    /* count -- specifies the number of lines to be included. */
    /* The count must be an unsigned integer. */
    /* That is, INCLUDE attempts to find <count> lines which */
    /* match the <srchtarget> to be included. */
    /* Count defaults to 1 for FIRST, LAST, PRIOR, and NEXT. */
    /* Count defaults to "*" for TO. */
    /* */
    /* NOTE: if both TO <limitarget> and <count> are specified, */
    /* INCLUDE stops with the first conditions which is */
    /* satisfied. */
    /* */
    /* limitarget -- specifies the limit of the search for lines to */
    /* be included. That is, INCLUDE will include all lines */
    /* which occur between the current line and the limit */
    /* line which match the <srchtarget>. If <limitarget> */
    /* begins with a minus ("-"), searching will be conducted*/
    /* in an upward direction; otherwise searching will be */
    /* conducted in a downward direction. */
    /* The setting of the WRAP option will affect this search*/
    /* */
    /* srchtarget -- specifies the target to be used to search for */
    /* matching lines to be included. */
    /* NOTE: <srchtarget> MUST *NOT* START WITH A LEFT-PARENTHESIS*/
    /* ( "(" ) unless "(<count>)" is also specified!! */
    /* NOTE: <srchtarget> may *not* start with a plus ("+") or */
    /* minus ("-")! (This is because the direction of the */
    /* search is determined by the */
    /* ALL/PRIOR/NEXT/TO <limitarget>/FIRST/LAST keywords) */
    /* */
    /* RETURNS: */
    /* 0 -- Normal: <count> lines containing the <searchtarget> */
    /* were found, and either <count> was "*" or the process */
    /* stopped when <count> lines had been found. */
    /* 1 -- One or more lines containing the <searchtarget> were */
    /* found, but <count> was not exhausted before the end of */
    /* the searchable portion of the range was reached. */
    /* 2 -- DMSXDC546E Target not found */
    /* 5 -- DMSXDC520E Invalid operand: ... */
    /* */
    /*___________________________________________________________________*/
    /* */
    /* Rev Who? When? What? */
    /* ----- ----- -------- ---------------------------------------------*/
    /* 0.0 RAC 11/24/93 Original (did ALL lines) */
    /* 0.1 RAC ? Added ALL/PRIOR/NEXT & count parameters */
    /* 0.2 RAC 07/03/96 Added FIRST/LAST mode parameters */
    /* 0.3 RAC 07/08/96 Added TO mode parameter */
    /* 0.4 RAC 07/12/99 Converted to KEDIT for Windows 1.5 KEXX */
    /* Added logic to require ALL be issued first, */
    /* fixed logic for displaying message and */
    /* returning to original line (marked) */
    /* 0.5 RAC 08/20/99 Added support for label as a <srchtarget> */
    /* 0.6 RAC 12/08/99 Corrected HELP for FIRST and LAST. */
    /* 0.7 RAC 12/09/99 Added prereq for GETARGET. */
    /* 0.8 RAC 10/26/00 Fixed bugs. */
    /* 0.9 RAC 11/12/02 THE version (no RANGE support) */
    /* */
    /* Programming Notes: */
    /* 1) In order to convert from XEDIT REXX to KEDIT for Windows, v1.5 */
    /* KEXX, the following changes were made: */
    /* a) all continued instructions were made into a single line */
    /* b) the REXX comment on the first line was */
    /* changed to a single-line KEX comment ("*" in column 1) */
    /* c) all multi-line REXX comments were changed to single-line */
    /* REXX comments */
    /* d) changed "ª" to "\" when used as REXX unary Not operator */
    /* e) changed "ª=" to "<>" when used as REXX Not-Equal operator */
    /* f) changed "ª" to "^" when used as KEDIT string Not operator */
    /* g) add "msgmode.2=''" prior to every "EXTRACT/MSGMODE/" because*/
    /* 2nd parameter to MSGMODE is supported by XEDIT but not KEDIT*/
    /* h) add logic to cause the alteration count to go up by only 1 */
    /* for the entire execution of the macro if the macro makes */
    /* any changes to the file (otherwise KEDIT counts every */
    /* change made by the macro, and AUTOSAVEs may occur many */
    /* times during the execution of the macro; even though a */
    /* single UNDO will reverse all the changes made by the macro).*/
    /* This yields XEDIT's behaviour. */
    /* i) change PRESERVE and RESTORE to EXTRACT and SET for the */
    /* editing environment settings being changed. This is */
    /* necessary because KEDIT's PRESERVE/RESTORE stack is only */
    /* one level deep! Be sure not to use EXIT after any editor */
    /* settings have been changed, or they will not be restored! */
    /* j) shorten lines longer than 250 characters */
    /* k) break apart programs longer than 4000 characters */
    /* l) reduce the maximum NUMERIC DIGITS to 50 */
    /* m) remove STREAM() function */
    /* n) remove NOTREADY */
    /* o) provide the first argument for LINEIN(), LINEOUT(), LINES(),*/
    /* CHARIN(), CHAROUT(), and CHARS() */
    /* p) remove "@", "#", and "$" from symbol names (they shouldn't */
    /* be there anyway!) */
    /* */
    /* 2) To convert to KEX for Windows, v1.0, the following additional */
    /* changes must be made: */
    /* a) Change binary constants ('1001'B) to hexadecimal ( '9'X) */
    /* b) Remove CALL ON and CALL OFF */
    /* c) Remove parenthesized symbol names in DROP statements: */
    /* DROP (list_of_symbol_names) */
    /* becomes: */
    /* INTERPRET 'DROP' list_of_symbol_names */
    /* c) Remove any CALL instructions and function invocations which */
    /* invoke internal routines from INTERPRET instructions */
    /* d) Remove PROCEDURE [EXPOSE] instructions */
    /* e) Change SELECT WHEN [OTHERWISE] END instructions to a */
    /* series of cascaded IF instructions: */
    /* SELECT */
    /* WHEN boolexpr1 THEN clause1 */
    /* WHEN boolexpr2 THEN clause2 */
    /* ... */
    /* WHEN boolexprN THEN clauseN */
    /* OTHERWISE clauseE */
    /* END */
    /* becomes: */
    /* /* SELECT */ */
    /* IF boolexpr1 THEN clause1 */
    /* ELSE IF boolexpr2 THEN clause2 */
    /* ... */
    /* ELSE IF boolexprN THEN clauseN */
    /* ELSE clauseE */
    /* /* END */ */
    /* f) Remove all forms of SIGNAL */
    /* g) Remove all invocations of external routines */
    /* h) Remove all invocations of these BIFs: */
    /* i) B2X() */
    /* ii) CHANGESTR() */
    /* iii) CONDITION() */
    /* iv) COUNTSTR() */
    /* v) ERRORTEXT() */
    /* vi) SOURCELINE() */
    /* vii) SYMBOL() */
    /* viii) TRACE() */
    /* ix) VALUE() */
    /* x) X2B() */
    /* */
    /* 3) To convert to KEX for DOS, v5.0, the following additional */
    /* changes must be made: */
    /* a) Remove all instructions other than IF, DO, ITERATE, LEAVE, */
    /* EXIT, DROP, NOP */
    /* b) Convert any WHILE or UNTIL clauses on DO instructions to */
    /* LEAVE instructions */
    /* c) Remove any <name> from ITERATE, LEAVE, or END */
    /* */
    /* */

    SIGNAL ON NOVALUE

    cc = 0 /*0.08*/
    globals = '_call_stack' /*0.08*/
    _call_stack = 'INCLUDE'

    token1 = LEFT( STRIP( ARG( 1 ) ), 1 )
    token2 = LEFT( STRIP( ARG( 1 ) ), 2 )
    token4 = TRANSLATE( LEFT( STRIP( ARG( 1 ) ), 4 ) )
    IF token1 = '?' | token2 = '/?' | token4 = 'HELP' THEN DO
    'XE EXCLUDE.KEX' /* Use comments for quick-and-dirty help 0.4*/
    EXIT 0
    END

    /* 0.4 Check for unconditional prerequisites */ /*0.07*/

    /* 0.4.1 Check for unconditionally required file(s) */ /*0.07*/

    /* cc = MAX( Require( 'GETARGET.KEX' ), cc ) 0.08*/

    /* Get mode of operation */
    the_rest = ARG( 1 )
    nn = VERIFY( TRANSLATE(
    the_rest' ' ), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ) - 1
    PARSE ARG mode +(nn) the_rest
    mode = TRANSLATE( mode ) /* fold to uppercase */
    the_rest = STRIP( the_rest, 'L' ) /* remove optional leading space
    (s) */
    direction = '+' /* default to forward */

    'EXTRACT/SIZE/'
    SELECT /* Case of <mode> */
    WHEN mode = 'ALL' THEN DO
    count = size.1 /* could be every line in the file! */
    limitarget = ''
    END
    WHEN WORDPOS( mode, 'PRIOR NEXT FIRST LAST' ) > 0 THEN DO
    IF mode = 'PRIOR' | mode = 'LAST' THEN direction = '-' /*
    backward */
    END
    WHEN mode = 'TO' THEN DO
    /* Get limit target */
    PARSE VALUE GeTarget( the_rest ) WITH target_type
    remaining_length limitarget
    IF target_type = 'I' THEN DO
    'EMSG ***ERROR*** Limit target, "'LEFT( the_rest, LENGTH(
    the_rest ) - remaining_length)'", is invalid!'
    EXIT 5
    END
    the_rest = RIGHT( the_rest, remaining_length )
    END
    OTHERWISE DO
    'EMSG ***ERROR*** First argument to INCLUDE must be one of "ALL
    PRIOR NEXT FIRST LAST TO"!'
    EXIT 13
    END
    END /* Case of <mode> */

    IF WORDPOS( mode, 'PRIOR NEXT FIRST LAST TO' ) > 0 THEN DO
    /* check for optional "( <count> )" */
    IF LEFT( the_rest, 1 ) = '(' THEN /* count follows */ DO
    PARSE VALUE the_rest WITH '(' count ')' the_rest
    the_rest = STRIP( the_rest, 'L' )
    count = STRIP( count )
    IF count = '*'
    THEN count = size.1 /* search up to every line in the file */
    ELSE /* count should be unsigned integer */ DO
    IF VERIFY( count, '0123456789' ) <> 0 THEN DO
    'EMSG ***ERROR*** Count, "'count'", must be an unsigned
    integer!'
    EXIT 15
    END
    END
    END
    ELSE /* ( <count> ) not specified */ DO
    /* Supply default value for <count> */
    IF mode = 'TO'
    THEN count = size.1 /* could be every line in the file! */
    ELSE count = 1 /* Only 1 for FIRST/LAST/PRIOR/NEXT */
    END
    END /* check for optional "( <count> )" */

    IF the_rest = '' THEN DO
    'EMSG ***ERROR*** Search target is missing!'
    EXIT 17
    END

    IF POS( LEFT( the_rest, 1 ), '+-' ) > 0 THEN DO
    'EMSG ***ERROR*** Search target, "'the_rest'", starts with plus
    or minus!'
    EXIT 19
    END

    IF POS( LEFT( the_rest, 1 ), '.' ) > 0 THEN DO /*0.5 */
    direction = '' /*0.5 */
    count = 1 /* There may only be one of this label */ /*0.5 */
    END /*0.5 */

    PARSE VALUE GeTarget( direction || the_rest ) WITH target_type
    remaining_length srchtarget

    IF target_type = 'I' THEN DO
    'EMSG ***ERROR*** Search target, "'the_rest'", is invalid!'
    EXIT 5
    END

    IF remaining_length <> 0 THEN DO
    'EMSG ***ERROR*** Search target, "'the_rest'", contains multiple
    targets!'
    EXIT 21
    END

    /* Search logic ... */

    msgmode.2 = '' /*0.4 */
    'EXTRACT/MSGMODE/WRAP/SCOPE/' /* PRESERVE */ /*0.4 */
    'EXTRACT/LINE/DISPLAY/STAY/' /*0.4 */
    /* 'EXTRACT/RANGE/' */ /*0.9 */
    lo_level = display.1
    hi_level = display.2

    IF lo_level = 0 & hi_level = 0 THEN DO /*0.4 */
    'EMSG ***ERROR*** ALL command must be issued prior to
    INCLUDE!' /*0.4 */
    EXIT 16 /*0.4 */
    END /*0.4 */

    IF mode = 'ALL' | mode = 'FIRST' THEN '-*'
    IF mode = 'LAST' THEN '+*'

    IF mode = 'TO' THEN DO
    IF LEFT( limitarget, 1 ) = '-' THEN DO
    'LOCATE' limitarget
    /* 'RANGE +0 :'line.1 */ /*0.9 */
    'LOCATE :'line.1
    END
    /* ELSE 'RANGE +0' limitarget */ /*0.9 */
    END

    'SET WRAP OFF' /* Prevents infinite loop */
    /* NOTE: after this point, EXIT should no longer be used 0.1 */
    /* to leave the macro, because the WRAP setting 0.1 */
    /* would not be restored. Instead use SIGNAL Abort 0.1 */
    /* to cause an orderly termination. 0.1 */

    /* Note: STAY setting has no effect */
    'SET SCOPE ALL' /* Operate on ALL lines in file */
    'L' srchtarget
    cc = RC
    IF RC = 0 THEN /* target found */ DO
    nn = 0 /* number of lines satisfying search criteria */
    kk = 0 /* number of lines added to displayed set */
    'SET MSGMODE OFF'
    DO mm = 1 TO count WHILE RC = 0
    nn = nn + 1
    'EXTRACT/SELECT/'
    IF select.1 < lo_level | select.1 > hi_level THEN
    /* not previously displayed */ kk = kk + 1
    'SET SELECT' lo_level '1'
    'L' srchtarget
    END
    'SET MSGMODE ON' /*0.4 */
    'MSG Included' kk 'of' nn 'lines with' the_rest
    END

    IF nn > 1 THEN DO
    IF nn = count | count = size.1
    THEN cc = 0
    ELSE cc = 1
    END
    ELSE cc = 2

    /* 'RANGE :'range.1 ':'range.2 */ /*0.9 */
    IF stay.1 = 'ON' THEN DO /*0.4 */
    'SET MSGMODE OFF' /* suppress "Not Found" message for */ /*0.4 */
    /* original line, if it was excluded*/ /*0.4 */
    ':'line.1
    IF RC <> 0 /* original current line was excluded */ /*0.4 */
    THEN '-* +1' /* position to first displayed line */ /*0.4 */
    END /*0.4 */

    /* 'RESTORE' any editor settings we may have changed */
    'SET MSGMODE' msgmode.1 msgmode.2
    'SET WRAP' wrap.1
    'SET SCOPE' scope.1

    EXIT cc

    /****************************************************************0.07*/
    /* 0.07*/
    /* REQUIRE -- check for prerequisite file 0.07*/
    /* 0.07*/
    /****************************************************************0.07*/

    Require: PROCEDURE EXPOSE (globals) sigl /*0.07*/
    RETURN 0

    /* 1. Debugging Prologue */ /*0.07*/
    _save_calls = _call_stack /*0.07*/
    _call_stack = 'Require called from line' sigl 'in'
    _call_stack /*0.07*/
    /* use the following once the subroutine is debugged... */ /*0.07*/
    _save_trace = TRACE( 'F' ) /* trace only failures, save old
    setting 0.07*/
    IF VERIFY( _save_trace, '?!NOF' ) <> 0 /*0.07*/
    THEN /* begin debugging code */ DO /*0.07*/
    SAY '==> Internal_Function called from' sigl 'with ' , /*0.07*/
    || ARG() 'arguments:' /*0.07*/
    DO result = 1 TO ARG() /*0.07*/
    SAY ' Argument' result ':= `'ARG(result)'`' /*0.07*/
    END result /*0.07*/
    DROP result /*0.07*/
    END /* end debugging code */ /*0.07*/

    /* 2. Function Logic */ /*0.07*/

    PARSE UPPER ARG filespec /*0.07*/

    IF STREAM( filespec, 'C', 'QUERY EXISTS' ) = '' THEN DO /*0.07*/
    SAY 'INCLUD013T Required resource, "'filespec , /*0.07*/
    || '", is not available' /*0.07*/
    cc = 16 /*0.07*/
    END /*0.07*/
    ELSE cc = 0 /*0.07*/

    /* 3. Debugging Epilogue */ /*0.07*/

    IF VERIFY( _save_trace, '?!NOF' ) <> 0 /*0.07*/
    THEN /* begin debugging code */ DO /*0.07*/
    SAY '==> Require returns `'cc'`' /*0.07*/
    END /* end debugging code */ /*0.07*/
    _call_stack = _save_calls /*0.07*/

    RETURN cc /* ENDPROC Require */ /*0.07*/
    /* _______________________ END OF INCLUDE.THE ______________________ */

    /*REXX GETARGET.THE -- routine to parse a single XEDIT target */
    OPTIONS NOEXT_COMMANDS_AS_FUNCS /* for Regina */

    /* This routine was converted from GETARGET XEDIT, so changes to this
    * routine may also have to be made to the source as well, and vice
    versa

    * Syntax:
    * GeTarget( <argument> )
    *
    * Where:
    * <argument> is a string whose leading characters are to be
    * parsed for a valid XEDIT target
    *
    * Returns: <target_type> <remaining_length> <target>
    * <target_type> is a type code --
    * L = label
    * AN = absolute number
    * RN = relative number
    * S = string
    * I = invalid target
    * <remaining_length> is the number of characters following the
    * target, after any intervening blanks have been removed.
    * In the case of an invalid target, this number reflects
    * the number of characters following the point at which
    * the syntax error was detected.
    * <target> is described by the following syntax --
    * { .<label> }
    * { : <number> }
    * { [+|-] <number> }
    * { [+|-] [\] <delim><text>[<delim> --. }
    * { .--------------------------------' }
    * { `--> [ {&|"|"} [\] <delim><text><delim> ]... --. }
    * { .-------------------------------------------' }
    * { `--> [ {&|"|"} [\] <delim><text>{<delim>|eol} ] ] }
    *
    * Notes:
    * In the above syntax, a space appears in those places where
    * one or more blanks are allowed.
    * In the above syntax, a number is terminated by the first
    * non-digit encountered.
    * The REXX construct, RIGHT( argument, remaining_length ) can be
    * be used to obtain the portion of the argument following the
    * target.
    * The non-target portion of <argument> could not be returned in
    * character form, because there is no delimiter which could
    * be used to separate it from <target>.
    *
    *_____________________________________________________________________
    *
    * Rev Who? When? What?
    * ----- ----- -------- ---------------------------------------------
    * 0.0 RAC 03/04/97 Original
    * 0.1 RAC 07/12/99 Converted to KEDIT 5 KEXX (not marked)
    *
    * Programming Notes:
    * 1) In order to convert to KEX, the following changes were made:
    * a) all SIGNAL instructions were commented out
    * b) all continued instructions were made into a single line
    * c) all single and multi-line REXX comments ("/*" to "*/" were
    * changed to single-line KEX comments ("*" in column 1)
    * d) changed "^" to "\" when used as REXX unary Not operator
    * e) changed "^=" to "<>" when used as REXX Not-Equal operator
    * f) changed "^" to "^" when used as KEDIT string Not operator
    * g) add "msgmode.2 = ''" prior to every "EXTRACT/MSGMODE/" because
    * 2nd parameter to MSGMODE is supported by XEDIT but not KEDIT.
    *
    *
    */

    SIGNAL ON NOVALUE

    arg1 = STRIP( ARG( 1 ) ) /* remove leading & trailing blanks */
    char1 = LEFT( arg1, 1 ) /* first non-blank character */

    SELECT /* Case of first non-blank character */
    WHEN char1 = ':' THEN /* absolute number or string */ DO
    IF POS( LEFT( STRIP( SUBSTR( arg1, 2), 'L' ),
    1 ), '*0123456879' ) > 0
    THEN type = 'AN' /* relative number */
    ELSE type = 'S' /* string */
    END /* absolute number or string */
    WHEN POS(char1, '*0123456789') > 0 THEN type = 'RN' /* relative
    number */
    WHEN char1 = '.' THEN type = 'L' /* label */
    WHEN POS( char1, '+-' ) > 0 THEN /* relative number or string */
    DO
    IF POS( LEFT( STRIP( SUBSTR( arg1, 2), 'L' ),
    1 ), '*0123456879' ) > 0
    THEN type = 'RN' /* relative number */
    ELSE type = 'S' /* string */
    END /* relative number or string */
    WHEN char1 = ' ' THEN type = 'I' /* invalid */
    OTHERWISE type = 'S' /* '^' or string delimiter */
    END /* Case of first non-blank character */

    SELECT /* Case of target type */
    WHEN type = 'S' THEN DO
    IF POS( char1, '+-' ) > 0 THEN /* leading optional direction
    */ DO
    target = char1
    arg1 = STRIP( SUBSTR( arg1, 2 ), 'L' )
    char1 = LEFT( arg1, 1 ) /* next non-blank character */
    END
    ELSE target = ''
    done = 0

    /* Note: loop is entered with "arg1" stripped of leading
    blanks */
    /* and "char1" containing a copy of its first
    character. */
    DO ii = 1 BY 1 WHILE arg1 <> '' & \ done

    IF char1 = ' ' THEN DO
    type = 'I'
    LEAVE ii
    END

    IF char1 = '^' THEN DO
    target = target || char1
    arg1 = STRIP( SUBSTR( arg1, 2 ), 'L' )
    char1 = LEFT( arg1, 1 ) /* next non-blank character */
    IF char1 = ' ' THEN DO
    type = 'I'
    LEAVE ii
    END
    END

    PARSE VALUE arg1 WITH (char1) text (char1) arg1
    target = target || char1 || text || char1
    arg1 = STRIP( arg1, 'L' ) /* strip leading blanks */
    char1 = LEFT( arg1, 1 ) /* next non-blank character */

    IF POS( char1, '&|' ) = 0 THEN done = 1
    ELSE /* another boolean term follows */ DO
    target = target || char1
    arg1 = STRIP( SUBSTR( arg1, 2 ), 'L' )
    char1 = LEFT( arg1, 1 ) /* next non-blank character */
    END

    END /* until no more input, or end of target */

    END /* type was String */
    WHEN type = 'I' THEN /* Invalid type */ NOP
    WHEN type = 'L' THEN /* Label */ DO
    target = char1
    arg1 = SUBSTR( arg1, 2 )
    char1 = LEFT( arg1, 1 )
    IF char1 = ' ' THEN type = 'I'
    ELSE PARSE VALUE target || arg1 WITH target arg1
    END
    OTHERWISE /* type is number (either absolute or relative) or line#
    */ DO
    target = ''
    IF POS( char1, '+-:' ) > 0 THEN DO
    target = char1 /* "+", "-", or ":" */
    arg1 = STRIP( SUBSTR( arg1, 2 ), 'L' )
    char1 = LEFT( arg1, 1 )
    END
    IF char1 = '*' THEN DO
    target = target || char1
    arg1 = STRIP( SUBSTR( arg1, 2 ), 'L' )
    END
    ELSE DO
    nn = VERIFY( arg1, '0123456789' ) - 1 /* pos of 1st non-
    digit */
    IF nn = -1 THEN nn = LENGTH( arg1 ) /* all
    numeric */
    PARSE VALUE arg1 WITH num +(nn) arg1
    target = target || num
    arg1 = STRIP( arg1, 'L' ) /* strip leading
    blanks */
    END
    END
    END /* Case of target type */

    RETURN type LENGTH( arg1 ) target
    /* ______________________ END OF GETARGET.THE ______________________ */

     

Log in to post a comment.