home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional Developers Kit 1992 November / Disc01 / Disc01.mdf / cppbeta / wkframe / grepk / grep.c__ / GREP.C
Encoding:
Text File  |  1992-04-01  |  22.6 KB  |  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.         |*/
  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/2 Standard Library                             |*/
  55. /*|    DDE4SBM.LIB    - C Set/2 Migration Library                            |*/
  56. /*|                                                                          |*/
  57. /*|  REQUIRED PROGRAMS:                                                      |*/
  58. /*|  ------------------                                                      |*/
  59. /*|                                                                          |*/
  60. /*|    IBM C Set/2 Compiler                                                  |*/
  61. /*|    IBM Linker                                                            |*/
  62. /*|                                                                          |*/
  63. /*|                                                                          |*/
  64. /*+--------------------------------------------------------------------------+*/
  65.  
  66.  
  67. #include <string.h>
  68. #include <ctype.h>
  69. #include <stdio.h>
  70. #include <stdlib.h>
  71. #include "grep.h"
  72.  
  73. #ifndef OS2_INCLUDED
  74.    #define OS2_INCLUDED
  75.    #define  INCL_DOS
  76.    #define  INCL_DOSERRORS
  77.    #include <os2.h>
  78. #endif
  79.  
  80. static  FILEFINDBUF3  findBuffer  ;
  81. static  FILE *inputFile ;
  82. static  char inputLine[MAX_LINE_LENGTH] ;
  83. static  char origLine[MAX_LINE_LENGTH]  ;
  84. static  int  inputLineLength            ;
  85. static  int  dummyVal                   ;
  86. static  int  printFileName              ;
  87. static  char *searchPattern = NULL      ;
  88. static  int fileCount, lineCount        ;
  89. static  int contextCount                ;
  90. static  char *theLine                   ;
  91. static  char *tmpLine                   ;
  92. static  char fileMask[255]              ;
  93. static  char searchPath[260]            ;
  94.  
  95.    /*********************/
  96.    /* Options variables */
  97.    /*********************/
  98.  
  99. static  int helpType            ;
  100. static  int noLogo      = 0     ;
  101. static  int caseFlag    = 0     ;
  102. static  int pauseFlag   = 0     ;
  103. static  int countFlag   = 0     ;
  104. static  int lineFlag    = 0     ;
  105. static  int contextFlag = 0     ;
  106. static  int absFlag     = 0     ;
  107. static  int dirFlag     = 0     ;
  108. static  int notFlag     = 0     ;
  109. static  int nameFlag    = 0     ;
  110. static  int pauseLineCount  = 0     ;
  111.  
  112.  
  113. /*****************************************************************/
  114. /* The following declarations support simple regular expressions */
  115. /*****************************************************************/
  116.  
  117. char *regExprKeyChar  = "*?" ;
  118.  
  119. typedef struct  structName
  120.    {
  121.    char * str   ;                /* Piece of string to search for */
  122.    int  strType ;
  123.    struct  structName * next ;
  124.    } subStringList ;
  125.  
  126. subStringList * listHead = NULL ;
  127. subStringList * curPtr   = NULL ;
  128. subStringList * prevPtr   = NULL ;
  129. int prevStrType , pieceLength        ;
  130.  
  131. char * tmpPtr   ;
  132. int foundFlag   ;
  133.  
  134. /*****************************/
  135. /*   Function Prototypes     */
  136. /*****************************/
  137.  
  138. void  processFile(char *);
  139. int   forAllMatch(char * );
  140. void  grepHelp(int );
  141.  
  142.                   /*********************/
  143.                   /*   Main Program    */
  144.                   /*********************/
  145.  
  146. int main (int argc, char **argv)
  147.    {
  148.    if ( argc == 1)
  149.       {
  150.       grepHelp(LINE_HELP) ;
  151.       exit (0) ;
  152.       }
  153.     argv++;
  154.     argc--;
  155.  
  156.     /*******************/
  157.     /* Process options */
  158.     /*******************/
  159.  
  160.     while ( argc > 0 && (**argv == '-' ||  **argv == '/' )  )
  161.        {
  162.        (*argv)++ ;
  163.        while (**argv != '\0')
  164.            {
  165.            switch (**argv)
  166.               {
  167.               case  'q':
  168.                  noLogo = 1 ;
  169.                  break ;
  170.  
  171.               case  'y':
  172.                  caseFlag    = 1 ;
  173.                  break ;
  174.  
  175.               case  's':
  176.                  dirFlag    = 1 ;
  177.                  break ;
  178.  
  179.               case  'n':
  180.                  nameFlag   = 1 ;
  181.                  break ;
  182.  
  183.               case  'p':
  184.                  pauseFlag = 1 ;
  185.                  break ;
  186.  
  187.               case  'l':
  188.                  lineFlag = 1 ;
  189.                  break ;
  190.  
  191.               case  'a':
  192.                  absFlag = 1 ;
  193.                  break ;
  194.  
  195.               case  'c':
  196.                  countFlag = 1 ;
  197.                  break ;
  198.  
  199.               case  'v':
  200.                  notFlag = 1 ;
  201.                  break ;
  202.  
  203.               case  'C':
  204.                  contextFlag = 1 ;
  205.                  (*argv)++;
  206.                  if ( ! isdigit(**argv) )
  207.                     printf("'-C' option expected integer, default of 3 is assumed.\n");
  208.                  else
  209.                     {
  210.                     contextCount = **argv ;
  211.                     (*argv)++;
  212.                     }
  213.                  break ;
  214.  
  215.               case  'h':
  216.                  grepHelp(FULL_HELP);
  217.                  exit(0);
  218.  
  219.               case  'z':
  220.                  grepHelp(CMDS_HELP);
  221.                  exit(0);
  222.  
  223.               default:
  224.                  printf("Grep: Unrecognized flag '%c' ignored.\n\n",**argv);
  225.                  break;
  226.               }
  227.            (*argv)++;
  228.            }
  229.        argv++ ;
  230.        argc-- ;
  231.        }
  232.  
  233.      if (argc == 0)
  234.         {
  235.         printf("grep: incorrect number of parameters\n");
  236.         grepHelp(LINE_HELP);
  237.         exit(255) ;
  238.         }
  239.  
  240.     /******************************/
  241.     /* Process the search pattern */
  242.     /******************************/
  243.  
  244.     searchPattern = *argv ;
  245.     argv++ ;
  246.     argc-- ;
  247.  
  248.     if ( ! noLogo )
  249.        {
  250.        printf("IBM C Set/2 Grep Utility\n") ;
  251.        printf("Copyright (C) International Business Machines Corp., 1991,1992.\n\n");
  252.        }
  253.  
  254.     if ( ! argc)
  255.        {
  256.        printf("Grep: You must specify at least one file name!\n");
  257.        exit (255) ;
  258.        }
  259.  
  260.     printf("Searching for \"%s\"\n",searchPattern);
  261.  
  262.     if ( ! caseFlag )
  263.        (void)strupr(searchPattern) ;
  264.  
  265.     /***********************************************************/
  266.     /* Below, we are building a linked-list of search patterns.*/
  267.     /* Each block is composed of the longest substring before  */
  268.     /* the appearance of any Special Chars (ie ? and * ).      */
  269.     /* There are two types of blocks, one type is the  one     */
  270.     /* mentioned above, the other type is a block containing   */
  271.     /* information on how many '?'s we have to match.          */
  272.     /***********************************************************/
  273.  
  274.     if (absFlag)       /* Interpret the search string as absolute. */
  275.        {
  276.        if ((listHead = (subStringList *)malloc(sizeof(subStringList))) == NULL)
  277.           {
  278.           printf("grep(1): Unable to get memory!\n");
  279.           exit(255);
  280.           }
  281.        listHead->str = searchPattern ;
  282.        listHead->strType  = REGULAR_TYPE ;
  283.        listHead->next = NULL ;
  284.        prevPtr = NULL      ;
  285.        }
  286.     else
  287.        /* Parsing of the expression line. */
  288.        {
  289.        if ((listHead = (subStringList *)malloc(sizeof(subStringList))) == NULL)
  290.           {
  291.           printf("grep(2): Unable to get memory! \n");
  292.           exit(255);
  293.           }
  294.  
  295.        curPtr = listHead   ;
  296.        curPtr->strType = 0 ;
  297.        curPtr->str = NULL  ;
  298.        curPtr->next = NULL ;
  299.        prevPtr = NULL      ;
  300.  
  301.        tmpPtr = searchPattern  ;
  302.  
  303.        while (*tmpPtr != '\0')
  304.           {
  305.           pieceLength = strcspn(tmpPtr,regExprKeyChar) ;
  306.  
  307.           if (! pieceLength )  /* Found '*' or '?' */
  308.              {
  309.              if (*tmpPtr == '*' )
  310.                 ++tmpPtr ;
  311.              else
  312.                 {
  313.                 curPtr->str = NULL ;
  314.                 curPtr->strType = 1;
  315.                 ++tmpPtr ;
  316.                 while (*tmpPtr == '?')
  317.                    {
  318.                    ++tmpPtr ;
  319.                    curPtr->strType += 1;
  320.                    }
  321.                 if ((curPtr->next = (subStringList *)malloc(sizeof(subStringList))) == NULL)
  322.                    {
  323.                    printf("grep(3): Unable to get memory!\n");
  324.                    exit(255);
  325.                    }
  326.                 prevPtr = curPtr      ;
  327.                 curPtr = curPtr->next ;
  328.                 curPtr->next = NULL   ;
  329.  
  330.                 }
  331.              }
  332.           else
  333.              {
  334.              if ((curPtr->str = (char *)malloc(pieceLength+1)) == NULL)
  335.                 {
  336.                 printf("grep(4): Unable to get memory!\n");
  337.                 exit(255);
  338.                 }
  339.              memcpy(curPtr->str,tmpPtr,pieceLength) ;
  340.              *(curPtr->str+pieceLength) = '\0'      ;
  341.              curPtr->strType = REGULAR_TYPE ;
  342.              tmpPtr +=  pieceLength         ;
  343.              if ((curPtr->next = (subStringList *)malloc(sizeof(subStringList))) == NULL)
  344.                 {
  345.                 printf("grep(5): Unable to get memory!\n");
  346.                 exit(255);
  347.                 }
  348.              prevPtr = curPtr      ;
  349.              curPtr = curPtr->next ;
  350.              curPtr->next = NULL   ;
  351.              }
  352.           }
  353.        }
  354.  
  355.  
  356.    if (prevPtr == NULL && absFlag != 1)
  357.       {
  358.       printf("grep: You have specified an invalid pattern!\n");
  359.       exit(255) ;
  360.       }
  361.  
  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.