home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cset21v1.zip / IBMCPP / WKFRAME / GREP / GREP.C next >
Text File  |  1993-02-28  |  23KB  |  657 lines

  1. /*+--------------------------------------------------------------------------+*/
  2. /*|                                                                          |*/
  3. /*| PROGRAM NAME: GREP                                                       |*/
  4. /*| -------------                                                            |*/
  5. /*|  A Simple OS/2 GREP program                                              |*/
  6. /*|                                                                          |*/
  7. /*| COPYRIGHT:                                                               |*/
  8. /*| ----------                                                               |*/
  9. /*|  Copyright (C) International Business Machines Corp., 1991,1992,1993.    |*/
  10. /*|                                                                          |*/
  11. /*| DISCLAIMER OF WARRANTIES:                                                |*/
  12. /*| -------------------------                                                |*/
  13. /*| The following [enclosed] code is sample code created by IBM              |*/
  14. /*| Corporation.  This sample code is not part of any standard IBM product   |*/
  15. /*| and is provided to you solely for the purpose of assisting you in the    |*/
  16. /*| development of your applications.  The code is provided "AS IS",         |*/
  17. /*| without warranty of any kind.  IBM shall not be liable for any damages   |*/
  18. /*| arising out of your use of the sample code, even if they have been       |*/
  19. /*| advised of the possibility of such damages.                              |*/
  20. /*|                                                                          |*/
  21. /*| REVISION LEVEL: 1.0                                                      |*/
  22. /*| ---------------                                                          |*/
  23. /*|                                                                          |*/
  24. /*| WHAT THIS PROGRAM DOES:                                                  |*/
  25. /*| -----------------------                                                  |*/
  26. /*|  This program is a simple grep with limited regular expression           |*/
  27. /*|  support.  Type  Grep  by itself for more help.                          |*/
  28. /*|                                                                          |*/
  29. /*| WHAT THIS PROGRAM DEMONSTRATES:                                          |*/
  30. /*| -------------------------------                                          |*/
  31. /*|  This program demonstrates how various C constructs are used;            |*/
  32. /*|  it demonstrates how to do subdirectory searching through the  help      |*/
  33. /*|  of various API calls.                                                   |*/
  34. /*|                                                                          |*/
  35. /*|                                                                          |*/
  36. /*|  REQUIRED FILES:                                                         |*/
  37. /*|  ---------------                                                         |*/
  38. /*|                                                                          |*/
  39. /*|    GREP.C         - Source code                                          |*/
  40. /*|    GREP.H         - Common definitions                                   |*/
  41. /*|    GREP.MAK       - Make file for this program                           |*/
  42. /*|    HELP.C         - Help procedures                                      |*/
  43. /*|                                                                          |*/
  44. /*|    OS2.H          - APIs include file                                    |*/
  45. /*|    STDLIB.H       - Standard library function declarations               |*/
  46. /*|    STRING.H       - String handling function declarations                |*/
  47. /*|    STDIO.H        - Handling IO                                          |*/
  48. /*|    CTYPE.H        - For mapping different casing                         |*/
  49. /*|                                                                          |*/
  50. /*|  REQUIRED LIBRARIES:                                                     |*/
  51. /*|  -------------------                                                     |*/
  52. /*|                                                                          |*/
  53. /*|    OS2386.LIB     - Presentation Manager/OS2 library                     |*/
  54. /*|    DDE4SBS.LIB    - C Set++ Standard Library                             |*/
  55. /*|                                                                          |*/
  56. /*|  REQUIRED PROGRAMS:                                                      |*/
  57. /*|  ------------------                                                      |*/
  58. /*|                                                                          |*/
  59. /*|    IBM C Set++ Compiler                                                  |*/
  60. /*|    IBM Linker                                                            |*/
  61. /*|                                                                          |*/
  62. /*|                                                                          |*/
  63. /*+--------------------------------------------------------------------------+*/
  64.  
  65.  
  66. #include <string.h>
  67. #include <ctype.h>
  68. #include <stdio.h>
  69. #include <stdlib.h>
  70. #include "grep.h"
  71.  
  72. #ifndef OS2_INCLUDED
  73.    #define OS2_INCLUDED
  74.    #define  INCL_DOS
  75.    #define  INCL_DOSERRORS
  76.    #include <os2.h>
  77. #endif
  78.  
  79. static  FILEFINDBUF3  findBuffer  ;
  80. static  FILE *inputFile ;
  81. static  char inputLine[MAX_LINE_LENGTH] ;
  82. static  char origLine[MAX_LINE_LENGTH]  ;
  83. static  int  inputLineLength            ;
  84. static  int  dummyVal                   ;
  85. static  int  printFileName              ;
  86. static  char *searchPattern = NULL      ;
  87. static  int fileCount, lineCount        ;
  88. static  int contextCount                ;
  89. static  char *theLine                   ;
  90. static  char *tmpLine                   ;
  91. static  char fileMask[255]              ;
  92. static  char searchPath[260]            ;
  93.  
  94.    /*********************/
  95.    /* Options variables */
  96.    /*********************/
  97.  
  98. static  int helpType            ;
  99. static  int noLogo      = 0     ;
  100. static  int caseFlag    = 0     ;
  101. static  int pauseFlag   = 0     ;
  102. static  int countFlag   = 0     ;
  103. static  int lineFlag    = 0     ;
  104. static  int contextFlag = 0     ;
  105. static  int absFlag     = 0     ;
  106. static  int dirFlag     = 0     ;
  107. static  int notFlag     = 0     ;
  108. static  int nameFlag    = 0     ;
  109. static  int pauseLineCount  = 0     ;
  110.  
  111.  
  112. /*****************************************************************/
  113. /* The following declarations support simple regular expressions */
  114. /*****************************************************************/
  115.  
  116. char *regExprKeyChar  = "*?" ;
  117.  
  118. typedef struct  structName
  119.    {
  120.    char * str   ;                /* Piece of string to search for */
  121.    int  strType ;
  122.    struct  structName * next ;
  123.    } subStringList ;
  124.  
  125. subStringList * listHead = NULL ;
  126. subStringList * curPtr   = NULL ;
  127. subStringList * prevPtr   = NULL ;
  128. int prevStrType , pieceLength        ;
  129.  
  130. char * tmpPtr   ;
  131. int foundFlag   ;
  132.  
  133. /*****************************/
  134. /*   Function Prototypes     */
  135. /*****************************/
  136.  
  137. void  processFile(char *);
  138. int   forAllMatch(char * );
  139. void  grepHelp(int );
  140.  
  141.                   /*********************/
  142.                   /*   Main Program    */
  143.                   /*********************/
  144.  
  145. int main (int argc, char **argv)
  146.    {
  147.    if ( argc == 1)
  148.       {
  149.       grepHelp(LINE_HELP) ;
  150.       exit (0) ;
  151.       }
  152.     argv++;
  153.     argc--;
  154.  
  155.     /*******************/
  156.     /* Process options */
  157.     /*******************/
  158.  
  159.     while ( argc > 0 && (**argv == '-' ||  **argv == '/' )  )
  160.        {
  161.        (*argv)++ ;
  162.        while (**argv != '\0')
  163.            {
  164.            switch (**argv)
  165.               {
  166.               case  'q':
  167.                  noLogo = 1 ;
  168.                  break ;
  169.  
  170.               case  'y':
  171.                  caseFlag    = 1 ;
  172.                  break ;
  173.  
  174.               case  's':
  175.                  dirFlag    = 1 ;
  176.                  break ;
  177.  
  178.               case  'n':
  179.                  nameFlag   = 1 ;
  180.                  break ;
  181.  
  182.               case  'p':
  183.                  pauseFlag = 1 ;
  184.                  break ;
  185.  
  186.               case  'l':
  187.                  lineFlag = 1 ;
  188.                  break ;
  189.  
  190.               case  'a':
  191.                  absFlag = 1 ;
  192.                  break ;
  193.  
  194.               case  'c':
  195.                  countFlag = 1 ;
  196.                  break ;
  197.  
  198.               case  'v':
  199.                  notFlag = 1 ;
  200.                  break ;
  201.  
  202.               case  'C':
  203.                  contextFlag = 1 ;
  204.                  (*argv)++;
  205.                  if ( ! isdigit(**argv) )
  206.                     printf("'-C' option expected integer, default of 3 is assumed.\n");
  207.                  else
  208.                     {
  209.                     contextCount = **argv ;
  210.                     (*argv)++;
  211.                     }
  212.                  break ;
  213.  
  214.               case  'h':
  215.                  grepHelp(FULL_HELP);
  216.                  exit(0);
  217.  
  218.               case  'z':
  219.                  grepHelp(CMDS_HELP);
  220.                  exit(0);
  221.  
  222.               default:
  223.                  printf("Grep: Unrecognized flag '%c' ignored.\n\n",**argv);
  224.                  break;
  225.               }
  226.            (*argv)++;
  227.            }
  228.        argv++ ;
  229.        argc-- ;
  230.        }
  231.  
  232.      if (argc == 0)
  233.         {
  234.         printf("grep: incorrect number of parameters\n");
  235.         grepHelp(LINE_HELP);
  236.         exit(255) ;
  237.         }
  238.  
  239.     /******************************/
  240.     /* Process the search pattern */
  241.     /******************************/
  242.  
  243.     searchPattern = *argv ;
  244.     argv++ ;
  245.     argc-- ;
  246.  
  247.     if ( ! noLogo )
  248.        {
  249.        printf("IBM C Set++ Grep Utility\n") ;
  250.        printf("Copyright (C) International Business Machines Corp., 1991,1992,1993.\n\n");
  251.        }
  252.  
  253.     if ( ! argc)
  254.        {
  255.        printf("Grep: You must specify at least one file name!\n");
  256.        exit (255) ;
  257.        }
  258.  
  259.     printf("Searching for \"%s\"\n",searchPattern);
  260.  
  261.     if ( ! caseFlag )
  262.        (void)strupr(searchPattern) ;
  263.  
  264.     /***********************************************************/
  265.     /* Below, we are building a linked-list of search patterns.*/
  266.     /* Each block is composed of the longest substring before  */
  267.     /* the appearance of any Special Chars (ie ? and * ).      */
  268.     /* There are two types of blocks, one type is the  one     */
  269.     /* mentioned above, the other type is a block containing   */
  270.     /* information on how many '?'s we have to match.          */
  271.     /***********************************************************/
  272.  
  273.     if (absFlag)       /* Interpret the search string as absolute. */
  274.        {
  275.        if ((listHead = (subStringList *)malloc(sizeof(subStringList))) == NULL)
  276.           {
  277.           printf("grep(1): Unable to get memory!\n");
  278.           exit(255);
  279.           }
  280.        listHead->str = searchPattern ;
  281.        listHead->strType  = REGULAR_TYPE ;
  282.        listHead->next = NULL ;
  283.        prevPtr = NULL      ;
  284.        }
  285.     else
  286.        /* Parsing of the expression line. */
  287.        {
  288.        if ((listHead = (subStringList *)malloc(sizeof(subStringList))) == NULL)
  289.           {
  290.           printf("grep(2): Unable to get memory! \n");
  291.           exit(255);
  292.           }
  293.  
  294.        curPtr = listHead   ;
  295.        curPtr->strType = 0 ;
  296.        curPtr->str = NULL  ;
  297.        curPtr->next = NULL ;
  298.        prevPtr = NULL      ;
  299.  
  300.        tmpPtr = searchPattern  ;
  301.  
  302.        while (*tmpPtr != '\0')
  303.           {
  304.           pieceLength = strcspn(tmpPtr,regExprKeyChar) ;
  305.  
  306.           if (! pieceLength )  /* Found '*' or '?' */
  307.              {
  308.              if (*tmpPtr == '*' )
  309.                 ++tmpPtr ;
  310.              else
  311.                 {
  312.                 curPtr->str = NULL ;
  313.                 curPtr->strType = 1;
  314.                 ++tmpPtr ;
  315.                 while (*tmpPtr == '?')
  316.                    {
  317.                    ++tmpPtr ;
  318.                    curPtr->strType += 1;
  319.                    }
  320.                 if ((curPtr->next = (subStringList *)malloc(sizeof(subStringList))) == NULL)
  321.                    {
  322.                    printf("grep(3): Unable to get memory!\n");
  323.                    exit(255);
  324.                    }
  325.                 prevPtr = curPtr      ;
  326.                 curPtr = curPtr->next ;
  327.                 curPtr->next = NULL   ;
  328.  
  329.                 }
  330.              }
  331.           else
  332.              {
  333.              if ((curPtr->str = (char *)malloc(pieceLength+1)) == NULL)
  334.                 {
  335.                 printf("grep(4): Unable to get memory!\n");
  336.                 exit(255);
  337.                 }
  338.              memcpy(curPtr->str,tmpPtr,pieceLength) ;
  339.              *(curPtr->str+pieceLength) = '\0'      ;
  340.              curPtr->strType = REGULAR_TYPE ;
  341.              tmpPtr +=  pieceLength         ;
  342.              if ((curPtr->next = (subStringList *)malloc(sizeof(subStringList))) == NULL)
  343.                 {
  344.                 printf("grep(5): Unable to get memory!\n");
  345.                 exit(255);
  346.                 }
  347.              prevPtr = curPtr      ;
  348.              curPtr = curPtr->next ;
  349.              curPtr->next = NULL   ;
  350.              }
  351.           }
  352.        }
  353.  
  354.  
  355.    if (prevPtr == NULL && absFlag != 1)
  356.       {
  357.       printf("grep: You have specified an invalid pattern!\n");
  358.       exit(255) ;
  359.       }
  360.  
  361.    if (prevPtr != NULL)
  362.       prevPtr->next = NULL ;  /* Throw away the extra block. */
  363.                               /* We always allocate one more */
  364.                               /* block on the list.          */
  365.  
  366.     /* Must do a subdirectory search */
  367.  
  368.     fileCount = 0 ;
  369.  
  370.     while(argc--)
  371.        {
  372.        if ( dirFlag ||  strchr(*argv,'\\') || strchr(*argv,':'))
  373.           {
  374.           dirFlag = 1;
  375.           tmpPtr = (char *)(*argv + (strlen(*argv) - 1)) ;
  376.           while ( *tmpPtr != '\\' && *tmpPtr != ':' && tmpPtr != *argv )
  377.              --tmpPtr;
  378.  
  379.           if ( tmpPtr == *argv)
  380.              {
  381.              strcpy(searchPath,".");
  382.              strcpy(fileMask, *argv);
  383.              }
  384.           else
  385.              {
  386.              if ( *tmpPtr == '\\')
  387.                 {
  388.                 *tmpPtr++ = '\0';
  389.                 strcpy(fileMask, tmpPtr) ;
  390.                 strcpy(searchPath, *argv);
  391.                 }
  392.              else     /* The case when we have ':' */
  393.                 {
  394.                 tmpPtr++ ;
  395.                 strcpy(fileMask, tmpPtr) ;
  396.                 *tmpPtr = '\0';
  397.                 strcpy(searchPath, *argv);
  398.                 }
  399.              }
  400.           }
  401.        else
  402.           {
  403.           strcpy(searchPath,".");
  404.           strcpy(fileMask, *argv);
  405.           }
  406.        forAllMatch(searchPath);
  407.        argv++ ;
  408.        }
  409.     return 0;
  410.     }
  411.  
  412.                 /****************************************/
  413.                 /*           forAllMatch                */
  414.                 /*                                      */
  415.                 /* Go through each file that match the  */
  416.                 /* file mask.                           */
  417.                 /*                                      */
  418.                 /* Do subdirectory search if requested. */
  419.                 /*                                      */
  420.                 /****************************************/
  421.  
  422.  
  423. int forAllMatch(char * path)
  424.    {
  425.    HDIR         findHandle  = 0xFFFFFFFF ;  /* Let OS/2 get us the handle */
  426.    int          findCount   = 1 ;
  427.    USHORT       rc ;
  428.    char         newPath[256];
  429.  
  430.    /*  Recursively process all subdirectory  */
  431.  
  432.    if (  path[strlen(path)-1] == ':')
  433.       strcat (path,"*.*");
  434.    else
  435.       strcat (path,"\\*.*");
  436.  
  437.    if (dirFlag)  /* Subdirectory search requested */
  438.       {
  439.       rc = DosFindFirst(path        ,
  440.                         &findHandle ,
  441.                         FILE_DIRECTORY  ,
  442.                         &findBuffer ,
  443.                         (ULONG)sizeof(findBuffer) ,
  444.                         (PULONG)&findCount ,
  445.                         (ULONG)0x0001);
  446.  
  447.       if (rc)
  448.          return rc;
  449.  
  450.       while (!rc)
  451.          {
  452.          if (strcmp(findBuffer.achName,".") && strcmp(findBuffer.achName,".."))
  453.             {
  454.             if (findBuffer.attrFile  == FILE_DIRECTORY )
  455.                {
  456.                strcpy(newPath,path) ;
  457.                newPath[strlen(path)-3] = '\0';
  458.                strcat(newPath,findBuffer.achName) ;
  459.                forAllMatch(newPath)  ;
  460.                }
  461.             }
  462.          rc = DosFindNext(findHandle,
  463.                           &findBuffer,
  464.                           sizeof(findBuffer),
  465.                           (PULONG) &findCount);
  466.          }
  467.       }
  468.  
  469.    /* When we get here, we have in path, the path to the directory we are  */
  470.    /* going to work with.                                                  */
  471.    /* Process all normal files that match the fileMask in the current directory */
  472.  
  473.    findHandle  = 0xFFFFFFFF;
  474.  
  475.    strcpy(newPath,path) ;
  476.  
  477.    newPath[strlen(path)-3] = '\0';
  478.  
  479.    strcat(newPath,fileMask);
  480.  
  481.    findCount = 1 ;
  482.  
  483.    rc = DosFindFirst(newPath,
  484.                      &findHandle,
  485.                      (ULONG)0L,
  486.                      &findBuffer,
  487.                      (ULONG)sizeof(findBuffer),
  488.                      (PULONG)&findCount,
  489.                      (ULONG)0x0001);
  490.  
  491.    path[strlen(path)-3] = '\0';
  492.  
  493.    while (!rc)    /* Process each file that matches the mask */
  494.       {
  495.       strcpy(newPath,path) ;
  496.       strcat(newPath,findBuffer.achName) ;
  497.       processFile(newPath) ;
  498.       rc = DosFindNext(findHandle,
  499.                        &findBuffer,
  500.                        sizeof(findBuffer),
  501.                        (PULONG)&findCount);
  502.       }
  503.    return 0 ;
  504.    }
  505.  
  506.                 /****************************************/
  507.                 /*           processFIle                */
  508.                 /*                                      */
  509.                 /*  fileName contains the name and path */
  510.                 /*  to the file that we will do a       */
  511.                 /*  search for the given pattern.       */
  512.                 /*                                      */
  513.                 /****************************************/
  514.  
  515.  
  516. void  processFile(char * fileName)
  517.    {
  518.    fileCount++;
  519.    printFileName = 0 ;    /* Not yet print file Name */
  520.    if ( (inputFile = fopen(fileName,"r") ) == NULL )
  521.       printf("Grep: Unable to open %s.\n", fileName) ;
  522.    else
  523.       {
  524.       lineCount = 0 ;
  525.       while  (fgets(inputLine,MAX_LINE_LENGTH,inputFile) != NULL )
  526.          {
  527.          strcpy(origLine,inputLine) ;
  528.  
  529.          if (! caseFlag)
  530.             (void)strupr(inputLine) ;
  531.  
  532.          inputLine[strlen(inputLine)-1] = '\0' ;
  533.          ++lineCount;
  534.          foundFlag = 0 ;
  535.          curPtr   = listHead ;
  536.          theLine  = inputLine ;
  537.          prevStrType = 0 ;
  538.  
  539.          /*******************************************/
  540.          /* The following code walk the linked-list */
  541.          /* of pieces of the string.                */
  542.          /* if strType is 0 : we match 'str' as-is, */
  543.          /* else strType = the number of ?'s in the */
  544.          /* regular expression.                     */
  545.          /*******************************************/
  546.  
  547.          while( !foundFlag && curPtr )
  548.             {
  549.             if (curPtr->strType == 0)   /* Match String as-is */
  550.                {
  551.                if ( (tmpLine = strstr(theLine,curPtr->str)) == NULL)
  552.                   /* This line does not have the pattern we wanted */
  553.                   curPtr = NULL ;
  554.                else
  555.                   {
  556.                   if (prevStrType != 0 && tmpLine != theLine)
  557.                      curPtr = NULL ;
  558.                   else
  559.                      {
  560.                      prevStrType = 0 ;
  561.                      theLine = tmpLine + strlen(curPtr->str) ;
  562.                      curPtr = curPtr->next ;
  563.                      if ( !curPtr )
  564.                         foundFlag = 1 ;
  565.                      }
  566.                   }
  567.                }
  568.             else  /* We must skip over strType # of ?'s  */
  569.                {
  570.                if ( strlen(theLine)  <  curPtr->strType)
  571.                   curPtr = NULL ;
  572.                else
  573.                   {
  574.                   prevStrType =  curPtr->strType    ;
  575.                   theLine +=  curPtr->strType ;
  576.                   curPtr = curPtr->next ;
  577.                   if ( !curPtr )
  578.                      foundFlag = 1 ;
  579.                   }
  580.                }
  581.             } /* end while */
  582.  
  583.          if ( foundFlag && !notFlag )
  584.             {
  585.             if (nameFlag)
  586.                {
  587.                if (!printFileName)
  588.                   {
  589.                   printFileName = 1 ;
  590.                   printf("%s\n",fileName);
  591.                   }
  592.                }
  593.             else
  594.                {
  595.                if (!printFileName)
  596.                   {
  597.                   printFileName = 1 ;
  598.                   printf("\n--------------------------------------------------------------------------------\n");
  599.                   printf("Processing file %s: \n",fileName);
  600.                   }
  601.                if (lineFlag)
  602.                   printf("%d: %s",lineCount , origLine) ;
  603.                else
  604.                   printf("%s", origLine) ;
  605.                if (pauseFlag)
  606.                   {
  607.                   ++pauseLineCount ;
  608.                   if (pauseLineCount > MAX_LINE_PER_SCREEN)
  609.                      {
  610.                      pauseLineCount = 1 ;
  611.                      printf("Press a key to continue...\n");
  612.                      dummyVal = getchar() ;
  613.                      }
  614.                   }
  615.                }
  616.             }
  617.          else if ( !foundFlag && notFlag )
  618.             {
  619.             if (nameFlag)
  620.                {
  621.                if (!printFileName)
  622.                   {
  623.                   printFileName = 1 ;
  624.                   printf("%s\n",fileName);
  625.                   }
  626.                }
  627.             else
  628.                {
  629.                if (!printFileName)
  630.                   {
  631.                   printFileName = 1 ;
  632.                   printf("\n--------------------------------------------------------------------------------\n");
  633.                   printf("Processing file %s: \n",fileName);
  634.                   }
  635.                if (lineFlag)
  636.                   printf("%d: %s",lineCount , origLine) ;
  637.                else
  638.                   printf("%s", origLine) ;
  639.                if (pauseFlag)
  640.                   {
  641.                   ++pauseLineCount ;
  642.                   if (pauseLineCount > MAX_LINE_PER_SCREEN)
  643.                      {
  644.                      pauseLineCount = 1 ;
  645.                      printf("Press ENTER to continue...\n");
  646.                      dummyVal = getchar() ;
  647.                      }
  648.                   }
  649.                }
  650.             }
  651.          }
  652.       fclose (inputFile) ;
  653.       }
  654.    }
  655.  
  656.  
  657.