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