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