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