RPA Toolkit
Don't need to initialize 'inc'
[rpatk.git] / rexgrep / rexgrep.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 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 /*
28  * Temporary here. Need to fix the encoding definitions.
29  */
30 #include "rpa/rpastat.h"
31
32 #include "rlib/rutf.h"
33 #include "rlib/rmem.h"
34 #include "rex/rextransition.h"
35 #include "rex/rexdfasimulator.h"
36 #include "rexgrep.h"
37 #include "rexgrepdep.h"
38
39 #define MAX_STACK 256000
40
41
42
43 rexgrep_t *rex_grep_create()
44 {
45         rexgrep_t *pGrep;
46         
47         pGrep = (rexgrep_t *)r_malloc(sizeof(*pGrep));
48         if (!pGrep)
49                 return (void *)0;
50         r_memset(pGrep, 0, sizeof(*pGrep));
51         pGrep->nfa = rex_db_create(REXDB_TYPE_NFA);
52         pGrep->si = rex_nfasimulator_create();
53         pGrep->dfasi = rex_dfasimulator_create();
54         pGrep->ret = 1;
55         pGrep->startuid = -1L;
56         return pGrep;
57 }
58
59
60 void rex_grep_destroy(rexgrep_t *pGrep)
61 {
62         if (!pGrep)
63                 return;
64         rex_db_destroy(pGrep->nfa);
65         rex_dfa_destroy(pGrep->dfa);
66         rex_nfasimulator_destroy(pGrep->si);
67         rex_dfasimulator_destroy(pGrep->dfasi);
68         r_free(pGrep);
69 }
70
71
72 int rex_grep_load_string_pattern(rexgrep_t *pGrep, rbuffer_t *buf)
73 {
74         return rex_grep_load_pattern(pGrep, buf);
75 }
76
77
78 int rex_grep_load_pattern(rexgrep_t *pGrep, rbuffer_t *buf)
79 {
80         pGrep->startuid = rex_db_addexpression(pGrep->nfa, pGrep->startuid, buf->s, buf->size, 0);
81         if (pGrep->startuid < 0) {
82                 return -1;
83         }
84         return 0;
85 }
86
87
88 int rex_grep_match(rexgrep_t *pGrep, const char* input, const char *end)
89 {
90         int inc;
91         ruint32 wc;
92         rexdb_t *db;
93
94         if (pGrep->usedfa) {
95                 ruint32 wc = 0;
96                 int ret = 0;
97                 long nstate = REX_DFA_STARTSTATE;
98                 const char *start = input;
99                 rexdfa_t *dfa = pGrep->dfa;
100                 rexdfs_t *s;
101
102                 while ((inc = r_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)end)) > 0) {
103                         if ((nstate = REX_DFA_NEXT(dfa, nstate, wc)) <= 0)
104                                 break;
105                         input += inc;
106                         s = REX_DFA_STATE(dfa, nstate);
107                         if (s->type == REX_STATETYPE_ACCEPT)
108                                 ret = input - start;
109                 }
110                 return ret;
111         }
112
113         if (pGrep->startuid < 0) {
114                 return -1;
115         }
116         db = pGrep->nfa;
117
118         rex_nfasimulator_start(pGrep->si, db, pGrep->startuid);
119         while ((inc = r_utf8_mbtowc(&wc, (const unsigned char*)input, (const unsigned char*)end)) > 0) {
120                 if (rex_nfasimulator_next(pGrep->si, db, wc, inc) == 0)
121                         break;
122                 input += inc;
123         }
124         if (r_array_length(pGrep->si->accepts) > 0) {
125                 rex_accept_t *acc = (rex_accept_t *)r_array_lastslot(pGrep->si->accepts);
126                 return acc->inputsize;
127         }
128         return 0;
129 }
130
131
132 int rex_grep_scan(rexgrep_t *pGrep, const char* start, const char* end)
133 {
134         int ret = 0;
135
136         while (start < end) {
137                 ret = rex_grep_match(pGrep, start, end);
138                 if (ret < 0) {
139                         /*
140                          * Error
141                          */
142                         return -1;
143                 } else if (ret > 0) {
144                         if (pGrep->showfilename) {
145                                 fprintf(stdout, "%s:", (const char*)pGrep->filename);
146                         }
147                         fwrite(start, 1, ret, stdout);
148                         fprintf(stdout, "\n");
149                         start += ret;
150                 } else {
151                         ruint32 wc;
152                         if ((ret = r_utf8_mbtowc(&wc, (const unsigned char*)start, (const unsigned char*)end)) <= 0)
153                                 ret = 1;
154                         start += ret;
155                 }
156         }
157         return 0;
158 }
159
160
161 static int rex_grep_scan_do(rexgrep_t *pGrep, const char* start, const char* end)
162 {
163         int ret = 0;
164
165         while (start < end) {
166                 ret = rex_grep_match(pGrep, start, end);
167                 if (ret < 0) {
168                         /*
169                          * Error
170                          */
171                         return -1;
172                 } else if (ret > 0) {
173                         return ret;
174                 } else {
175                         ruint32 wc;
176                         if ((ret = r_utf8_mbtowc(&wc, (const unsigned char*)start, (const unsigned char*)end)) <= 0)
177                                 ret = 1;
178                         start += ret;
179                 }
180         }
181         return 0;
182 }
183
184
185 int rex_grep_scan_lines(rexgrep_t *pGrep, const char* start, const char* end)
186 {
187         int ret;
188         const char *eol;
189
190         for (eol = start; eol < end; eol++) {
191                 if (*eol == '\n' || (eol + 1) == end) {
192                         ret = rex_grep_scan_do(pGrep, start, eol + 1);
193                         if (ret > 0) {
194                                 if (pGrep->showfilename) {
195                                         fprintf(stdout, "%s:", (const char*)pGrep->filename);
196                                 }
197                                 fwrite(start, 1, eol + 1 - start, stdout);
198                         }
199                         start = eol + 1;
200                 }
201         }
202         rex_grep_output_utf8_string(pGrep, "\n");
203         return 0;
204 }
205
206
207 void rex_grep_scan_buffer(rexgrep_t *pGrep, rbuffer_t *buf)
208 {
209         switch (pGrep->greptype) {
210         case REX_GREPTYPE_SCANLINES:
211                 rex_grep_scan_lines(pGrep, buf->s, buf->s + buf->size);
212                 break;
213         case REX_GREPTYPE_MATCH:
214         case REX_GREPTYPE_SCAN:
215         default:
216                 rex_grep_scan(pGrep, buf->s, buf->s + buf->size);
217                 break;
218         };
219 }
220
221
222 void rex_grep_output(rexgrep_t *pGrep, const char *s, unsigned long size, unsigned int encoding)
223 {
224         const unsigned char *input = (const unsigned char*)s;
225         const unsigned char *end = input + size;
226         unsigned int wc;
227         int ret;
228
229         if (encoding == RPA_ENCODING_UTF16LE || encoding == RPA_ENCODING_ICASE_UTF16LE) {
230                 while ((ret = (int)r_utf16_mbtowc(&wc, input, end)) != 0) {
231                         rex_grep_output_char(wc);
232                         input += ret;
233                 }
234         } else {
235                 while ((ret = (int)r_utf8_mbtowc(&wc, input, end)) != 0) {
236                         rex_grep_output_char(wc);
237                         input += ret;
238                 }
239         }
240 }
241
242
243 void rex_grep_output_utf8_string(rexgrep_t *pGrep, const char *s)
244 {
245         rex_grep_output(pGrep, s, r_strlen(s), RPA_ENCODING_UTF8);
246 }
247
248
249 void rex_grep_output_utf16_string(rexgrep_t *pGrep, const unsigned short *s)
250 {
251         unsigned long size = 0;
252         const unsigned short *pstr = s;
253
254         while (*pstr) {
255                 size += sizeof(unsigned short);
256                 pstr += 1;
257         }
258         rex_grep_output(pGrep, (const char*)s, size, RPA_ENCODING_UTF16LE);
259 }