home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / ipl / progs / igrep.icn < prev    next >
Text File  |  2000-07-29  |  6KB  |  188 lines

  1. ############################################################################
  2. #
  3. #    File:     igrep.icn
  4. #
  5. #    Subject:  Program for string search similar to egrep
  6. #
  7. #    Author:   Robert J. Alexander
  8. #
  9. #    Date:     May 1, 1994
  10. #
  11. ############################################################################
  12. #
  13. #   This file is in the public domain.
  14. #
  15. ############################################################################
  16. #
  17. #  Program to emulate UNIX egrep, but using the enhanced regular
  18. #  expressions supported by regexp.icn.  Options supported are nearly
  19. #  identical to those supported by egrep (no -b:  print disk block
  20. #  number).  There is one additional option, -E, to allow Icon-type
  21. #  (hence C-type) string escape sequences in the pattern string.
  22. #  BEWARE:  when -E is used, backslashes that are meant to be processed
  23. #  in the regular expression context must be doubled.  The following
  24. #  patterns are equivalent:
  25. #
  26. #   without -E: '\bFred\b'
  27. #   with    -E: '\\bFred\\b'
  28. #
  29. #  To enable the -D option (intended mainly for debugging), the Icon
  30. #  Program Library file "ximage" must be linked with this program.
  31. #
  32. ############################################################################
  33.  
  34. procedure Usage(n)
  35.    write(&errout,
  36.       "igrep -- emulates UNIX egrep\n_
  37.       Usage: igrep -Options [expression] filename..._
  38.     \n  Options:_
  39.     \n  c   print count of matching lines rather than actual lines_
  40.     \n  h   don't display file names_
  41.     \n  i   ignore case of letters_
  42.     \n  l   list only the names of files containing matching lines_
  43.     \n  n   precede lines with line numbers_
  44.     \n  s   work silently -- display nothing_
  45.     \n  v   invert search to display only lines that don't match_
  46.     \n  e expr  useful if expressions starts with -_
  47.     \n  E expr  expresson containing Icon escape sequences_
  48.     \n  f file  take list of alternated expressions from \"file\""
  49. #   ,if \xdump then
  50. #   "\n D   dump compiled pattern and quit" else ""
  51. )
  52.    exit(n)
  53. end
  54.  
  55. link options,regexp
  56.  
  57. procedure main(arg)
  58.    local compiledPattern
  59.    if *arg = 0 then Usage()
  60.    Options(arg)
  61.    compiledPattern := GetPattern(arg) |
  62.          {write(&errout,"Bad pattern ",image(Pattern)) ; exit(2)}
  63. #   if \Dump then (\xdump)(compiledPattern)
  64.    exit(ScanFiles(arg,compiledPattern))
  65. end
  66.  
  67. global CountOnly,NoNames,NamesOnly,NumberLines,Out,Invert,Escapes,
  68.       Pattern,PatternFile,Dump,Re_LeftmostShortest
  69.  
  70. procedure Options(arg)
  71.    local opt
  72.    opt := options(arg,"chilnsve:E:f:DS")
  73.    CountOnly := opt["c"]
  74.    NoNames := opt["h"]
  75.    if \opt["i"] then Re_Filter := map
  76.    NamesOnly := opt["l"]
  77.    NumberLines := opt["n"]
  78.    Out := if \opt["s"] then &null else &output
  79.    Invert := opt["v"]
  80.    Pattern := \opt["e" | "E"]
  81.    Escapes := opt["E"]
  82.    PatternFile := opt["f"]
  83.    Dump := opt["D"]
  84.    Re_LeftmostShortest := (\opt["S"],&null) | 1
  85.    return opt
  86. end
  87.  
  88. procedure GetPattern(arg)
  89.    local f,sep
  90.    if \PatternFile then {
  91.       f := open(PatternFile) |
  92.         stop("Can't open pattern file \"",PatternFile,"\"")
  93.       (/Pattern := "" & sep := "") | (sep := "|")
  94.       while Pattern ||:= sep || read(f) do sep := "|"
  95.       close(f)
  96.       }
  97.    /Pattern := get(arg)
  98.    if /Pattern then Usage(2)
  99.    return RePat(if \Escapes then istring(Pattern) else Pattern)
  100. end
  101.  
  102. procedure ScanFiles(arg,pattern)
  103.    local errors,totalCount,fn,f,header,lineNbr,count,line,fLine,status,
  104.          lineNbrTag
  105.    totalCount := 0
  106.    if *arg = 0 then arg := ["-"]
  107.    every fn := !arg do {
  108.       f := if fn == "-" then &input else open(fn) |
  109.             {write(&errout,"Can't open \"",fn,"\" -- skipped") ; errors := 2 ;
  110.         next}
  111.       header := if \NoNames | *arg = 1 then &null else fn || ":"
  112.       lineNbr := count := 0
  113.       while line := read(f) do {
  114.          lineNbr +:= 1
  115.          fLine := (\Re_Filter)(line) | line
  116.          status := ReFind(pattern,fLine) | &null
  117.      status := if \Invert then (\status,&null) | 1
  118.          if \status then {
  119.         count +:= 1
  120.         if count = 1 & \NamesOnly then {write(\Out,fn) ; next}
  121.         lineNbrTag := if \NumberLines then lineNbr || ":" else &null
  122.         if not \(CountOnly | NamesOnly) then
  123.           write(\Out,header,lineNbrTag,line)
  124.         }
  125.          }
  126.       close(f)
  127.       if \CountOnly then write(header,count)
  128.       totalCount +:= count
  129.       }
  130.    ## if \CountOnly & *arg > 1 then write(\Out,"** Total ** ",totalCount)
  131.    return \errors | if totalCount = 0 then 1 else 0
  132. end
  133.  
  134. #
  135. #  istring() -- Procedure to convert a string containing special escape
  136. #  constructs, of the same format as Icon source language character
  137. #  strings, to their true string representation.  Value returned is the
  138. #  string with special constructs converted to their respective
  139. #  characters.
  140. #
  141.  
  142. procedure istring(s)
  143.   local r,c
  144.   r := ""
  145.   s ? {
  146.     while r ||:= tab(upto('\\')) do {
  147.       move(1)
  148.       r ||:= case c := map(move(1)) of {
  149.     "b": "\b"       # backspace
  150.     "d": "\d"       # delete (rubout)
  151.     "e": "\e"       # escape (altmode)
  152.     "f": "\f"       # formfeed
  153.     "l": "\l"       # linefeed (newline)
  154.     "n": "\n"       # newline (linefeed)
  155.     "r": "\r"       # carriage return
  156.     "t": "\t"       # horizontal tab
  157.     "v": "\v"       # vertical tab
  158.     "x": istring_radix(16,2)# hexadecimal code
  159.     "^": char(ord(move(1)) % 32) | break # control code
  160.     default: {      # either octal code or non-escaped character
  161.       if any('01234567',c) then {   # if octal digit
  162.         move(-1)
  163.         istring_radix(8,3)
  164.       }
  165.       else c            # else non-escaped character
  166.     } | break
  167.       }
  168.     }
  169.     r ||:= tab(0)
  170.   }
  171.   return r
  172. end
  173.  
  174. procedure istring_radix(r,max)
  175.   local n,d,i,c
  176.   d := "0123456789abcdef"[1:r + 1]
  177.   n := 0
  178.   every 1 to max do {
  179.     c := move(1) | break
  180.     if not (i := find(map(c),d) - 1) then {
  181.       move(-1)
  182.       break
  183.     }
  184.     n := n * r + i
  185.   }
  186.   return char(n)
  187. end
  188.