First version of dfa module in alex. This version uses yacc to parse
[idzebra-moved-to-github.git] / dfa / agrep.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: agrep.c,v $
7  * Revision 1.1  1994-09-26 10:16:52  adam
8  * First version of dfa module in alex. This version uses yacc to parse
9  * regular expressions. This should be hand-made instead.
10  *
11  */
12 #include <stdio.h>
13 #include <assert.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <stdarg.h>
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22
23
24 #include <util.h>
25 #include "imalloc.h"
26 #include "dfa.h"
27
28 #ifndef O_BINARY
29 #define O_BINARY 0
30 #endif
31
32 static char *prog;
33
34 void error( const char *format, ... )
35 {
36     va_list argptr;
37     va_start( argptr, format );
38     fprintf( stderr, "%s error: ", prog );
39     (void) vfprintf( stderr, format, argptr );
40     putc( '\n', stderr );
41     exit( 1 );
42 }
43
44 #ifdef YYDEBUG
45 #ifdef YACC
46 extern int yydebug;
47 #else
48 extern int alexdebug;
49 #endif
50 #endif
51
52 static int show_lines = 0;
53
54 int agrep_options( argc, argv )
55 int argc;
56 char **argv;
57 {
58     while( --argc > 0 )
59         if( **++argv == '-' )
60             while( *++*argv )
61             {
62                 switch( **argv )
63                 {
64 #ifdef __STDC__
65                 case 'V':
66                     fprintf( stderr, "%s: %s %s\n", prog, __DATE__, __TIME__ );
67                     continue;
68 #endif
69                 case 'v':
70                     dfa_verbose = 1;
71                     continue;
72                 case 'n':
73                     show_lines = 1;
74                     continue;
75 #ifdef YYDEBUG
76                 case 't':
77 #ifdef YACC
78                     yydebug = 1;
79 #else
80                     alexdebug = 1;
81 #endif
82                     continue;
83 #endif
84                 case 'd':
85                     switch( *++*argv )
86                     {
87                     case 's':
88                         debug_dfa_tran = 1;
89                         break;
90                     case 't':
91                         debug_dfa_trav = 1;
92                         break;
93                     case 'f':
94                         debug_dfa_followpos = 1;
95                         break;
96                     default:
97                         --*argv;
98                         debug_dfa_tran = 1;
99                         debug_dfa_followpos = 1;
100                         debug_dfa_trav = 1;
101                     }
102                     continue;
103                 default:
104                     fprintf( stderr, "%s: unknown option `-%s'\n", prog, *argv );
105                     return 1;
106                 }
107                 break;
108             }
109     return 0;
110 }
111
112 #define INF_BUF_SIZE  32768U
113 static char *inf_buf;
114 static char *inf_ptr, *inf_flsh;
115 static int inf_eof, line_no;
116
117 static int inf_flush( fd )
118 int fd;
119 {
120     char *p;
121     unsigned b, r;
122
123     r = (unsigned) (inf_buf+INF_BUF_SIZE - inf_ptr);  /* no of `wrap' bytes */
124     if( r )
125         memcpy( inf_buf, inf_ptr, r );
126     inf_ptr = p = inf_buf + r;
127     b = INF_BUF_SIZE - r;
128     do
129         if( (r = read( fd, p, b ) ) == (unsigned) -1 )
130             return -1;
131         else if( r )
132             p +=  r;
133         else
134         {
135             *p++ = '\n';
136             inf_eof = 1;
137             break;
138         }
139     while( (b -= r) > 0 );
140     while( p != inf_buf && *--p != '\n' )
141         ;
142     while( p != inf_buf && *--p != '\n' )
143         ;
144     inf_flsh = p+1;
145     return 0;
146 }
147
148 static char *prline( p )
149 char *p;
150 {
151     char *p0;
152
153     --p;
154     while( p != inf_buf && p[-1] != '\n' )
155         --p;
156     p0 = p;
157     while( *p++ != '\n' )
158         ;
159     p[-1] = '\0';
160     if( show_lines )
161         printf( "%5d:\t%s\n", line_no, p0 );
162     else
163         puts( p0 );
164     p[-1] = '\n';
165     return p;
166 }
167
168 static int go( fd, dfaar )
169 int fd;
170 DFA_state **dfaar;
171 {
172     DFA_state *s = dfaar[0];
173     DFA_tran *t;
174     char *p;
175     int i;
176     unsigned char c;
177
178     while( 1 )
179     {
180         for( c = *inf_ptr++, t=s->trans, i=s->tran_no; --i >= 0; t++ )
181             if( c >= t->ch[0] && c <= t->ch[1] )
182             {
183                 p = inf_ptr;
184                 do
185                 {
186                     if( (s = dfaar[t->to] )->rule_no )
187                     {
188                         inf_ptr = prline( inf_ptr );
189                         c = '\n';
190                         break;
191                     }
192                     for( t=s->trans, i=s->tran_no; --i >= 0; t++ )
193                         if( (unsigned) *p >= t->ch[0] 
194                            && (unsigned) *p <= t->ch[1] )
195                             break;
196                     p++;
197                 } while( i >= 0 );
198                 s = dfaar[0];
199                 break;
200             }
201         if( c == '\n' )
202         {
203             ++line_no;
204             if( inf_ptr == inf_flsh )
205             {
206                 if( inf_eof )
207                     break;
208                 ++line_no;
209                 if( inf_flush( fd ) )
210                 {
211                     fprintf( stderr, "%s: read error\n", prog );
212                     return -1;
213                 }
214             }
215         }
216     }
217     return 0;
218 }
219
220 int agrep( dfas, fd )
221 DFA_states *dfas;
222 int fd;
223 {
224     inf_buf = imalloc( sizeof(char)*INF_BUF_SIZE );
225     inf_eof = 0;
226     inf_ptr = inf_buf+INF_BUF_SIZE;
227     inf_flush( fd );
228     line_no = 1;
229
230     go( fd, dfas->sortarray);
231
232     ifree( inf_buf );
233     return 0;
234 }
235
236
237 int main( argc, argv )
238 int argc;
239 char **argv;
240 {
241     char *pattern = NULL;
242     char outbuf[BUFSIZ];
243     int fd, i, no = 0;
244     DFA *dfa = init_dfa();
245     DFA_states *dfas;
246
247     prog = *argv;
248 #ifdef YYDEBUG
249 #ifdef YACC
250     yydebug = 0;
251 #else
252     alexdebug = 0;
253 #endif
254 #endif
255     setbuf( stdout, outbuf );
256     i = agrep_options( argc, argv );
257     if( i )
258         return i;
259     while( --argc > 0 )
260         if( **++argv != '-' && **argv )
261             if( !pattern )
262             {
263                 pattern = *argv;
264                 i = parse_dfa( dfa, &pattern, grep_chars );
265                 if( i || *pattern )
266                 {
267                     fprintf( stderr, "%s: illegal pattern\n", prog );
268                     return 1;
269                 }
270                 dfa->root = dfa->top;
271                 dfas = mk_dfas( dfa, 200 );
272                 rm_dfa( &dfa );
273             }
274             else
275             {
276                 ++no;
277                 fd = open( *argv, O_RDONLY | O_BINARY);
278                 if( fd == -1 )
279                 {
280                     fprintf( stderr, "%s: couldn't open `%s'\n", prog, *argv );
281                     return 1;
282                 }
283                 i = agrep( dfas, fd );
284                 close( fd );
285                 if( i )
286                     return i;
287             }
288     if( !no )
289     {
290         fprintf( stderr, "%s: no files specified\n", prog );
291         return 2;
292     }
293     fflush(stdout);
294     return 0;
295 }