home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / nshellmegasource1.50 / mega src / commands / grep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-30  |  9.6 KB  |  438 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     grep.c
  4.     
  5.     Copyright (c) 1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #ifdef __MWERKS__            // Get the appropriate A4 stuff
  16. #include <A4Stuff.h>
  17. #else
  18. #include <SetUpA4.h>
  19. #endif
  20.  
  21. #include <script.h>
  22. #include <string.h>
  23.  
  24. #include "nshc.h"
  25. #include "regexp.h"
  26. #include "regexp.proto.h"
  27.  
  28. #include "arg_utl.proto.h"
  29. #include "fss_utl.proto.h"
  30. #include "fss_utl2.proto.h"
  31. #include "nshc_utl.proto.h"
  32. #include "str_utl.proto.h"
  33.  
  34. // data definition - this struct is the root of all data
  35.  
  36. typedef struct {
  37.  
  38.     int        by_file;            // 1 if files are listed, 0 if stdin
  39.     int        got_fss;            // 1 if FSSpec calls are available
  40.     int        arg;                // next file to process in arg list
  41.     int        found;                // next file to process in arg list
  42.     short    e_arg;                // position of '-p' in arg list
  43.     short    fref;                // file ref. number, 0 if no file open
  44.     char    pattern[LINE_MAX];    // the pattern for which we search
  45.     char    line[LINE_MAX];        // the line we are currently looking at
  46.     int        line_pos;            // the place to put the next char in 'line'
  47.  
  48. } t_grep_data;
  49.  
  50. typedef    t_grep_data    **t_grep_handle;
  51.  
  52. /* ======================================== */
  53.  
  54. // globals
  55.  
  56. t_nshc_calls    *g_nshc_calls;        // global copy of nshc_calls to reduce parm passing
  57.  
  58. /* ======================================== */
  59.  
  60. // prototypes - utility
  61.  
  62. int  grep( char *pattern, char *target );
  63. void grep_bad( t_nshc_parms *nshc_parms, int code );
  64. void grep_bad_file( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg );
  65. void grep_good(  t_nshc_parms *nshc_parms, t_grep_handle gData );
  66.  
  67. // prototypes - file copy routines
  68.  
  69. void grep_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_grep_data **gData );
  70. void grep_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_grep_data **gData );
  71.  
  72. // prototypes - console copy routines
  73.  
  74. void grep_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_grep_data **gData );
  75.  
  76. // prototypes - state machine
  77.  
  78. void grep_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  );
  79. void grep_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  80. void grep_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  81.  
  82. /* ======================================== */
  83.  
  84. // utility routines
  85.  
  86. /* ======================================== */
  87.  
  88. void regerror(char *s)
  89. {
  90.     g_nshc_calls->NSH_puts_err( s );
  91. }
  92.  
  93. void grep_bad(  t_nshc_parms *nshc_parms, int code )
  94. {
  95.     nshc_parms->action = nsh_stop;
  96.     nshc_parms->result = code;
  97. }
  98.  
  99. void grep_bad_file(  t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg )
  100. {
  101.     nshc_calls->NSH_putStr_err("\pgrep: File access error (");
  102.     nshc_calls->NSH_putStr_err(msg);
  103.     nshc_calls->NSH_putStr_err("\p)\r");
  104.  
  105.     nshc_parms->action = nsh_stop;
  106.     nshc_parms->result = NSHC_ERR_GENERAL;
  107. }
  108.  
  109. void grep_good(  t_nshc_parms *nshc_parms, t_grep_handle gData )
  110. {
  111.     nshc_parms->action = nsh_stop;
  112.     
  113.     if ( (**gData).found )
  114.         nshc_parms->result = 0;
  115.     else
  116.         nshc_parms->result = 1;
  117. }
  118.  
  119. /* ======================================== */
  120.  
  121. // file access routines
  122.  
  123. /* ======================================== */
  124.  
  125. void grep_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_grep_data **gData )
  126. {
  127.     int        result;
  128.     long    dirID;
  129.     Boolean    isDir;
  130.     FSSpec    fss;
  131.     
  132.     (**gData).fref = 0;
  133.     (**gData).line_pos = 0;
  134.  
  135.     // =====> skip the -p option
  136.     
  137.     if ( (**gData).arg == (**gData).e_arg )
  138.         (**gData).arg += 2;
  139.         
  140.     if ( (**gData).arg >= nshc_parms->argc ) {
  141.         grep_good( nshc_parms, gData );
  142.         return;
  143.         }
  144.     
  145.     // =====> convert path to fsspec
  146.     
  147.     result = arg_to_fss( nshc_parms, nshc_calls, (**gData).arg, &fss );
  148.  
  149.     (**gData).arg++;
  150.     
  151.     if (result) {
  152.         grep_bad( nshc_parms, result );
  153.         return;
  154.         }
  155.     
  156.     result = fss_to_DirID( &fss, &dirID, &isDir );
  157.         
  158.     if (( result == noErr) && isDir)
  159.         return;
  160.             
  161.     if ( result == fnfErr ) {
  162.         nshc_calls->NSH_putStr_err("\pgrep: File not found = ");
  163.         nshc_calls->NSH_putStr_err((StringPtr)fss.name);
  164.         nshc_calls->NSH_putchar('\r');
  165.         return;
  166.         }
  167.             
  168.     if (!result)
  169.         result = fss_OpenDF((**gData).got_fss, &fss, fsRdPerm, &(**gData).fref);
  170.     
  171.     if ( result ) {
  172.         grep_bad_file( nshc_parms, nshc_calls, (StringPtr)fss.name );
  173.         return;
  174.         }
  175. }
  176.  
  177. /* ======================================== */
  178.  
  179. void grep_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_grep_data **gData )
  180. {
  181.     char    c;
  182.     int        close;
  183.     int        i,j;
  184.     int        temp;
  185.     int        result;
  186.     long    bcount;
  187.     char    buf[LINE_MAX];
  188.     char    *filename;
  189.     
  190.     result = close = 0;
  191.     
  192.     // =====> copy the data fork
  193.     
  194.     bcount = LINE_MAX - 1;
  195.     result = FSRead( (**gData).fref, &bcount, &buf );
  196.     
  197.     if (( result == noErr ) || ( result == eofErr )) {
  198.     
  199.         if (result == eofErr) {
  200.             close = 1;
  201.             result = 0;
  202.             }
  203.         
  204.         if (bcount) {
  205.             j = (**gData).line_pos;
  206.             for ( i = 0 ; i < bcount ; i++ ) {
  207.                 c = buf[i];
  208.                 if ( c && ( c != '\r' ) && ( j < 255 ) )
  209.                     (**gData).line[j++] = c;
  210.                 else {
  211.                     (**gData).line[j] = 0;
  212.                     HLock( gData );
  213.                     if ( grep( (**gData).pattern, (**gData).line ) ) {
  214.                         filename = &nshc_parms->arg_buf[nshc_parms->argv[(**gData).arg-1]];
  215.                         nshc_calls->NSH_puts( filename );
  216.                         nshc_calls->NSH_putStr( "\p: " );
  217.                         nshc_calls->NSH_puts( (**gData).line );
  218.                         nshc_calls->NSH_putchar( '\r' );
  219.                         (**gData).found = 1;
  220.                         }
  221.                     HUnlock( gData );
  222.                     j = 0;
  223.                     }
  224.                 }
  225.             (**gData).line_pos = j;
  226.             }
  227.     
  228.         }
  229.     else
  230.         grep_bad_file( nshc_parms, nshc_calls, "\pread data" );
  231.     
  232.     // =====> close the input file
  233.     
  234.     if (close) {
  235.  
  236.         if ( (**gData).fref ) {
  237.             if ( temp = FSClose( (**gData).fref ) )
  238.                 result = temp;
  239.             (**gData).fref = 0;
  240.             }
  241.             
  242.         if (result)
  243.             grep_bad_file( nshc_parms, nshc_calls, "\pclose file" );
  244.                 
  245.         }
  246. }
  247.  
  248. /* ======================================== */
  249.  
  250. // console access routines
  251.  
  252. /* ======================================== */
  253.  
  254. void grep_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_grep_data **gData )
  255. {
  256.     long    bcount;
  257.     char    buf[LINE_MAX];
  258.     
  259.     bcount = nshc_calls->NSH_gets( buf, LINE_MAX );
  260.     
  261.     if (!bcount) return;            // wait for characters
  262.     
  263.     if ( grep( (**gData).pattern, buf ) ) {
  264.         nshc_calls->NSH_puts( buf );
  265.         (**gData).found = 1;
  266.         }
  267.  
  268.     if ( bcount == -1 )                // end of input, set-up for exit
  269.         grep_good( nshc_parms, gData );
  270. }
  271.  
  272. /* ======================================== */
  273.  
  274. int grep( char *pattern, char *target )
  275. {
  276.     regexp    *r;
  277.     int        result;
  278.     
  279.     result = -1;
  280.     
  281.     r = regcomp( pattern );
  282.     
  283.     if ( r ) {
  284.         result = regexec( r, target );
  285.         DisposPtr( r );
  286.         }
  287.         
  288.     return( result );
  289. }
  290.  
  291. /* ======================================== */
  292.  
  293. // state machine - core routines
  294.  
  295. /* ======================================== */
  296.  
  297. void grep_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  )
  298. {
  299.     int                arg;
  300.     char             *p;
  301.     t_grep_handle    gData;    // handle to hold our data
  302.     
  303.     nshc_parms->action = nsh_continue;
  304.  
  305.     gData = (t_grep_handle)NewHandleClear(sizeof(t_grep_data));
  306.     
  307.     if (gData) {
  308.     
  309.         nshc_parms->data = (Handle)gData;            // save the handle to our data
  310.         (**gData).got_fss = fss_test();                // test if we can use FSSpec calls
  311.  
  312.         arg = nshc_got_option( nshc_parms, 'e' );    // get the position of '-e' arg
  313.         
  314.         // figure out if we are by_file, based on presence of -e option
  315.  
  316.         if (arg) {
  317.             (**gData).by_file = nshc_parms->argc > 3;
  318.             (**gData).arg = 1;
  319.             }
  320.         else {
  321.             (**gData).by_file = nshc_parms->argc > 2;
  322.             (**gData).arg = 2;
  323.             }
  324.             
  325.         (**gData).e_arg = arg;                        // save position of pattern
  326.         
  327.         if ( ++arg < nshc_parms->argc )
  328.             strcpy( (**gData).pattern, &nshc_parms->arg_buf[nshc_parms->argv[arg]] );
  329.         else {
  330.             nshc_calls->NSH_putStr_err( "\pUsage: grep [-e] pattern [files...]\r" );
  331.             grep_bad( nshc_parms, NSHC_ERR_PARMS );
  332.             }
  333.         
  334.         }
  335.     else {
  336.         nshc_calls->NSH_putStr_err( "\pgrep: Could not allocate storage.\r" );
  337.         grep_bad( nshc_parms, NSHC_ERR_MEMORY );
  338.         }
  339. }
  340.  
  341. /* ======================================== */
  342.  
  343. void grep_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  344. {
  345.     t_grep_handle    gData;
  346.  
  347.     if (gData = (t_grep_handle)nshc_parms->data) {
  348.  
  349.         if ( (**gData).by_file ) {
  350.         
  351.             // if we are not in the middle of a file, open one
  352.  
  353.             if ( !(**gData).fref )
  354.                 grep_open( nshc_parms, nshc_calls, gData );
  355.  
  356.             // read and write some of the open file
  357.  
  358.             if ( (**gData).fref )
  359.                 grep_read_write( nshc_parms, nshc_calls, gData );
  360.  
  361.             // and see if we are done
  362.  
  363.             if ( !(**gData).fref && ( (**gData).arg >= nshc_parms->argc ) )
  364.                 grep_good( nshc_parms, gData );
  365.                 
  366.             }
  367.         else
  368.             grep_console( nshc_parms, nshc_calls, gData );
  369.  
  370.         }
  371. }
  372.  
  373. /* ======================================== */
  374.  
  375. void grep_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  376. {
  377.     short            fRef;
  378.     t_grep_handle    gData;
  379.     int                temp;
  380.     int                result;
  381.     
  382.     result = 0;
  383.     
  384.     if (gData = (t_grep_handle)nshc_parms->data) {
  385.     
  386.         if ( (**gData).fref ) {
  387.             if ( temp = FSClose( (**gData).fref ) )
  388.                 result = temp;
  389.             (**gData).fref = 0;
  390.             }
  391.             
  392.         DisposeHandle(nshc_parms->data);
  393.         }
  394.         
  395.     if (result)
  396.         grep_bad_file( nshc_parms, nshc_calls, "\pclosing files" );
  397.         
  398.     nshc_parms->action = nsh_idle;
  399. }
  400.  
  401. /* ======================================== */
  402.  
  403. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  404. {
  405. #ifdef __MWERKS__
  406.     long oldA4  = SetCurrentA4();
  407. #else
  408.     RememberA0();
  409.     SetUpA4();
  410. #endif
  411.  
  412.     g_nshc_calls = nshc_calls;
  413.     
  414.     if ( !nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION ) ) {
  415.     
  416.         switch (nshc_parms->action) {
  417.             case nsh_start:
  418.                 grep_start(nshc_parms, nshc_calls);
  419.                 break;
  420.             case nsh_continue:
  421.                 grep_continue(nshc_parms, nshc_calls);
  422.                 break;
  423.             case nsh_stop:
  424.                 grep_stop(nshc_parms, nshc_calls);
  425.                 break;
  426.             }
  427.         
  428.         }
  429.  
  430. #ifdef __MWERKS__
  431.     SetA4(oldA4);
  432. #else
  433.     RestoreA4();
  434. #endif
  435. }
  436.  
  437. /* ======================================== */
  438.