home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1987 / 10 / bowlst.oct next >
Text File  |  1987-09-14  |  16KB  |  518 lines

  1. Listing 1
  2.  
  3.      /*
  4.       *
  5.       *                              FINDCMD
  6.       *
  7.       *                           MODULE: MAIN.C
  8.       *
  9.       *               COPYRIGHT (C) 1987 by Charles F. Bowman
  10.       *                        All Rights Reserved.
  11.       *
  12.       */
  13.      
  14.      /*
  15.       *      This module contains the driving loop of the program.
  16.       */
  17.      #include        <stdio.h>
  18.      
  19.      #include        "findcmd.h"
  20.      
  21.      struct  attribs atts[] = {              /* For display */
  22.              DIRECT, 'd',
  23.              RDONLY, 'r',
  24.              HIDDEN, 'h',
  25.              SYSTEM, 's',
  26.              ARCHIV, 'a'
  27.      };
  28.      
  29.      char *month[] = {
  30.              "Jan", "Feb", "Mar",
  31.              "Apr", "May", "Jun",
  32.              "Jul", "Aug", "Sep",
  33.              "Oct", "Nov", "Dec"
  34.      };
  35.      
  36.      main( ac, av )
  37.      int     ac;
  38.      char    *av[];
  39.      {
  40.              int     i, len;
  41.              char    dir[ MAXPATH ];
  42.              char    path[ MAXPATH ];
  43.              char    *tptr, tpath[ MAXPATH ];
  44.              struct  dirent  dfile;
  45.      
  46.              if( ac == 1 ){
  47.                      fprintf( stderr, "usage: fc pat1 pat2 ... patn\n" );
  48.                      exit( 1 );
  49.              }
  50.      
  51.              printf( "FINDCMD - COPYRIGHT (C) 1987, Charles F. Bowman. " );
  52.              printf( "All Rights Reserved.\n\n" );
  53.      
  54.              sprintf( path, ".;%s", getenv("PATH") );        /* Get path */
  55.      
  56.              for( i = 1; i < ac; i++ ){
  57.                      /*
  58.                       *      For each supplied pattern argument
  59.                       */
  60.                      strcpy( tpath, path );
  61.                      tptr = tpath;
  62.                      inits( av[i] );         /* set-up transition table */
  63.                      while( (len = nextdir(tptr)) > 0 ){
  64.                              /*
  65.                               *      For each directory component
  66.                               */
  67.                              tptr[ len ] = NIL;
  68.                              if( tptr[len-1] == '\\' ){
  69.                                      /*
  70.                                       *      No double backslashes!
  71.                                       */
  72.                                      sprintf( dir, "%s*.*", tptr );
  73.                              } else {
  74.                                      sprintf( dir, "%s\\*.*", tptr );
  75.                              }
  76.      
  77.                              /*
  78.                               *      Compare each entry in directory
  79.                               */
  80.                              if( firstf(dir, &dfile) ){      /* Get first */
  81.                                      /*
  82.                                       *      Error - bad dir in path
  83.                                       */
  84.                                      fprintf( stderr,
  85.                                              "BAD DIRECTORY SEGMENT: [%s]\n",
  86.                                              dir );
  87.                                      break;
  88.                              }
  89.                              do{
  90.                                      if( state(slcase(dfile.dname)) ){
  91.                                              /*
  92.                                               *      Print if a match is found!
  93.                                               */
  94.                                              putfile( &dfile, tptr );
  95.                                      }
  96.                              } while( nextf(&dfile) );       /* Get next */
  97.      
  98.                              tptr += len + 1;
  99.                      }
  100.              }
  101.      
  102.              exit( 0 );
  103.      }
  104.      
  105.      /*
  106.       *      NEXTDIR: return the next directory component of 'PATH'
  107.       */
  108.      nextdir( cp )
  109.      char    *cp;
  110.      {
  111.              register        count;
  112.      
  113.  
  114.              count = 0;
  115.              if( *cp == NIL ){               /* End of list */
  116.                      return( -1 );
  117.              }
  118.              while( *cp != NIL && *cp != FLDSEP ){
  119.                      cp++;
  120.                      count++;
  121.              }
  122.              return( count );
  123.      }
  124.      
  125.      /*
  126.       *      SLCASE: convert a string to lower case
  127.       */
  128.      char    *
  129.      slcase( cp )
  130.      char    *cp;
  131.      {
  132.              register char   *ptr;
  133.      
  134.              ptr = cp;
  135.              while( *ptr ){
  136.                      *ptr = tolower( *ptr );
  137.                      ptr++;
  138.              }
  139.      
  140.              return( cp );
  141.      }
  142.      
  143.      /*
  144.       *      PUTFILE: display directory info for each matched file
  145.       */
  146.      putfile( dfile, dir )
  147.      struct  dirent  *dfile;
  148.      char    *dir;
  149.      {
  150.              int     i;
  151.              char    datestr[ 50 ];
  152.      
  153.              /*
  154.               *      Print attribute chatacters
  155.               */
  156.              for( i = 0; i < SA_SIZE(atts); i++ ){
  157.                      if( atts[i].val & dfile->dattr ){
  158.                              putchar( atts[i].chr );
  159.                      } else {
  160.                              putchar( '-' );
  161.                      }
  162.              }
  163.      
  164.              fdosdte( datestr, &dfile->ddate );      /* DOS -> ASCII */
  165.              if( dir[strlen(dir)-1] == '\\' ){
  166.                      /*
  167.                       *      No double backslashes!
  168.                       */
  169.  
  170.                      printf( " %8D %s %s%s\n",
  171.                              dfile->dsize,
  172.                              datestr,
  173.                              slcase(dir),
  174.                              dfile->dname
  175.                      );
  176.              } else {
  177.                      printf( " %8D %s %s\\%s\n",
  178.                              dfile->dsize,
  179.                              datestr,
  180.                              slcase(dir),
  181.                              dfile->dname
  182.                      );
  183.              }
  184.      
  185.              return( 0 );
  186.      }
  187.      
  188.      /*
  189.       *      FDOSDATE: convert a DOS format date to an ASCII string
  190.       */
  191.      fdosdte( where, dptr )
  192.      char    *where;
  193.      struct  dosdate *dptr;
  194.      {
  195.              sprintf( where, "%s %2d %02d:%02d:%02d %4d",
  196.                      month[ dptr->month-1 ],
  197.                      dptr->day,
  198.                      dptr->hour,
  199.                      dptr->min,
  200.                      dptr->sec * 2,
  201.                      dptr->year + 1980
  202.              );
  203.      
  204.              return( 0 );
  205.      }
  206.  
  207. Listing 2
  208.  
  209.  
  210.      /*
  211.       *
  212.       *                              FINDCMD
  213.       *
  214.       *                           MODULE: DOS.C
  215.       *
  216.       *               COPYRIGHT (C) 1987 by Charles F. Bowman
  217.       *                        All Rights Reserved.
  218.       *
  219.       */
  220.      
  221.      /*
  222.       *      This module contains the DOS dependent functions to
  223.       *      access file names in directories. This is non-portable code.
  224.       */
  225.      #include        <dos.h>
  226.      #include        <stdio.h>
  227.      
  228.      #include        "findcmd.h"
  229.      
  230.      struct  reg     regs;                   /* set & retrieve regs */
  231.      static  struct  dirent  lfile;          /* DOS disk trans addr */
  232.      
  233.      /*
  234.       *      FIRSTF: initiate DOS environment and return first file name
  235.       */
  236.      firstf( dirpath, dfile )
  237.      char    *dirpath;
  238.      struct  dirent  *dfile;
  239.      {
  240.              /*
  241.               *      Set disk transfer address
  242.               */
  243.              regs.r_ax = SETDTA;
  244.              ptoreg( dsreg, regs.r_dx, regs.r_ds, &lfile );
  245.              intcall( ®s, ®s, DOSINT );
  246.      
  247.              /*
  248.               *      Find first 
  249.               */
  250.              regs.r_ax = NFFIRST;
  251.              regs.r_cx = HIDDEN | SYSTEM | DIRECT | RDONLY | ARCHIV; /* All! */
  252.              ptoreg( dsreg, regs.r_dx, regs.r_ds, dirpath );
  253.              intcall( ®s, ®s, DOSINT );
  254.      
  255.              if( regs.r_flags & F_CF ){
  256.                      /*
  257.                       *      Error!
  258.                       */
  259.                      return( 1 );
  260.              }
  261.      
  262.              *dfile = lfile;
  263.              return( 0 );
  264.      }
  265.      
  266.      /*
  267.       *      NEXTF: return all subsequent files in directory
  268.       */
  269.      nextf( dfile )
  270.      struct  dirent  *dfile;
  271.      {
  272.              /*
  273.               *      Call DOS: find next
  274.               */
  275.              regs.r_ax = NFNEXT;
  276.              regs.r_cx = HIDDEN | SYSTEM | DIRECT | RDONLY | ARCHIV;
  277.              intcall( ®s, ®s, DOSINT );
  278.      
  279.              if( regs.r_flags & F_CF ){
  280.                      /*
  281.                       *      Error!
  282.                       */
  283.                      return( 0 );
  284.              }
  285.      
  286.              *dfile = lfile;
  287.              return( 1 );
  288.      }
  289.  
  290. Listing 3
  291.  
  292.      /*
  293.       *
  294.       *                              FINDCMD
  295.       *
  296.       *                          MODULE: STATE.C
  297.       *
  298.       *               COPYRIGHT (C) 1987 by Charles F. Bowman
  299.       *                        All Rights Reserved.
  300.       *
  301.       */
  302.      
  303.      /*
  304.       *      This module contains the routines nesessary
  305.       *      to implement the state machine
  306.       */
  307.      #include        <stdio.h>
  308.      
  309.      #include        "findcmd.h"
  310.      
  311.      static  int     tos = -1;
  312.      static  int     pat[ 100 ];
  313.      static  struct  stk     stk[ 100 ];
  314.      
  315.      /*
  316.       *      INITS: initialize the state machine (transition table)
  317.       */
  318.      inits( p )
  319.      char    *p;
  320.      {
  321.              register int     i;
  322.      
  323.              i = 1;
  324.              pat[0] = PATBEG;
  325.              while( *p != NIL ){
  326.                      /*
  327.                       *      Add each char in pattern to state array
  328.                       */
  329.                      switch( *p ){
  330.                      case '?':
  331.                              pat[i] = QUEST;
  332.                              break;
  333.                      case '*':
  334.                              pat[i] = ASTER;
  335.                              break;
  336.                      default:
  337.                              pat[i] = *p;
  338.                              break;
  339.                      }
  340.                      p++;
  341.                      i++;
  342.              }
  343.              pat[i] = PATEND;
  344.      
  345.              return( 0 );
  346.      }
  347.      
  348.      /*
  349.       *      STATE: driving routine for the state machine; 
  350.       *             performs the actual pattern matching.
  351.       */
  352.      state( n )
  353.      char    *n;
  354.      {
  355.              register int     state;
  356.              char    *ptr;
  357.      
  358.              ptr = n;
  359.              tos = -1;
  360.              state = 0;
  361.              for(;;){                                /* Forever */
  362.                      switch( pat[state] ){
  363.                      case PATBEG:                    /* Begin state */
  364.                              break;
  365.      
  366.                      case ASTER:                     /* Wild card */
  367.                              if( *(ptr+1) != NIL ){
  368.                                      /*
  369.                                       *      Save machine state
  370.                                       */
  371.                                      PUSH( state-1, ptr+1 );
  372.                              }
  373.                              while( (*ptr != pat[state+1]) && (*ptr != NIL) ){
  374.                                      /*
  375.                                       *      Skip non-matching chars
  376.                                       *      up to end of string
  377.                                       */
  378.                                      ptr++;
  379.                              }
  380.                              break;
  381.      
  382.                      case PATEND:                    /* End state */
  383.                              if( *ptr == NIL ){
  384.                                      /*
  385.                                       *      Match!
  386.                                       */
  387.                                      return( 1 );
  388.                              } else if( TOS ){
  389.                                      /*
  390.                                       *      No match - restore saved state
  391.                                       */
  392.                                      POP( state, ptr );
  393.                              } else {
  394.                                      /*
  395.                                       *      No match!
  396.                                       */
  397.                                      return( 0 );
  398.                              }
  399.                              break;
  400.      
  401.                      case QUEST:                     /* Any 1 character */
  402.                              ptr++;
  403.                              break;
  404.      
  405.                      default:
  406.                              if( *ptr != pat[state] ){
  407.                                      if( TOS ){
  408.                                              /*
  409.                                               *      Restore saved state
  410.                                               */
  411.                                              POP( state, ptr );
  412.                                      } else {
  413.                                              /*
  414.                                               *      Fail - no match!
  415.                                               */
  416.                                              return( 0 );
  417.                                      }
  418.                              } else {
  419.                                      /*
  420.                                       *      Equal - move on
  421.                                       */
  422.                                      ptr++;
  423.                              }
  424.                              break;
  425.                      }
  426.                      state++;                        /* Next state */
  427.              }
  428.      }
  429.  
  430.  
  431. Listing 4
  432.      /*
  433.       *
  434.       *                              FINDCMD
  435.       *
  436.       *                           MODULE: FINDCMD.H
  437.       *
  438.       *               COPYRIGHT (C) 1987 by Charles F. Bowman
  439.       *                        All Rights Reserved.
  440.       *
  441.       */
  442.      
  443.      /*
  444.       *      Header file for FINDCMD.C
  445.       */
  446.      #define NIL     '\0'
  447.      #define FLDSEP  ';'                     /* dir separator in path */
  448.      #define MAXPATH 250
  449.      
  450.      /*
  451.       *      Machine states
  452.       */
  453.      #define ASTER   128
  454.      #define QUEST   129
  455.      #define PATBEG  130
  456.      #define PATEND  131
  457.      
  458.      /*
  459.       *      DOS file attribute bits
  460.       */
  461.      #define RDONLY  0x01                    /* Read only file */
  462.      #define HIDDEN  0x02                    /* Hidden file */
  463.      #define SYSTEM  0x04                    /* System file */
  464.      #define DIRECT  0x10                    /* Directory file */
  465.      #define ARCHIV  0x20                    /* Archive bit */
  466.      
  467.      #define SA_SIZE(foo)    (sizeof(foo)/sizeof(foo[0]))
  468.      
  469.      /*
  470.       *      Macros for stack manipulation
  471.       */
  472.      #define TOS             (tos == -1 ? 0 : 1)
  473.      #define POP(x,y)        {x = stk[tos].state; y = stk[tos].ptr; tos--; }
  474.      #define PUSH(x,y)       { tos++; stk[tos].state = (x); stk[tos].ptr = (y); }
  475.      
  476.      char    *slcase();
  477.      
  478.      /*
  479.       *      Internal DOS date structure
  480.       */
  481.      struct dosdate {
  482.              unsigned sec    : 5;            /* Second (intervals of 2) */
  483.              unsigned min    : 6;            /* Minutes */
  484.              unsigned hour   : 5;            /* Hours */
  485.              unsigned day    : 5;            /* Day of month */
  486.              unsigned month  : 4;            /* Month of year */
  487.              unsigned year   : 7;            /* Year since 1980 */
  488.      };
  489.      
  490.      
  491.      /*
  492.       *      DOS FCB / DIR ENTRY - Set to DTA
  493.       */
  494.      struct  dirent  {
  495.              char    dinfo[ 21 ];
  496.              char    dattr;
  497.              struct  dosdate ddate;
  498.              long    dsize;
  499.              char    dname[ 13 ];
  500.      };
  501.      
  502.      /*
  503.       *      Used to print attribute bits of files
  504.       */
  505.      struct attribs {
  506.                       int    val;
  507.                       int    chr;
  508.      };
  509.      
  510.      /*
  511.       *      Used to save an restore machine state
  512.       */
  513.      struct  stk     {
  514.              int     state;
  515.              char    *ptr;
  516.      };
  517.      
  518.