program WCLC !Word Count & Line Count on text files common /line/nQ,S byte S(200) integer*2 nQ integer*2 j,l byte file(15),ans,star data star/'*'/ integer*4 bc,wc,lc,blank,record,wrdcnt,sntcnt integer*4 word(0:20),sentnc(0:50) logical*1 nextl,period common /graphs/map byte map(80,17) call tthclr type 1000 1000 format('+',T20,'Caffin''s Word Count Utility') call ltpos(3,10) type 1005 1005 format('+','Please enter file name: ',$) accept 1010,nF,(file(i),i=1,nF) 1010 format(Q,14a1) file(nF+1)=0 open(unit=1,name=file,type='OLD') period=.false. bc=0 wc=0 lc=0 blank=0 record=0 wrdcnt=0 sntcnt=0 do 80 i=0,20 word(i)=0 80 continue do 85 i=0,50 sentnc(i)=0 85 continue do 95 i=1,80 do 90 j=1,15 map(i,j)=' ' 90 continue map(i,16)='-' map(i,17)=' ' 95 continue call ltpos(6,1) type 1040 1040 format('+','Stand by while I read the file in. Now at record ',$) 100 read(1,1050,err=500,end=500)nQ,(s(i),i=1,nQ) 1050 format(Q,200a1) record=record+1 !Count records bc=bc+nQ ! and bytes (exclude CR, LF) if((record.and.7).eq.0)then call ltpos(6,51) !Periodic update of counter type 1055,record ! on screen. Reassure user 1055 format('+',I6,$) ! we are still alive. endif if(nQ.eq.0)then blank=blank+1 !Count & ignore blank lines goto 100 elseif(nQ.gt.140)then nQ=140 !Limit lines to <=140 char endif nQold=nQ j=1 !Start at beginning of line s(nQ+1)="15 !Delimit line in storage s(nQ+2)="15 !Delimit line in storage lc=lc+1 !Count non-blank lines 110 call fndwrd(j) !Find start of next word if(j.gt.nQ)goto 120 !Check for EOL jst=j !Keep start of a new word call eatwrd(j,l,period) !Find end of word and length if(l.gt.0)then word(l)=word(l)+1 !Increment histogram wc=wc+1 !Count words wrdcnt=wrdcnt+1 !Count words in sentence endif if(period)then if(wrdcnt.gt.50)wrdcnt=50 !Check for gargantuan ... sentnc(wrdcnt)=sentnc(wrdcnt)+1 !Histogram of sentence length sntcnt=sntcnt+1 !Count sentences wrdcnt=0 !Zero counter endif if(j.le.nQold)goto 110 120 continue goto 100 500 call rctrlo !Clear any ^O call graph(word,20,1) map(14,1)='W' map(15,1)='o' map(16,1)='r' map(17,1)='d' map(18,1)='s' map(2,8)='-' call graph(sentnc,50,25) map(65,1)='S' map(66,1)='e' map(67,1)='n' map(68,1)='t' map(69,1)='e' map(70,1)='n' map(71,1)='c' map(72,1)='e' map(73,1)='s' map(25,8)='-' call tthclr type 1070,(file(i),i=1,nF) 1070 format('+',T20,'For file ',14A1) type 1080,bc,wc,sntcnt,lc,(lc/60),blank 1080 format( x,'The Byte count: ',I8,/ 1 x,'The Word count: ',I8, 2 10x, 'Sentence count :',I5,/ 3 x,'The Line count: ',I8, 4 10x, 'Columns of 60 lines:',I5,/ 5 x,'Blank lines : ',I8,/) type 1170,map 1170 format(x,80a1) call exit end subroutine fndwrd(j) integer*2 j !Pointer c Advances in a line S from character j until either it passes c nQ characters or it reaches a word-type character. c It returns j pointing to the word-type character or =nQ+1. common /line/nQ,s byte s(142) integer*2 nQ byte byts(2),byt integer*2 ints equivalence (byts(1),ints),(byt,byts(1)) data ints/0/ logical*1 stwrd(128) data stwrd/32*.false., !Control codes 1 16*.false., !SP to / 2 10*.true., !Numbers?? 3 7*.false., !: to @ 4 26*.true., !A to Z 5 6*.false., ![ to ` 7 26*.true., !a to z 8 5*.false./ !{ to DEL nextl=.false. do 100 i=j,nQ ij=i !Remember counter value byt=s(i) !Translate byte to integer if(stwrd(ints+1))goto 150 !Jump out on word-type char 100 continue ij=nQ+1 !Paranoia: ensure ij>nQ: EOL 150 j=ij return end subroutine eatwrd(j,l,period) integer*2 j,l !Pointer and word length logical*1 period !True if a period was found common /line/nQ,s byte s(142) integer*2 nQ byte byts(2),byt integer*2 ints equivalence (byts(1),ints),(byt,byts(1)) data ints/0/ logical*1 wrd(128) data wrd/32*.false., !Control codes 1 16*.false., !SP to / 2 10*.true., !Numbers?? 3 7*.false., !: to @ 4 26*.true., !A to Z 5 6*.false., ![ to ` 7 26*.true., !a to z 8 5*.false./ !{ to DEL logical*1 space(128) data space/10*.false., !NUL to HT 1 .true., ! LF 2 .false., ! VT 3 2*.true., ! FF, CR 4 18*.false., !SO to US 5 .true., ! SP 6 31*.false., ! ! to ? 7 32*.false., !@ to _ 8 32*.false./ !` to DEL period=.false. l=0 !Length counter do 100 i=j,nQ ij=i byt=s(i) if(wrd(ints+1))l=l+1 !Valid word char: count if(byt.eq.'.')period=.true. !Scan for '.' if(space(ints+1))goto 150 !Valid space: end of word 100 continue ij=nQ+1 !Oops: EOL nQ=nQ+1 !Tidy up s(nQ+1)="15 150 j=ij return end subroutine graph(v,l,c) integer*4 v(1) !Incoming vector integer l !Vector length integer c !Start column for graph integer*2 y(80) common /graphs/map byte map(80,17) max=0 do 100 i=1,l if(v(i).gt.max)max=v(i) !Find max 100 continue fmax=float(max) do 110 i=1,l y(i)=ifix(30.*float(v(i))/fmax) !Normalise to 30 units high 110 continue do 130 i=1,l do 120 j=1,15 j2=2*(16-j) if(y(i).ge.j2)then map(c+i+2,j)=':' elseif(y(i).eq.j2-1)then map(c+i+2,j)='.' else c map(c+i+2,j)='#' endif 120 continue 130 continue do 140 j=1,15 map(c+2,j)='|' 140 continue map(c,16)=' ' map(c+1,16)=' ' do 150 i=1,l map(c+2+i,17)=("060+mod(i,10)).and."377 150 continue return end