1 /* This file is part of the Zebra server.
2 Copyright (C) 1994-2009 Index Data
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <idzebra/util.h>
28 #include <yaz/yaz-util.h>
33 static int show_line = 0;
35 typedef unsigned MatchWord;
39 int n; /* no of MatchWord needed */
40 int range; /* max no. of errors */
41 MatchWord *Sc; /* Mask Sc */
44 #define INFBUF_SIZE 16384
48 static INLINE void set_bit (MatchContext *mc, MatchWord *m, int ch, int state)
50 int off = state & (WORD_BITS-1);
51 int wno = state / WORD_BITS;
53 m[mc->n * ch + wno] |= 1<<off;
56 static INLINE void reset_bit (MatchContext *mc, MatchWord *m, int ch,
59 int off = state & (WORD_BITS-1);
60 int wno = state / WORD_BITS;
62 m[mc->n * ch + wno] &= ~(1<<off);
65 static INLINE MatchWord get_bit (MatchContext *mc, MatchWord *m, int ch,
68 int off = state & (WORD_BITS-1);
69 int wno = state / WORD_BITS;
71 return m[mc->n * ch + wno] & (1<<off);
74 static MatchContext *mk_MatchContext (struct DFA *dfa, int range)
76 MatchContext *mc = imalloc (sizeof(*mc));
79 mc->n = (dfa->no_states+WORD_BITS) / WORD_BITS;
81 mc->Sc = icalloc (sizeof(*mc->Sc) * 256 * mc->n);
83 for (i=0; i<dfa->no_states; i++)
86 struct DFA_state *state = dfa->states[i];
88 for (j=0; j<state->tran_no; j++)
91 int ch0 = state->trans[j].ch[0];
92 int ch1 = state->trans[j].ch[1];
93 assert (ch0 >= 0 && ch1 >= 0);
95 for (ch = ch0; ch <= ch1; ch++)
96 set_bit (mc, mc->Sc, ch, i);
103 static void mask_shift (MatchContext *mc, MatchWord *Rdst, MatchWord *Rsrc,
104 struct DFA *dfa, int ch)
107 MatchWord *Rsrc_p = Rsrc, mask;
110 for (j = 1; j<mc->n; j++)
115 for (j = 0; j<WORD_BITS/4; j++)
121 struct DFA_state *state = dfa->states[s];
122 int i = state->tran_no;
124 if (ch >= state->trans[i].ch[0] &&
125 ch <= state->trans[i].ch[1])
126 set_bit (mc, Rdst, 0, state->trans[i].to);
130 struct DFA_state *state = dfa->states[s+1];
131 int i = state->tran_no;
133 if (ch >= state->trans[i].ch[0] &&
134 ch <= state->trans[i].ch[1])
135 set_bit (mc, Rdst, 0, state->trans[i].to);
139 struct DFA_state *state = dfa->states[s+2];
140 int i = state->tran_no;
142 if (ch >= state->trans[i].ch[0] &&
143 ch <= state->trans[i].ch[1])
144 set_bit (mc, Rdst, 0, state->trans[i].to);
148 struct DFA_state *state = dfa->states[s+3];
149 int i = state->tran_no;
151 if (ch >= state->trans[i].ch[0] &&
152 ch <= state->trans[i].ch[1])
153 set_bit (mc, Rdst, 0, state->trans[i].to);
157 if (s >= dfa->no_states)
164 static void shift (MatchContext *mc, MatchWord *Rdst, MatchWord *Rsrc,
168 MatchWord *Rsrc_p = Rsrc, mask;
169 for (j = 0; j<mc->n; j++)
174 for (j = 0; j<WORD_BITS/4; j++)
180 struct DFA_state *state = dfa->states[s];
181 int i = state->tran_no;
183 set_bit (mc, Rdst, 0, state->trans[i].to);
187 struct DFA_state *state = dfa->states[s+1];
188 int i = state->tran_no;
190 set_bit (mc, Rdst, 0, state->trans[i].to);
194 struct DFA_state *state = dfa->states[s+2];
195 int i = state->tran_no;
197 set_bit (mc, Rdst, 0, state->trans[i].to);
201 struct DFA_state *state = dfa->states[s+3];
202 int i = state->tran_no;
204 set_bit (mc, Rdst, 0, state->trans[i].to);
208 if (s >= dfa->no_states)
215 static void or (MatchContext *mc, MatchWord *Rdst,
216 MatchWord *Rsrc1, MatchWord *Rsrc2)
219 for (i = 0; i<mc->n; i++)
220 Rdst[i] = Rsrc1[i] | Rsrc2[i];
224 static int go (MatchContext *mc, struct DFA *dfa, FILE *inf)
226 MatchWord *Rj, *Rj1, *Rj_a, *Rj_b, *Rj_c;
233 infbuf = imalloc (INFBUF_SIZE);
235 Rj = icalloc (mc->n * (mc->range+1) * sizeof(*Rj));
236 Rj1 = icalloc (mc->n * (mc->range+1) * sizeof(*Rj));
237 Rj_a = icalloc (mc->n * sizeof(*Rj));
238 Rj_b = icalloc (mc->n * sizeof(*Rj));
239 Rj_c = icalloc (mc->n * sizeof(*Rj));
241 set_bit (mc, Rj, 0, 0);
242 for (d = 1; d<=mc->range; d++)
245 memcpy (Rj + mc->n * d, Rj + mc->n * (d-1), mc->n * sizeof(*Rj));
246 for (s = 0; s<dfa->no_states; s++)
248 if (get_bit (mc, Rj, d-1, s))
250 struct DFA_state *state = dfa->states[s];
251 int i = state->tran_no;
253 set_bit (mc, Rj, d, state->trans[i].to);
257 while ((ch = getc (inf)) != EOF)
261 infbuf[inf_ptr] = ch;
268 printf ("%5d:", lineno);
273 } while (infbuf[i] != '\n');
276 if (++i == INFBUF_SIZE)
279 } while (infbuf[i] != '\n');
284 if (++inf_ptr == INFBUF_SIZE)
286 mask_shift (mc, Rj1, Rj, dfa, ch);
287 for (d = 1; d <= mc->range; d++)
289 mask_shift (mc, Rj_b, Rj+d*mc->n, dfa, ch); /* 1 */
291 or (mc, Rj_a, Rj+(d-1)*mc->n, Rj1+(d-1)*mc->n); /* 2,3 */
293 shift (mc, Rj_c, Rj_a, dfa);
295 or (mc, Rj_a, Rj_b, Rj_c); /* 1,2,3*/
297 or (mc, Rj1+d*mc->n, Rj_a, Rj+(d-1)*mc->n); /* 1,2,3,4 */
299 for (s = 0; s<dfa->no_states; s++)
301 if (dfa->states[s]->rule_no)
302 if (get_bit (mc, Rj1+mc->range*mc->n, 0, s))
305 for (d = 0; d <= mc->range; d++)
306 reset_bit (mc, Rj1+d*mc->n, 0, dfa->no_states);
320 static int grep_file (struct DFA *dfa, const char *fname, int range)
327 inf = fopen (fname, "r");
330 yaz_log (YLOG_FATAL|YLOG_ERRNO, "cannot open `%s'", fname);
337 mc = mk_MatchContext (dfa, range);
346 int main (int argc, char **argv)
351 const char *pattern = NULL;
353 struct DFA *dfa = dfa_init();
356 while ((ret = options ("nr:dsv:", argv, argc, &arg)) != -2)
364 i = dfa_parse (dfa, &pattern);
367 fprintf (stderr, "%s: illegal pattern\n", prog);
375 grep_file (dfa, arg, range);
380 yaz_log_init (yaz_log_mask_str(arg), prog, NULL);
389 debug_dfa_followpos = 1;
402 yaz_log (YLOG_FATAL, "Unknown option '-%s'", arg);
408 fprintf (stderr, "usage:\n "
409 " %s [-d] [-n] [-r n] [-s] [-v n] pattern file ..\n", prog);
412 else if (no_files == 0)
414 grep_file (dfa, NULL, range);
422 * c-file-style: "Stroustrup"
423 * indent-tabs-mode: nil
425 * vim: shiftwidth=4 tabstop=8 expandtab