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