home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / epm603a.zip / EPMSMP.ZIP / EGREPXMP.E < prev    next >
Text File  |  1995-11-10  |  7KB  |  132 lines

  1. ;  Extended GREP searching in EPM 6.0x
  2. ;
  3. ; EGREP can be used for more than just searching though a file - you can
  4. ; also use it directly to search a given string, and can pre-compile the
  5. ; search string into an EGREP program for better performance in a loop.
  6. ; Here are some examples.
  7. ;
  8. ; Larry Margolis
  9. --------------------------------------------------------------------------
  10.  
  11. ; Some examples of using Extended GREP from the macros for other than searching
  12. ; through a file.
  13.  
  14. ; First, we pass 'X' as a fourth parameter to Pos(), to tell it that the search
  15. ; string is an EGREP expression rather than a simple string:
  16.  
  17. defc qpos =
  18.    prog = 'a.*t'
  19.    searchstr = 'This is a test.'
  20.    sayerror 'Result =' pos(prog, searchstr, 1, 'X')
  21.  
  22. ; Next, we also pass in 'M' to specify that we want to be given a result
  23. ; showing all matches, not just the starting column of the "hit".  This
  24. ; gives a start and end column for the entire match, followed by start
  25. ; and end columns for each parenthesized expression in the search string
  26. ; (in the order in which the open parens were seen).
  27.  
  28. defc qposm =
  29.    prog = '(q:a*) (:c)'
  30.    searchstr = 'The quick brown fox jumps over the lazy dog.'
  31.    Result = pos(prog, searchstr, 1, 'XM')
  32.    parse value result with s0 e0 s1 e1 s2 e2  -- We know this succeeded; failure would return just 0.
  33.    sayerror 'Result =' result 'entire match = "'substr(searchstr, s0, e0-s0+1)'", q:a* = "'substr(searchstr, s1, e1-s1+1)'", following word = "'substr(searchstr, s2, e2-s2+1)'"'
  34.  
  35. include 'stdconst.e'
  36.  
  37. ; Here, we split the compilation of the regular expression into a program, and
  38. ; the execution of that program, into two pieces.  This saves on the overhead of
  39. ; recompiling the program every time, if it will be used repeatedly.
  40.  
  41. defc regtest =
  42.    prog = 'a.*t'
  43.    regprog = RegExpComp(prog)
  44.    searchstr = 'This is a test.'
  45.    exec_result = RegExpExec(regprog, searchstr)
  46.    call dynalink32(E_DLL,         -- dynamic link library name
  47.                    'myfree',                   -- DosFreeSeg
  48.                    atol(regprog))
  49.    sayerror 'Result =' exec_result 'regprog =' regprog '= 0x'ltoa(atol(regprog), 16)
  50.  
  51. ; Here, we use the E Toolkit dynalink calls to do something similar.  The
  52. ; differences are that the program must have a null at the end; the
  53. ; program string and string to be searched are passed as pointers rather
  54. ; than EPM strings (meaning that strings much longer than EPM's limit of
  55. ; 1600 characters can be passed, by using a buffer instead of an EPM
  56. ; string); and the result positions are offsets (0-based) rather than
  57. ; character positions (1-based).  This returns a Boolean for success or
  58. ; failure, and up to 20 shorts in the provided buffer, corresponding to
  59. ; 10 start positions and 10 end positions as returned in qposm(), above.
  60. ; Note that non-matched positions are set to -1, which itoa() returns
  61. ; as 65535.
  62.  
  63. defc regtktest =
  64.    prog = 'a.*t'\0
  65.    regprog = dynalink32( E_DLL,                     -- library name
  66.                          'EtkRegexpComp',           -- function name
  67.                          gethwndc(EPMINFO_EDITCLIENT)  ||
  68.                          address(prog), 2 )
  69.    if not regprog then
  70.       sayerror 'regprog is 0!'
  71.       return
  72.    endif
  73.    searchstr = 'This is a test.'
  74.    resultbuf = copies(\0, 40)
  75.    exec_result = dynalink32( E_DLL,                     -- library name
  76.                              'EtkRegexpSearch',         -- function name
  77.                              gethwndc(EPMINFO_EDITCLIENT)  ||  -- Window handle
  78.                              atol(regprog)                 ||  -- pointer to program
  79.                              address(searchstr)            ||  -- pointer to input string
  80.                              atol(length(searchstr))       ||  -- length of input string
  81.                              atol(0)                       ||  -- Boolean REVERSE flag
  82.                              address(resultbuf)            ||  -- pointer to result buffer
  83.                              atol(length(resultbuf)) )         -- length of result buffer
  84.    call dynalink32(E_DLL,         -- dynamic link library name
  85.                    'myfree',                   -- DosFreeSeg
  86.                    atol(regprog))
  87. ;  startptrs = leftstr(result_buf, 20)
  88. ;  endptrs = substr(result_buf, 20)
  89.    s0 = itoa(substr(resultbuf,  1, 2), 10)
  90.    e0 = itoa(substr(resultbuf, 21, 2), 10)
  91.    s1 = itoa(substr(resultbuf,  3, 2), 10)
  92.    e1 = itoa(substr(resultbuf, 23, 2), 10)
  93.    sayerror 'Result =' exec_result 'start =' s0 'end =' e0 'start1 =' s1 'end1 =' e1
  94.  
  95. ; Finally, we use a combination of techniques:  we precompile the program, but
  96. ; then pass it to Pos() (because we want to use the Match option).  We include
  97. ; a 'P' in the fourth parameter to Pos() to indicate that we're passing a
  98. ; Precompiled program.  This example removes all comments (delimited with
  99. ; /* ... */ ) and quoted strings from the input line.  The original code first
  100. ; obtained the position of the first '/*', the first single quote, and the
  101. ; first double quote on the line; determined which was smallest (but non-zero,
  102. ; because pos() returns 0 if the search string isn't found), then looked for
  103. ; the appropriate end for the first quote or comment starter found.  If the
  104. ; end was found, the match (start to end) was blanked out; if no end was found,
  105. ; the input string was truncated at the start point.  When rewritten to use the
  106. ; EGREP option, the resulting code is much shorter.  It's also slower - 100
  107. ; iterations of the original code took 3.469 seconds, while 100 iterations of
  108. ; the EGREP code took 6.5 seconds.  Precompiling the program outside of the loop
  109. ; cured the slowness; the same 100 iterations now took 2.125 seconds - even
  110. ; faster than the original code (for this test string).  The original code
  111. ; can be seen in TAGS.E, in rexx_proc_search() - it's still fastest when
  112. ; there are no comments or quoted strings in the text.
  113.  
  114. defc stripstuff =
  115.    regprog = RegExpComp('/\*.@(\*/|$)|"[^"]*("|$)|''[^'']*(''|$)')
  116.    line = '12"/*"34''*/"''56/*a''"''"*/78''"a"''9'
  117.    e0 = 0
  118.    loop                -- Remove comments & quotes
  119.       parse value pos(regprog, line, e0+1, 'XMP') with s0 e0 .
  120.       if not s0 then leave; endif
  121.       if e0 = length(line) then
  122.          line=leftstr(line, s0-1)
  123.       else
  124.          line=overlay('', line, s0, e0-s0+1)  -- Keep column alignment
  125.       endif
  126.    endloop
  127.    call dynalink32(E_DLL,         -- dynamic link library name
  128.                    'myfree',                   -- DosFreeSeg
  129.                    atol(regprog))
  130.    sayerror 'result = >'line'<'
  131.  
  132.