/* Wc - Text statistics Original effort by Fabio Rossetti. Inspired by the wc program by Gary Brant found on <>< 179 and the WC utility found in the Lattice C 5.0 package. (c) 1989 by Fabio Rossetti To compile under Lattice C v5.0x use: lc -O -v -cus wc blink lib:cres.o wc.o to wc lib lib:a.lib lib:lc.lib sd nd */ #include #include #include #include #include #include #include #include #include #include #define NARGS 3 LONG argc; STRPTR argv[NARGS]; #define FILS argv[0] #define PRINT argv[1] #define CHECK argv[2] struct ArpBase *ArpBase=NULL; struct Process *Pr; /* file stuff */ #define BFSIZE 4096 BPTR fh=NULL; TEXT *Buf; /* flag to signal if only a file is found, affects output */ BOOL Single = TRUE; /* extended AnchorPath structure (full path needed) */ struct UAnchor { struct AnchorPath AP; TEXT Bf[255]; }; struct UAnchor *Anchor; struct DirectoryEntry *De,*FileList=NULL; /* shutdown routine */ VOID Cleanup(r1,r2) LONG r1,r2; { if (FileList) FreeDAList(FileList); if (Anchor) FreeAnchorChain((struct AnchorPath *)Anchor); if (fh) Close(fh); if (ArpBase) CloseLibrary((struct Library *)ArpBase); Pr->pr_Result2 = r2; exit(r1); } /* Conversion table for checksum */ TEXT *Ascii = "!@#$%^&*()_+1234567890-=qwertyuiop[]asdfghjkl;'`\\zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:\"~|ZXCVBNM<>?"; /* A Lattice Wc compatible way to assign a unique numeric value to an ASCII char */ Code(c) TEXT c; { REGISTER BYTE i=0; REGISTER TEXT *pos=Ascii; while (*pos != NULL) { if(*pos++ == c) return(i+1); else i++; } return(0); } /* perform statistics on the opened file Name-d */ VOID Wc(filhand,Name) BPTR filhand; TEXT *Name; { REGISTER TEXT c; BOOL inword=FALSE,inpword=FALSE; REGISTER ULONG i, nc=0, /* number of chars */ na=0, /* number of alpha chars */ asnum=0,/* 1st part of checksum, sum of printable chars */ sum=0; /* 2nd part of checksum, sum perf'd by Code() */ ULONG nl=0, /* number of lines */ nw=0, /* number of words of alpha chars */ np=0, /* number of words of printable chars */ count, awl; /* average word lenght */ while (count = Read(filhand,Buf,BFSIZE)) { /* CTRL C ? */ if (SetSignal(0,0) & SIGBREAKF_CTRL_C) { Puts("***Break"); Cleanup(RETURN_WARN,NULL); } for (i = 0; i < count; i++) { c = *(Buf+i); /* filter non-printable chars */ if (PRINT) if ( !isprint(c) && !isspace(c) ) continue; /* perform chexsum */ if (CHECK) if (isprint(c)) { ++asnum; if(!isspace(c)) sum+=Code(c); } ++nc; /* a line */ if (c == '\n') ++nl; if (isalpha(c)) ++na; /* count words e pwords */ if (isspace(c)) { inword = FALSE; inpword = FALSE; } else { if (inword == FALSE) { inword = TRUE; if (isalpha(c)) ++nw; } if (inpword == FALSE) { inpword = TRUE; if ((isprint(c))) ++np; } } } } /* calculate average word lenght */ if (!nw) awl = 0; else awl = ((na % nw) > (nw / 2)) ? ((na/nw)+1) : (na/nw); /* output results, table form if more than one file */ if (Single) { Printf(" Characters : %ld\n",nc); Printf("Alpha Characters : %ld\n",na); Printf(" Words : %ld\n",nw); Printf("Avr. Word Lenght : %ld\n",awl); Printf(" PWords : %ld\n",np); Printf(" Lines : %ld\n",nl); if(CHECK) Printf("\n Checksum : %ld %ld\n",asnum,sum); } else { if(CHECK) Printf("%7ld %7ld %7ld %7ld %7ld %7ld %7ld %7ld %s\n", nc,na,nw,awl,np,nl,asnum,sum,Name); else Printf("%7ld %7ld %7ld %7ld %7ld %7ld %s\n", nc,na,nw,awl,np,nl,Name); } } /* Trick to keep code down to size */ VOID MemCleanup() { } /* as above */ VOID _main(Line) STRPTR Line; { BOOL Result; TEXT **ArV; LONG i=0; Pr = (struct Process*)FindTask(NULL); if(!(ArpBase = (struct ArpBase*)OpenLibrary(ArpName,ArpVersion))) Cleanup(RETURN_FAIL,ERROR_INVALID_RESIDENT_LIBRARY); /* parse command line */ for (argc=0;argc < NARGS ;++argc) argv[argc] = (STRPTR) NULL; while(*Line > ' ') ++Line; if((argc = GADS(++Line, strlen(Line), "Usage: Wc [Pattern] [PRINT=P] [CHECK=C]", argv, "Files/...,PRINT=P/S,CHECK=C/S" )) < 0) { Puts(FILS); Cleanup(RETURN_WARN,NULL); } /* get buffer for file */ if (!(Buf = ArpAllocMem(BFSIZE,MEMF_CLEAR))) { Puts("Error: no memory"); Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE); } if (!(FILS)) { Wc(Input(),NULL); Cleanup(NULL,NULL); } /* Allocate space for anchorpath */ if ( Anchor = (struct UAnchor *)ArpAlloc( (ULONG)sizeof( *Anchor )) ) { Anchor->AP.ap_Length = 255; Anchor->AP.ap_BreakBits = SIGBREAKF_CTRL_C; /* stop if ^C */ } else { Puts("Error: no memory"); Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE); } ArV = (TEXT **) FILS; while (ArV[i] != NULL) { /* examine files specified by pattern */ Result = FindFirst(ArV[i],(struct AnchorPath *)Anchor); while ( Result == 0 ) { if (Anchor->AP.ap_Info.fib_DirEntryType < 0) { /* add filename to ordered DAList */ if ( !(De=AddDANode(Anchor->AP.ap_Buf, &FileList, 0L, 0L))) { Puts("Error: no memory"); Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE); } } Result = FindNext((struct AnchorPath*) Anchor ); } if (Result != ERROR_NO_MORE_ENTRIES) { switch(Result) { case ERROR_OBJECT_NOT_FOUND: Printf("Error:Can't find %s\n",ArV[i]); break; case ERROR_BREAK: Puts("***Break"); break; default: Puts("Error"); } Cleanup(RETURN_ERROR,Result); } i++; } De = FileList; if ((De->de_Next)) { Single = FALSE; if(CHECK){ Puts(" Chars Alpha Words A.W.L. PWords Lines Checksum FileName"); Puts("--------------------------------------------------------------------------"); } else { Puts(" Chars Alpha Words A.W.L. PWords Lines FileName"); Puts("----------------------------------------------------------"); } } while (De) { if (!(fh = Open(De->de_Name,MODE_OLDFILE))) { Puts(De->de_Name); Puts("Error:"); Pr->pr_Result2 = ERROR_OBJECT_NOT_FOUND; exit(RETURN_ERROR); } else { Wc(fh,BaseName(De->de_Name)); Close(fh); } De = De->de_Next; } fh = NULL; Cleanup(NULL,NULL); }