Bug fix.
[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.7  1995-10-16 09:31:24  adam
8  * Bug fix.
9  *
10  * Revision 1.6  1995/09/28  09:18:51  adam
11  * Removed various preprocessor defines.
12  *
13  * Revision 1.5  1995/09/04  12:33:25  adam
14  * Various cleanup. YAZ util used instead.
15  *
16  * Revision 1.4  1995/01/24  16:00:21  adam
17  * Added -ansi to CFLAGS.
18  * Some changes to the dfa module.
19  *
20  * Revision 1.3  1994/09/27  16:31:18  adam
21  * First version of grepper: grep with error correction.
22  *
23  * Revision 1.2  1994/09/26  16:30:56  adam
24  * Minor changes. imalloc uses xmalloc now.
25  *
26  * Revision 1.1  1994/09/26  10:16:52  adam
27  * First version of dfa module in alex. This version uses yacc to parse
28  * regular expressions. This should be hand-made instead.
29  *
30  */
31 #include <stdio.h>
32 #include <assert.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdarg.h>
36
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41
42
43 #include <alexutil.h>
44 #include <dfa.h>
45 #include "imalloc.h"
46
47 #ifndef O_BINARY
48 #define O_BINARY 0
49 #endif
50
51 static char *prog;
52
53 void error (const char *format, ...)
54 {
55     va_list argptr;
56     va_start (argptr, format);
57     fprintf (stderr, "%s error: ", prog);
58     (void) vfprintf (stderr, format, argptr);
59     putc ('\n', stderr);
60     exit (1);
61 }
62
63 static int show_lines = 0;
64
65 int agrep_options (argc, argv)
66 int argc;
67 char **argv;
68 {
69     while (--argc > 0)
70         if (**++argv == '-')
71             while (*++*argv)
72             {
73                 switch (**argv)
74                 {
75                 case 'V':
76                     fprintf (stderr, "%s: %s %s\n", prog, __DATE__, __TIME__);
77                     continue;
78                 case 'v':
79                     dfa_verbose = 1;
80                     continue;
81                 case 'n':
82                     show_lines = 1;
83                     continue;
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 struct DFA_state **dfaar;
171 {
172     struct DFA_state *s = dfaar[0];
173     struct 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 struct DFA_state **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);
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     struct DFA *dfa = dfa_init();
245
246     prog = *argv;
247     setbuf (stdout, outbuf);
248     i = agrep_options (argc, argv);
249     if (i)
250         return i;
251     while (--argc > 0)
252         if (**++argv != '-' && **argv)
253             if (!pattern)
254             {
255                 pattern = *argv;
256                 i = dfa_parse (dfa, &pattern);
257                 if (i || *pattern)
258                 {
259                     fprintf (stderr, "%s: illegal pattern\n", prog);
260                     return 1;
261                 }
262                 dfa_mkstate (dfa);
263             }
264             else
265             {
266                 ++no;
267                 fd = open (*argv, O_RDONLY | O_BINARY);
268                 if (fd == -1)
269                 {
270                     fprintf (stderr, "%s: couldn't open `%s'\n", prog, *argv);
271                     return 1;
272                 }
273                 i = agrep (dfa->states, fd);
274                 close (fd);
275                 if (i)
276                     return i;
277             }
278     if (!no)
279     {
280         fprintf (stderr, "usage:\n "
281                          " %s [-d] [-v] [-n] [-f] pattern file ..\n", prog);
282         return 2;
283     }
284     fflush(stdout);
285     dfa_delete (&dfa);
286     return 0;
287 }