%%s 4/4/591 %%d D 1.2 20-Sep-82 17:05:26 dpm 2 1 %%c Modified fb.w`fb.r`printb so that the "-c" switch will work. The %%c test for (endstk == 0 & fb == ERR) was moved after the test for %%c (count == YES). %%s 0/0/0 %%d D 1.1 25-Mar-82 12:05:44 v1.1 1 0 %%c Version 1.1 is the Spring 1982 Distribution of the LBL/Hughes release %%c of the Software Tools Virtual Operating System software and documentation. %%T %%I 1 #-h- fbbuf 321 asc 25-mar-82 07:53:39 v1.1 (sw-tools v1.1) ## fbbuf - common block for 'fb' block buffer common /fbbuf/ fbbuf(MAXBUFLENGTH), endstk, fname(FILENAMESIZE), fb character fbbuf #buffer which holds lines integer endstk #pointer to end of stack; init=0 character fname #holds name of scratch file integer fb #file ID of scratch file; init=ERR #-h- fbcom 1309 asc 25-mar-82 07:53:41 v1.1 (sw-tools v1.1) ## /fbcom/ - common block for 'bf' tool # Put on a file called 'fbcom' # Used only by 'fb', but very similar to variables used in 'find' common /fbcom/ andpat, count, except, elevel, casind, pat(MAXPAT, NEXPR), atend, atbeg, seps(MAXPAT,2), nbrsep, skping, prting, mcount, seploc, bklth, lcount, locatd(NEXPR) integer andpat #flag for locating blocks which contain all args integer count #flag for counting occurrences only integer except #flag for locating blocks without indicated patterns integer elevel #number of patterns to locate integer casind #YES/NO if match is case-independent integer pat #patterns to locate integer atend #flag for indicating end of block reached integer atbeg #flag indicating beginning of block reached integer seps #block separator(s) (1=start,2=ending) integer nbrsep #number of separators (1 or 2) integer seploc #location of separator (BEFORE or AFTER block) integer mcount #count of number of matches integer skping #flag indicating lines should not be examined character locatd #flag indicating which patterns have been located integer bklth #max size of block to output # init = HUGE integer lcount #running line count of block #-h- fbtemp 97 asc 25-mar-82 07:53:43 v1.1 (sw-tools v1.1) common / fbtemp / tmpbuf(MAXLINE) character tmpbuf # temporary buffer used by checkl and bmatch %%D 2 #-h- fb.r 11293 asc 25-mar-82 07:53:49 v1.1 (sw-tools v1.1) %%E 2 %%I 2 #-h- fb.r 11290 asc 20-sep-82 17:01:46 dpm (dave martin) %%E 2 #-h- defns 497 asc 25-mar-82 07:52:37 v1.1 (sw-tools v1.1) define(NEXPR,10) # max number of expressions ifdef(LARGE_ADDRESS_SPACE) define(MAXBUFLENGTH,20000) # length of block buffer (characters) elsedef define(MAXBUFLENGTH,5000) #length of block buffer (characters) enddef define(BEFORE,1) #separator at beginning of block define(AFTER,0) #separator at end of block define(HUGE,30000) # just a large number define(mkuniq,scratf) define(USE_STRING,"usage: fb [-acix] [-ln] [-sexpr [-sexpr]] expr [expr] ...") #-h- main 344 asc 25-mar-82 07:52:39 v1.1 (sw-tools v1.1) DRIVER(fb) ## fb - find block of lines include fbcom call query(USE_STRING) call fbargs #set initial values; parse args call dobk (STDIN) #search blocks for patterns if (count == YES) #print final count { call putdec(mcount, 1) call putc('@n') } DRETURN end #-h- bmatch 378 asc 25-mar-82 07:52:41 v1.1 (sw-tools v1.1) ## bmatch - locate patterns which appear in line of block subroutine bmatch (line) character line(ARB) integer match include fbcom include fbtemp call strcpy(line, tmpbuf) if (casind == YES) call fold(tmpbuf) for (i=1; i<=elevel; i=i+1) if (match(tmpbuf, pat(1,i)) == YES) locatd(i) = YES #mark arg that was matched return end #-h- checkl 344 asc 25-mar-82 07:52:42 v1.1 (sw-tools v1.1) ## checkl - check line for block separator subroutine checkl (line) character line(ARB) integer match include fbcom include fbtemp call strcpy(line, tmpbuf) if (casind == YES) call fold(tmpbuf) atbeg = match(tmpbuf, seps(1,1)) if (nbrsep == 1) atend = atbeg else atend = match(tmpbuf, seps(1,2)) return end #-h- dobeg 390 asc 25-mar-82 07:52:44 v1.1 (sw-tools v1.1) ## dobeg - process beginning of block (fb tool) subroutine dobeg (line) character line(ARB) integer stackl include fbcom call initbk #clear stacks lcount = 0 if (nbrsep > 1 | seploc == BEFORE) { call bmatch(line) if (stackl(line) == ERR) call error ("Block buffer overflow") } skping = NO prting = NO return end #-h- dobk 1025 asc 25-mar-82 07:52:46 v1.1 (sw-tools v1.1) ## dobk - find patterns in block of text subroutine dobk (fd) integer getlin, remove integer fd, prt, first, junk character line(MAXLINE) include fbcom include fbbuf call initbk #clear stacks first = YES while(getlin(line, fd) != EOF) { call checkl (line) #check line for block separator #check if sep really at start of block if (first == YES & atend == YES & nbrsep == 1) seploc = BEFORE first = NO if (atend == YES) call doend(line) if (atbeg == YES) { call dobeg(line) next } if (skping == YES) next else call dolin (line) } #EOF reached if (skping == NO) call doend(line) if (fb != ERR) #make sure scratch file is removed { call close(fb) junk = remove(fname) fb = ERR } return end #-h- doend 1059 asc 25-mar-82 07:52:49 v1.1 (sw-tools v1.1) ## doend - process end of block (fb tool) subroutine doend (line) character line(ARB) integer stackl integer prt include fbcom if (prting == YES) { if ( (nbrsep > 1 | seploc == AFTER) & count == NO) call outlin(line) if (bklth != HUGE) #finish off rest of block for(lcount=lcount+1; lcount<=bklth; lcount=lcount+1) call putch('@n', STDOUT) } else if (skping == NO) { if (nbrsep > 1 | seploc == AFTER) { call bmatch (line) if (stackl(line) ==ERR) call error ("Block buffer overflow") } call tally (prt) if (prt == YES) { call printb if (bklth != HUGE) for (lcount=lcount+1; lcount<=bklth; lcount=lcount+1) call putch('@n',STDOUT) } } skping = YES prting = NO return end #-h- dolin 794 asc 25-mar-82 07:52:51 v1.1 (sw-tools v1.1) ## dolin - process line for 'fb' tool subroutine dolin (line) character line(ARB) integer prt integer stackl include fbcom if (skping == YES) return if (prting == YES) { if (count == NO) call outlin(line) } else #check line for match { call bmatch (line) if (stackl(line) == ERR) call error ("Block buffer overflow") call tally(prt) #block may definitely be printed if (prt == YES & except == NO) { call printb prting = YES } #block may definitely be skipped else if (prt == NO & except == YES) skping = YES } return end #-h- fbargs 2409 asc 25-mar-82 07:52:55 v1.1 (sw-tools v1.1) ## fbargs - parse arguments for 'fb' tool subroutine fbargs character arg(MAXLINE) integer getarg, itoc, getpat, status, index, ctoi integer i, j include fbbuf include fbcom string ilpat "illegal pattern: " string maxexp "max nbr expressions allowed: " string dsep "% *$" data except/NO/ data andpat/NO/ data count /NO/ data mcount /0/ data elevel/0/ data casind/NO/ data skping /NO/ data nbrsep /0/ data seploc /AFTER/ data endstk /0/ data fb /ERR/ data bklth /HUGE/ data lcount /0/ #loop thru args, picking up flags and patterns for (i=1; getarg(i, arg, MAXARG) != EOF; i=i+1) { if (arg(1) == '-' & (arg(2) == 's' | arg(2) == 'S')) { nbrsep = nbrsep + 1 if (nbrsep > 2) call error ("only start and ending separators allowed") if (casind == YES) call fold(arg) if (getpat(arg(3), seps(1, nbrsep)) == ERR) { call putlin(ilpat, ERROUT) call error (arg(3)) } } else if (arg(1) == '-') { call fold(arg) if (index(arg, 'a') > 0) andpat = YES if (index(arg, 'c') > 0) count = YES if (index(arg, 'i') > 0) casind = YES if (index(arg, 'x') > 0) except = YES j = index(arg, 'l') if (j > 0) #setting block length { j = j + 1 bklth = ctoi(arg, j) if (bklth <= 0) call error(USE_STRING) } } else if (elevel < NEXPR) { elevel = elevel + 1 if (casind == YES) call fold(arg) if (getpat(arg(1), pat(1,elevel)) == ERR) { call putlin(ilpat, ERROUT) call error (arg) } } else { call putlin(maxexp, ERROUT) status = itoc(NEXPR, arg, MAXARG) call error(arg) } } #check for errors if (elevel == 0) call error(USE_STRING) if (nbrsep == 0) #set default separator { if (getpat(dsep, seps(1,1)) == ERR) call error ("illegal default separator") nbrsep = 1 } if (nbrsep > 1) #skip till beginning of first block skping = YES return end #-h- initbk 312 asc 25-mar-82 07:52:58 v1.1 (sw-tools v1.1) ## initbk - initialize buffers for 'fb' tool subroutine initbk integer junk integer remove include fbcom include fbbuf for (i=1; i<=elevel; i=i+1) locatd(i) = NO endstk = 0 if (fb != ERR) { call close(fb) junk = remove(fname) fb = ERR } return end #-h- outlin 214 asc 25-mar-82 07:53:00 v1.1 (sw-tools v1.1) ## outlin - output line from block, if user wants to see it subroutine outlin(line) character line(ARB) include fbcom lcount = lcount + 1 if (lcount <= bklth) call putlin(line, STDOUT) return end %%D 2 #-h- printb 778 asc 25-mar-82 07:53:01 v1.1 (sw-tools v1.1) %%E 2 %%I 2 #-h- printb 778 asc 20-sep-82 16:43:19 dpm (dave martin) %%E 2 ## printb - print (or count) block of lines subroutine printb integer i, junk character c character getch integer open, remove include fbbuf include fbcom %%D 2 if (endstk == 0 & fb == ERR) #nothing on stack return %%E 2 if (count == YES) { mcount = mcount + 1 return } %%I 2 if (endstk == 0 & fb == ERR) #nothing on stack return %%E 2 if (fb != ERR) #copy scratch file to output { call close(fb) fb = open(fname, READ) #start at beginning if (fb == ERR) call error ("problems reopening scratch file") while(getch(c, fb) != EOF) call putch(c, STDOUT) call close(fb) junk = remove (fname) fb = ERR } for (i=1; i<=endstk; i=i+1) call putch(fbbuf(i), STDOUT) return end #-h- stackl 1069 asc 25-mar-82 07:53:04 v1.1 (sw-tools v1.1) ## stackl - put line on bottom of stack (if user wants to see it) integer function stackl (line) character line(MAXLINE) integer length, create integer len include fbbuf include fbcom string fbtemp "fbt" stackl = OK if (count == YES) #no need to stack if just counting return lcount = lcount + 1 if (lcount > bklth) #user doesn't want to see this much return len = length(line) if ( (len+endstk+1) > MAXBUFLENGTH) #store buffer on scratch file { if (fb == ERR) { call mkuniq(fbtemp, fname) fb = create(fname, WRITE) if (fb == ERR) { call remark ("problems opening scratch file") call cant (fname) } } for (i=1; i<=endstk; i=i+1) call putch(fbbuf(i), fb) call putlin(line, fb) endstk = 0 return } call scopy(line, 1, fbbuf, endstk+1) endstk = endstk + len return end #-h- tally 658 asc 25-mar-82 07:53:06 v1.1 (sw-tools v1.1) ## tally - tally results of block search subroutine tally (prt) integer prt #returned as YES if block should be printed; else NO include fbcom prt = andpat for (i=1; i<=elevel; i=i+1) { if (andpat == NO & locatd(i) == YES) { prt = YES break } else if (andpat == YES & locatd(i) == NO) { prt = NO break } } if (except == YES) #opposite for exceptions { if (prt == NO) prt = YES else prt = NO } return end #-h- fb.fmt 2942 asc 25-mar-82 07:53:58 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Fb (1) 28-May-80 search blocks of lines for text patterns .sy fb [-acix] [-ln] [-sexpr [-sexpr]] expr [expr] ... .ds "Fb" (find block) searches blocks or groups of lines in a file for text patterns. It is similar to 'find' except that if a pattern is found, the entire block of lines is copied to standard output, rather than simply the line in which the pattern occurred. Thus it is useful for searching mailing lists, bibliographies, and similar files where several lines are grouped together to form cohesive units. The search patterns may be any regular expression as described in the 'ed' and 'find' writeups. "Fb" assumes the blocks of lines are separated by an empty line or a line containing only blanks. When "fb" is called without any options, standard input is read and each line is checked to see if it matches any of the regular expressions given as arguments. If any matches are found, the entire block is printed on standard output. Other options include: .in +10 .ti -8 -a Only print the block if ALL the arguments are found within it .ti -8 -x Only print the block if none of the arguments are found within it .ti -8 -c Only print a COUNT of the number of blocks found which match/don't match the expressions .ti -8 -i Perform the pattern matches ignoring case. .ti -8 -sexpr Use 'expr' as the block separator (instead of a blank or empty line). "Expr" can be a regular expression just as the search arguments can. If two "-sexpr" arguments are given, the first one is considered to be the pattern which starts a block (e.g. -ssubroutine) and the second is considered the pattern which ends a block (e.g. -send). If the -i flag has been seen before the -s flags, then the start and end expressions will be case-independent. .ti -8 -ln prints only the first 'n' lines of the block; if the block contains less than 'n' lines, the block is padded out with blank lines. .in -10 .fi Care should be taken when using the characters % $ [ ] ! * @ and any shell characters in the text pattern. It is often necessary to enclose the entire substitution pattern in quotes. .fl A scratch file ("fbt") is used if the internal line buffer becomes full. .sa find .br ed For a complete description of regular expressions, see "Software Tools" pages 135-154. .di Error messages are given if: .br .in +3 a) One of the patterns given is illegal .br b) Too many separators are given (2 are allowed) .br c) The maximum number of expressions is exceeded (9 are allowed) .br d) There are problems opening the scratch file (when the block line buffer fills up). .in -3 If the following messages show up, something is dreadfully wrong: .in +3 a) "Illegal default separator" .br b) "Block buffer overflow" .in -3 .au Debbie Scherrer (Lawrence Berkeley Laboratory) .bu An expression may not start with a minus sign (-). Regular expressions cannot span line boundaries. %%E 1