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