* PARSET.KEX * Parse a target from the beginning of argument, return its length * Example: * a = '/x/&~,/, foo' /* a = argument */ * i = parset(a) /* i = length of target = 8 */ * t = left(a,i) /* t = target = '/x/&~,/,' */ * r = substr(a,1+i) /* r = remainder = ' foo' */ * or: * i = 1 + parset(a) /* i = 1+length of target = 9 */ * parse var a t =(i) r /* Same t and r as above */ * Assumes a valid target; doesn't attempt to diagnose invalid ones * Changes from XEDIT for KEDIT: * Change logical negation character from '¬' to '~' * Additions for KEDIT: * Allow ';' as an absolute line number prefix (same as ':') * Handle special string target prefixes: * Word, Prefix, Suffix, Regexp * Handle group targets: * ALL, BLOCK, PARAgraph * Handle line class targets: * BLAnk, NEW, CHAnged, TAGged, ALTered, SELect n [m|*] * 27 Sep 1998 Rex Swain, Independent Consultant, rex@rexswain.com parse upper arg str /* Argument; note UPPER */ * ----- Is there a first non-blank character? ----- fst = verify(str,' ') /* Pos first non-blank char */ if fst = 0 then /* Target = '' */ return fst /* Empty/all-blank; return 0 */ * ----- Examine the first non-blank character ----- ch1 = substr(str,fst,1) /* First non-blank char */ if ch1 = '*' then /* Target = '*' */ return fst if ch1 = '.' then /* Target = '.name' */ return pos(' ',str||' ',1+fst) - 1 len = length(str) /* Length of entire string */ lp1 = 1 + len /* Global for nomatch() */ dig = '1234567890' /* All digits */ if member(ch1,dig) then return nomatch(dig,1+fst) - 1 * ----- Is there a second non-blank character? ----- ptr = verify(str,' ',,1+fst) /* Pos second non-blank char */ if ptr = 0 then /* Only one non-blank char? */ return fst * ----- Examine the second non-blank character ----- ch2 = substr(str,ptr,1) /* Second non-blank char */ if member(ch1,':;+-') then do /* Prefix one of ':;+-' */ if ch2 = '*' then /* Target = 'p*' */ return ptr if member(ch2,dig) then /* Target = 'p123' */ return nomatch(dig,1+ptr) - 1 end * ----- It must be a string or group or line class target ----- let = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' /* All letters */ ptr = fst /* Back to first non-blank */ if member(ch1,'+-') then /* Leading + or - ? */ ptr = ptr + 1 /* Advance over it */ do forever ptr = nomatch(' ',ptr) /* Pos of next non-blank */ if substr(str,ptr,1) = '~' then /* If it is '~' */ ptr = nomatch(' ',1+ptr) /* Skip over it */ del = substr(str,ptr,1) /* Probably leading delimiter */ fcd = 1 /* Must find closing delim */ if member(del,let) then do /* A letter? */ i = nomatch(let,1+ptr) /* Next non-letter */ key = substr(str,ptr,i-ptr) /* Keyword */ if kw1() then do /* String target prefix? */ ptr = nomatch(' ',i) /* Skip to next non-blank */ del = substr(str,ptr,1) /* This is leading delimiter */ end else do /* Must be some other keyword */ if kw2() then do /* Group or line class? */ ptr = i /* Skip over it */ fcd = 0 /* Do not find closing delim */ end if kw3 then do /* SELECT? */ ptr = nomatch(' ',ptr) /* Next non-blank */ ptr = nomatch(dig,ptr) /* Next non-digit */ ptr = nomatch(' ',ptr) /* Next non-blank */ c = substr(str,ptr,1) /* That non-blank char */ if c = '*' then /* Asterisk? */ ptr = ptr + 1 /* Skip over it */ if member(c,dig) then /* Digit? */ ptr = nomatch(dig,ptr)/* Skip over digits */ end /* End if SELECT */ end /* End if other keyword */ end /* End if a letter */ if fcd then do /* Find closing delimiter? */ ptr = pos(del,str,1+ptr) /* Find closing delimiter */ if ptr = 0 then /* Not found? */ return len /* Target = entire string */ ptr = ptr + 1 /* Advance past it */ end i = nomatch(' ',ptr) /* Pos next non-blank char */ c = substr(str,i,1) /* Next non-blank char */ if member(c,'|&') then /* Logical connector? */ ptr = i + 1 /* Advance; continue loop */ else /* This is end of target */ return ptr - 1 /* We're done */ end /* End do forever */ exit /* Cannot get here! */ * ----- Subroutines ----- nomatch: procedure expose str lp1 * Find next non-matching character in global str * Return 1+length(str) if not found, rather than 0 parse arg c,s /* Characters, starting pos */ i = verify(str,c,,s) if i = 0 then i = lp1 return i member: procedure * Is character one of the characters in string parse arg c,s /* Character, string */ return pos(c,s) > 0 kw1: * Test global key for a string target prefix keyword if abbrev('WORD' ,key,1) then return 1 if abbrev('REGEXP',key,1) then return 1 if abbrev('PREFIX',key,1) then return 1 if abbrev('SUFFIX',key,1) then return 1 return 0 kw2: * Test global key for a group or line class target keyword * Also set global kw3 flag if it is SELECT kw3 = abbrev('SELECT',key,3) if kw3 then return 1 if key = 'ALL' then return 1 if key = 'NEW' then return 1 if key = 'BLOCK' then return 1 if abbrev('BLANK' ,key,3) then return 1 if abbrev('TAGGED' ,key,3) then return 1 if abbrev('CHANGED' ,key,3) then return 1 if abbrev('ALTERED' ,key,3) then return 1 if abbrev('PARAGRAPH',key,4) then return 1 return 0