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 >
C/C++ Source or Header  |  1989-12-27  |  6KB  |  328 lines

  1. /*
  2.           Wc - Text statistics
  3.  
  4.           Original effort by Fabio Rossetti. Inspired by the wc program
  5.           by Gary Brant found on <>< 179 and the WC utility found
  6.           in the Lattice C 5.0 package.
  7.  
  8.       (c) 1989 by Fabio Rossetti
  9.  
  10.       To compile under Lattice C v5.0x use:
  11.  
  12.         lc -O -v -cus wc
  13.         blink lib:cres.o wc.o to wc lib lib:a.lib lib:lc.lib sd nd
  14.  
  15. */
  16.  
  17. #include <ctype.h>
  18. #include <exec/types.h>
  19. #include <exec/memory.h>
  20. #include <exec/libraries.h>
  21. #include <libraries/dos.h>
  22. #include <libraries/dosextens.h>
  23. #include <libraries/arpbase.h>
  24. #include <arpfunctions.h>
  25. #include <proto/exec.h>
  26. #include <proto/dos.h>        
  27.  
  28.  
  29. #define NARGS 3
  30.  
  31. LONG argc;
  32. STRPTR argv[NARGS];
  33.  
  34. #define FILS     argv[0]
  35. #define PRINT    argv[1]
  36. #define CHECK     argv[2]
  37.  
  38. struct ArpBase *ArpBase=NULL;
  39. struct Process *Pr;
  40.  
  41. /* file stuff */
  42. #define BFSIZE     4096
  43. BPTR fh=NULL;
  44. TEXT *Buf;
  45.  
  46. /* flag to signal if only a file is found, affects output */
  47. BOOL Single = TRUE;
  48.  
  49. /* extended AnchorPath structure (full path needed) */
  50. struct UAnchor {
  51.     struct AnchorPath AP;
  52.     TEXT Bf[255];
  53.         };
  54.  
  55. struct UAnchor *Anchor;
  56. struct DirectoryEntry *De,*FileList=NULL;
  57.  
  58. /* shutdown routine */
  59. VOID Cleanup(r1,r2)
  60. LONG r1,r2;
  61. {
  62.     if (FileList) FreeDAList(FileList);
  63.     if (Anchor) FreeAnchorChain((struct AnchorPath *)Anchor);
  64.     if (fh) Close(fh);
  65.     if (ArpBase) CloseLibrary((struct Library *)ArpBase);
  66.     Pr->pr_Result2 = r2;
  67.     exit(r1);
  68. }
  69.  
  70. /* Conversion table for checksum */
  71. TEXT *Ascii =
  72. "!@#$%^&*()_+1234567890-=qwertyuiop[]asdfghjkl;'`\\zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:\"~|ZXCVBNM<>?";
  73.  
  74. /* A Lattice Wc compatible way to assign a unique numeric value to an ASCII char */
  75. Code(c)
  76. TEXT c;
  77. {
  78.     REGISTER BYTE i=0;
  79.     REGISTER TEXT *pos=Ascii;
  80.     while (*pos != NULL) {
  81.         if(*pos++ == c) return(i+1);
  82.         else i++;
  83.         }
  84.    return(0);
  85. }
  86.  
  87. /* perform statistics on the opened file Name-d */
  88. VOID Wc(filhand,Name)
  89. BPTR filhand;
  90. TEXT *Name;
  91.  
  92. {
  93.  
  94.  
  95.     REGISTER TEXT c;
  96.     BOOL inword=FALSE,inpword=FALSE;
  97.     REGISTER ULONG    i,
  98.             nc=0,    /* number of chars */
  99.             na=0,    /* number of alpha chars */
  100.             asnum=0,/* 1st part of checksum, sum of printable chars */
  101.             sum=0;    /* 2nd part of checksum, sum perf'd by Code() */
  102.     ULONG         nl=0,    /* number of lines */
  103.             nw=0,    /* number of words of alpha chars */
  104.             np=0,    /* number of words of printable chars */
  105.             count,
  106.             awl;    /* average word lenght */
  107.  
  108.  
  109.  
  110.     while (count = Read(filhand,Buf,BFSIZE)) {
  111.  
  112.     /* CTRL C ? */
  113.     if (SetSignal(0,0) & SIGBREAKF_CTRL_C) {
  114.         Puts("***Break");
  115.         Cleanup(RETURN_WARN,NULL);
  116.         }
  117.  
  118.         for (i = 0; i < count; i++) {
  119.         
  120.         c = *(Buf+i);
  121.  
  122.         /* filter non-printable chars */
  123.         if (PRINT)
  124.             if ( !isprint(c) && !isspace(c) ) continue;
  125.  
  126.         /* perform chexsum */
  127.         if (CHECK)
  128.             if (isprint(c)) {
  129.                 ++asnum;
  130.                 if(!isspace(c)) sum+=Code(c);
  131.                 }    
  132.         ++nc;    
  133.  
  134.         /* a line */
  135.         if (c == '\n') ++nl;
  136.  
  137.         if (isalpha(c)) ++na;
  138.  
  139.         /* count words e pwords */
  140.         if (isspace(c))
  141.         {
  142.         inword = FALSE;
  143.         inpword = FALSE;
  144.         }
  145.  
  146.         else {
  147.          if (inword == FALSE) 
  148.             {
  149.                 inword = TRUE;
  150.                 if (isalpha(c)) ++nw;
  151.             }
  152.          if (inpword == FALSE) 
  153.             {
  154.                 inpword = TRUE;
  155.                 if ((isprint(c))) ++np;
  156.             }
  157.         }
  158.         }
  159.     }
  160.  
  161.     /* calculate average word lenght */
  162.     if (!nw) awl = 0;
  163.     else awl = ((na % nw) > (nw / 2)) ? ((na/nw)+1) : (na/nw);
  164.  
  165.     /* output results, table form if more than one file */
  166.     if (Single) {
  167.     Printf("      Characters : %ld\n",nc);
  168.     Printf("Alpha Characters : %ld\n",na);
  169.     Printf("           Words : %ld\n",nw);
  170.     Printf("Avr. Word Lenght : %ld\n",awl);
  171.     Printf("          PWords : %ld\n",np);
  172.     Printf("           Lines : %ld\n",nl);
  173.     if(CHECK) Printf("\n        Checksum : %ld %ld\n",asnum,sum);    
  174.     }
  175.     else
  176.     {
  177.     if(CHECK) Printf("%7ld %7ld %7ld %7ld %7ld %7ld %7ld %7ld %s\n",
  178.             nc,na,nw,awl,np,nl,asnum,sum,Name);
  179.     else Printf("%7ld %7ld %7ld %7ld %7ld %7ld %s\n",
  180.             nc,na,nw,awl,np,nl,Name);
  181.     }
  182. }
  183.  
  184.  
  185. /* Trick to keep code down to size */
  186. VOID MemCleanup()
  187. {
  188. }
  189. /* as above */
  190.     
  191. VOID _main(Line)
  192. STRPTR Line;
  193.  
  194. {
  195.  
  196.  
  197.     BOOL Result;
  198.     TEXT **ArV;
  199.     LONG i=0;
  200.  
  201.     Pr = (struct Process*)FindTask(NULL);
  202.     
  203.     if(!(ArpBase = (struct ArpBase*)OpenLibrary(ArpName,ArpVersion)))
  204.             Cleanup(RETURN_FAIL,ERROR_INVALID_RESIDENT_LIBRARY);
  205.     
  206.     /* parse command line */
  207.     for (argc=0;argc < NARGS ;++argc)
  208.         argv[argc] = (STRPTR) NULL;
  209.  
  210.     while(*Line > ' ')
  211.         ++Line;
  212.  
  213.     if((argc = GADS(++Line,
  214.         strlen(Line),
  215.         "Usage: Wc [Pattern] [PRINT=P] [CHECK=C]",
  216.         argv,
  217.         "Files/...,PRINT=P/S,CHECK=C/S" )) < 0)
  218.             {
  219.             Puts(FILS);
  220.             Cleanup(RETURN_WARN,NULL);
  221.             }
  222.  
  223.  
  224.     /* get buffer for file */
  225.     if (!(Buf = ArpAllocMem(BFSIZE,MEMF_CLEAR))) {
  226.                 Puts("Error: no memory");
  227.                 Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE);
  228.                 }
  229.     if (!(FILS)) {
  230.             Wc(Input(),NULL);
  231.             Cleanup(NULL,NULL);
  232.             }
  233.  
  234.  
  235.  
  236.     /* Allocate space for anchorpath */     
  237.     if ( Anchor = (struct UAnchor *)ArpAlloc( (ULONG)sizeof( *Anchor )) )
  238.     {
  239.         Anchor->AP.ap_Length = 255; 
  240.         Anchor->AP.ap_BreakBits = SIGBREAKF_CTRL_C; /* stop if ^C */
  241.     }
  242.     else
  243.     {
  244.         Puts("Error: no memory");
  245.         Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE);
  246.     }
  247.     ArV = (TEXT **) FILS;
  248.  
  249.     while (ArV[i] != NULL) {
  250.  
  251.     /* examine files specified by pattern */ 
  252.     Result = FindFirst(ArV[i],(struct AnchorPath *)Anchor);
  253.  
  254.     while ( Result == 0 )
  255.     {
  256.         if (Anchor->AP.ap_Info.fib_DirEntryType < 0) {
  257.  
  258.         /* add filename to ordered DAList */ 
  259.         if ( !(De=AddDANode(Anchor->AP.ap_Buf,
  260.                      &FileList, 0L, 0L)))
  261.             {
  262.             Puts("Error: no memory");
  263.             Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE);
  264.             }
  265.         }
  266.  
  267.         Result = FindNext((struct AnchorPath*) Anchor );
  268.     }
  269.     if (Result != ERROR_NO_MORE_ENTRIES) {
  270.         switch(Result)
  271.         {
  272.         case ERROR_OBJECT_NOT_FOUND:
  273.         Printf("Error:Can't find %s\n",ArV[i]);
  274.         break;
  275.  
  276.         case ERROR_BREAK:
  277.         Puts("***Break");
  278.         break;
  279.  
  280.         default:
  281.         Puts("Error");
  282.         }
  283.         Cleanup(RETURN_ERROR,Result);
  284.  
  285.     }        
  286.  
  287.     i++;
  288.         }
  289.  
  290.         
  291.  
  292.     De = FileList;
  293.  
  294.     if ((De->de_Next)) {
  295.     Single = FALSE;
  296.     if(CHECK){
  297.     Puts("  Chars   Alpha   Words  A.W.L.  PWords   Lines     Checksum    FileName");
  298.     Puts("--------------------------------------------------------------------------");
  299.     }
  300.     else {
  301.     Puts("  Chars   Alpha   Words  A.W.L.  PWords   Lines FileName");
  302.     Puts("----------------------------------------------------------");
  303.         }
  304.     }
  305.     while (De) {
  306.  
  307.     if (!(fh = Open(De->de_Name,MODE_OLDFILE)))
  308.         {
  309.         Puts(De->de_Name);
  310.         Puts("Error:");
  311.         Pr->pr_Result2 = ERROR_OBJECT_NOT_FOUND;
  312.         exit(RETURN_ERROR);
  313.         }
  314.     else
  315.         {
  316.         Wc(fh,BaseName(De->de_Name));
  317.         Close(fh);
  318.         }
  319.  
  320.     De = De->de_Next;
  321.  
  322.     }
  323.             
  324.     fh = NULL;
  325.     Cleanup(NULL,NULL);
  326.  
  327. }
  328.