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