home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
326.lha
/
ARPTools
/
src
/
Wc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-12-27
|
6KB
|
328 lines
/*
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 <ctype.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/arpbase.h>
#include <arpfunctions.h>
#include <proto/exec.h>
#include <proto/dos.h>
#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);
}