RPA Toolkit
Work on documentation.
[rpatk.git] / rexcc / unix / main.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 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <sys/mman.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <wchar.h>
31 #include <time.h>
32 #include <errno.h>
33 #include "rlib/rmem.h"
34 #include "rlib/rarray.h"
35 #include "rex/rexdfaconv.h"
36 #include "rex/rexdfa.h"
37 #include "rexcc.h"
38
39
40 void rex_buffer_unmap_file(rbuffer_t *buf)
41 {
42         if (buf) {
43                 munmap(buf->s, buf->size);
44                 r_free(buf);
45         }
46 }
47
48
49 rbuffer_t * rex_buffer_map_file(const char *filename)
50 {
51         struct stat st;
52         rbuffer_t *str;
53         char *buffer;
54
55         int fd = open(filename, O_RDONLY);
56         if (fd < 0) {
57                 return (void*)0;
58         }
59         if (fstat(fd, &st) < 0) {
60                 close(fd);
61                 return (void*)0;
62         }
63         buffer = (char*)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
64         if (buffer == (void*)-1) {
65                 close(fd);
66                 return (void*)0;
67         }
68         str = (rbuffer_t *)r_malloc(sizeof(rbuffer_t));
69         if (!str)
70                 goto error;
71         memset(str, 0, sizeof(*str));
72         str->s = buffer;
73         str->size = st.st_size;
74         str->userdata = (void*)((unsigned long)fd);
75         str->alt_destroy = rex_buffer_unmap_file;
76         close(fd);
77         return str;
78
79 error:
80         munmap(buffer, st.st_size);
81         close(fd);
82         return str;
83 }
84
85
86 int usage(int argc, const char *argv[])
87 {
88                 fprintf(stderr, "REX Code Compiler - using REX library version: %s \n", rex_db_version());
89                 fprintf(stderr, "Copyright (C) 2012 Martin Stoilov\n\n");
90
91                 fprintf(stderr, "Usage: \n %s [OPTIONS] <filename>\n", argv[0]);
92                 fprintf(stderr, " OPTIONS:\n");
93                 fprintf(stderr, "\t-o <cfile>               Output .c file.\n");
94                 fprintf(stderr, "\t-d                       Dump regular expressions.\n");
95                 fprintf(stderr, "\t-D                       Dump DFA states.\n");
96                 fprintf(stderr, "\t-N                       Dump NFA states.\n");
97                 fprintf(stderr, "\t-s                       Include substates.\n");
98                 fprintf(stderr, "\t-t                       Display statistics.\n");
99                 fprintf(stderr, "\t-v                       Display version information.\n");
100                 fprintf(stderr, "\t-h, --help               Display this help.\n");
101                 
102                 return 0;
103 }
104
105
106 int rexcc_buffer_realloc(rbuffer_t *buffer, unsigned long size)
107 {
108         char *s;
109
110         s = (char *)r_realloc(buffer->s, size);
111         if (!s)
112                 return -1;
113         buffer->s = s;
114         buffer->size = size;
115         return 0;
116
117 }
118
119
120 rbuffer_t *rexcc_buffer_loadfile(FILE *pFile)
121 {
122         unsigned long memchunk = 256;
123         long ret = 0, inputsize = 0;
124         rbuffer_t *buf;
125
126         buf = r_buffer_create(2 * memchunk);
127         if (!buf)
128                 return (void*)0;
129
130         do {
131                 if ((buf->size - inputsize) < memchunk) {
132                         if (rexcc_buffer_realloc(buf, buf->size + memchunk) < 0) {
133                                 fprintf(stderr, "Out of memory!\n");
134                                 exit(1);
135                         }
136                 }
137                 ret = (long)fread(&buf->s[inputsize], 1, memchunk - 1, pFile);
138                 if ((ret <= 0) && ferror(pFile)) {
139                         r_buffer_destroy(buf);
140                         return (void*)0;
141                 }
142                 inputsize += ret;
143                 buf->s[inputsize] = '\0';
144                 buf->size = inputsize;
145         } while (!feof(pFile));
146
147         return buf;
148 }
149
150
151 int main(int argc, const char *argv[])
152 {
153         int i, ret = 0, dumponly = 0;;
154         rexcc_t *pCC;
155         int withsubstates = 0;
156         FILE *devnull = NULL;
157         rexdb_t *tempdb = NULL;
158         FILE *cfile = stdout;
159         FILE *hfile = NULL;
160
161         pCC = rex_cc_create();
162         if (argc <= 1) {
163                 usage(argc, argv);
164                 goto end;
165         }
166         for (i = 1; i < argc; i++) {
167                 if (strcmp(argv[i], "-t") == 0) {
168                         pCC->showtime = 1;
169                 }
170         }
171         for (i = 1; i < argc; i++) {
172                 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "/?") == 0 || strcmp(argv[i], "-h") == 0) {
173                         usage(argc, argv);
174                         goto end;
175                 }
176         }
177         for (i = 1; i < argc; i++) {
178                 if (strcmp(argv[i], "-v") == 0) {
179                         fprintf(stderr, "REXCC with REX library version: %s\n", rex_db_version());
180                         goto end;
181                 }
182         }
183         for (i = 1; i < argc; i++) {
184                 if (strcmp(argv[i], "-o") == 0) {
185                         if (++i < argc) {
186                                 cfile = fopen(argv[i], "wb");
187                                 if (!cfile) {
188                                         fprintf(stderr, "Failed to create file: %s, %s\n", argv[i], strerror(errno));
189                                         goto error;
190                                 }
191
192                         }
193                 }
194         }
195         for (i = 1; i < argc; i++) {
196                 if (strcmp(argv[i], "-s") == 0) {
197                         withsubstates = 1;
198                 }
199         }
200         for (i = 1; i < argc; i++) {
201                 if (strcmp(argv[i], "-D") == 0) {
202                         dumponly = 1;
203                 }
204         }
205         for (i = 1; i < argc; i++) {
206                 if (strcmp(argv[i], "-N") == 0) {
207                         dumponly = 2;
208                 }
209         }
210         for (i = 1; i < argc; i++) {
211                 if (strcmp(argv[i], "-d") == 0) {
212                         dumponly = 3;
213                 }
214         }
215         for (i = 1; i < argc; i++) {
216                 if (argv[i][0] != '-') {
217                         rbuffer_t *text = rex_buffer_map_file(argv[i]);
218                         if (text) {
219                                 if (rex_cc_load_buffer(pCC, text) < 0) {
220                                         /*
221                                          * Error
222                                          */
223                                 }
224                                 if (pCC->startuid >= 0) {
225                                         tempdb = rex_db_createdfa(pCC->nfa, pCC->startuid);
226                                         pCC->dfa = rex_db_todfa(tempdb, withsubstates);
227                                         rex_db_destroy(tempdb);
228                                         if (pCC->dfa && !dumponly)
229                                                 rex_cc_output(pCC, cfile);
230                                         if (dumponly == 3) {
231                                                 rex_cc_parseinfodump(pCC);
232                                         }
233                                 }
234                                 r_buffer_destroy(text);
235                         } else {
236                                 /*
237                                  * Error
238                                  */
239                         }
240                         break;
241                 } else if (argv[i][1] == 'o'){
242                         ++i;
243                 }
244         }
245         if (dumponly == 1) {
246                 for (i = 0; i < pCC->dfa->nstates; i++) {
247                         rex_dfa_dumpstate(pCC->dfa, i);
248                 }
249                 goto end;
250         } else if (dumponly == 2) {
251                 rexdb_t *db = pCC->nfa;
252                 for (i = 0; i < r_array_length(db->states); i++) {
253                         rex_db_dumpstate(db, i);
254                 }
255                 goto end;
256         }
257
258 end:
259         rex_cc_destroy(pCC);
260         if (pCC->showtime) {
261                 fprintf(stdout, "memory: %ld KB (leaked %ld Bytes)\n", (long)r_debug_get_maxmem()/1024, (long)r_debug_get_allocmem());
262         }
263         if (devnull)
264                 fclose(devnull);
265         if (cfile)
266                 fclose(cfile);
267         if (hfile)
268                 fclose(hfile);
269         return ret;
270
271 error:
272         if (devnull)
273                 fclose(devnull);
274         if (cfile)
275                 fclose(cfile);
276         if (hfile)
277                 fclose(hfile);
278         rex_cc_destroy(pCC);
279         return 2;
280 }