RPA Toolkit
Fixed rexgrep search in lines.
[rpatk.git] / rexgrep / rexgrep.c
1 /*
2  *  Regular Pattern Analyzer Toolkit (RPA/Tk)
3  *  Copyright (c) 2009-2012 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26
27 #include "rlib/rutf.h"
28 #include "rlib/rmem.h"
29 #include "rex/rextransition.h"
30 #include "rex/rexdfasimulator.h"
31 #include "rexgrep.h"
32 #include "rexgrepdep.h"
33
34 #define MAX_STACK 256000
35
36
37 rexgrep_t *rex_grep_create()
38 {
39         rexgrep_t *pGrep;
40         
41         pGrep = (rexgrep_t *)r_malloc(sizeof(*pGrep));
42         if (!pGrep)
43                 return (void *)0;
44         r_memset(pGrep, 0, sizeof(*pGrep));
45         pGrep->nfa = rex_db_create(REXDB_TYPE_NFA);
46         pGrep->si = rex_nfasimulator_create();
47         pGrep->dfasi = rex_dfasimulator_create();
48         pGrep->ret = 1;
49         pGrep->startuid = 0UL;
50         return pGrep;
51 }
52
53
54 void rex_grep_destroy(rexgrep_t *pGrep)
55 {
56         if (!pGrep)
57                 return;
58         rex_db_destroy(pGrep->nfa);
59         rex_dfa_destroy(pGrep->dfa);
60         rex_nfasimulator_destroy(pGrep->si);
61         rex_dfasimulator_destroy(pGrep->dfasi);
62         r_free(pGrep);
63 }
64
65
66 int rex_grep_load_string_pattern(rexgrep_t *pGrep, rbuffer_t *buf)
67 {
68         return rex_grep_load_pattern(pGrep, buf);
69 }
70
71
72 int rex_grep_load_pattern(rexgrep_t *pGrep, rbuffer_t *buf)
73 {
74         pGrep->startuid = rex_db_addexpression(pGrep->nfa, pGrep->startuid, buf->s, buf->size, 0);
75         if (pGrep->startuid < 0) {
76                 return -1;
77         }
78         return 0;
79 }
80
81
82 int rex_grep_match(rexgrep_t *pGrep, const char* input, const char *end)
83 {
84         int inc;
85         ruint32 wc;
86         rexdb_t *db;
87
88         if (pGrep->usedfa) {
89                 ruint32 wc = 0;
90                 int ret = 0;
91                 long nstate = REX_DFA_STARTSTATE;
92                 const char *start = input;
93                 rexdfa_t *dfa = pGrep->dfa;
94                 rexdfs_t *s;
95
96                 while ((inc = r_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)end)) > 0) {
97                         REX_DFA_NEXT(dfa, nstate, wc, &nstate);
98                         if (nstate == 0)
99                                 break;
100                         input += inc;
101                         s = REX_DFA_STATE(dfa, nstate);
102                         if (s->type == REX_STATETYPE_ACCEPT)
103                                 ret = (int)(input - start);
104                 }
105                 return ret;
106         }
107
108         if (pGrep->startuid < 0) {
109                 return -1;
110         }
111         db = pGrep->nfa;
112
113         rex_nfasimulator_start(pGrep->si, db, pGrep->startuid);
114         while ((inc = r_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)end)) > 0) {
115                 if (rex_nfasimulator_next(pGrep->si, db, wc, inc) == 0)
116                         break;
117                 input += inc;
118         }
119         if (r_array_length(pGrep->si->accepts) > 0) {
120                 rex_accept_t *acc = (rex_accept_t *)r_array_lastslot(pGrep->si->accepts);
121                 return acc->inputsize;
122         }
123         return 0;
124 }
125
126
127 int rex_grep_scan(rexgrep_t *pGrep, const char* start, const char* end)
128 {
129         int ret = 0;
130
131         while (start < end) {
132                 ret = rex_grep_match(pGrep, start, end);
133                 if (ret < 0) {
134                         /*
135                          * Error
136                          */
137                         return -1;
138                 } else if (ret > 0) {
139                         if (pGrep->showfilename) {
140                                 fprintf(stdout, "%s:", (const char*)pGrep->filename);
141                         }
142                         fwrite(start, 1, ret, stdout);
143                         fprintf(stdout, "\n");
144                         start += ret;
145                 } else {
146                         ruint32 wc;
147                         if ((ret = r_utf8_mbtowc(&wc, (const unsigned char*)start, (const unsigned char*)end)) <= 0)
148                                 ret = 1;
149                         start += ret;
150                 }
151         }
152         return 0;
153 }
154
155
156 static int rex_grep_scan_do(rexgrep_t *pGrep, const char* start, const char* end)
157 {
158         int ret = 0;
159
160         while (start < end) {
161                 ret = rex_grep_match(pGrep, start, end);
162                 if (ret < 0) {
163                         /*
164                          * Error
165                          */
166                         return -1;
167                 } else if (ret > 0) {
168                         return ret;
169                 } else {
170                         ruint32 wc;
171                         if ((ret = r_utf8_mbtowc(&wc, (const unsigned char*)start, (const unsigned char*)end)) <= 0)
172                                 ret = 1;
173                         start += ret;
174                 }
175         }
176         return 0;
177 }
178
179
180 int rex_grep_scan_lines(rexgrep_t *pGrep, const char* start, const char* end)
181 {
182         int ret;
183         const char *eol;
184
185         for (eol = start; eol < end; eol++) {
186                 if (*eol == '\n' || (eol + 1) == end) {
187                         ret = rex_grep_scan_do(pGrep, start, eol + 1);
188                         if (ret > 0) {
189                                 if (pGrep->showfilename) {
190                                         fprintf(stdout, "%s:", (const char*)pGrep->filename);
191                                 }
192                                 fwrite(start, 1, eol + 1 - start, stdout);
193                                 if ((eol + 1) == end)
194                                         fprintf(stdout, "\n");
195                         }
196                         start = eol + 1;
197                 }
198         }
199         return 0;
200 }
201
202
203 void rex_grep_scan_buffer(rexgrep_t *pGrep, rbuffer_t *buf)
204 {
205         switch (pGrep->greptype) {
206         case REX_GREPTYPE_SCANLINES:
207                 rex_grep_scan_lines(pGrep, buf->s, buf->s + buf->size);
208                 break;
209         case REX_GREPTYPE_MATCH:
210         case REX_GREPTYPE_SCAN:
211         default:
212                 rex_grep_scan(pGrep, buf->s, buf->s + buf->size);
213                 break;
214         };
215 }
216
217
218 void rex_grep_output(rexgrep_t *pGrep, const char *s, unsigned long size, unsigned int encoding)
219 {
220         fwrite(s, 1, size, stdout);
221 }
222
223
224 void rex_grep_output_utf8_string(rexgrep_t *pGrep, const char *s)
225 {
226         rex_grep_output(pGrep, s, r_strlen(s), 0);
227 }
228