RPA Toolkit
3923cf2217a2e7a71499dbf8bb91ac0f966c36be
[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 DFA states.\n");
95                 fprintf(stderr, "\t-N                       Dump NFA states.\n");
96                 fprintf(stderr, "\t-s                       Include substates.\n");
97                 fprintf(stderr, "\t-t                       Display statistics.\n");
98                 fprintf(stderr, "\t-v                       Display version information.\n");
99                 fprintf(stderr, "\t-h, --help               Display this help.\n");
100                 
101                 return 0;
102 }
103
104
105 int rexcc_buffer_realloc(rbuffer_t *buffer, unsigned long size)
106 {
107         char *s;
108
109         s = (char *)r_realloc(buffer->s, size);
110         if (!s)
111                 return -1;
112         buffer->s = s;
113         buffer->size = size;
114         return 0;
115
116 }
117
118
119 rbuffer_t *rexcc_buffer_loadfile(FILE *pFile)
120 {
121         unsigned long memchunk = 256;
122         long ret = 0, inputsize = 0;
123         rbuffer_t *buf;
124
125         buf = r_buffer_create(2 * memchunk);
126         if (!buf)
127                 return (void*)0;
128
129         do {
130                 if ((buf->size - inputsize) < memchunk) {
131                         if (rexcc_buffer_realloc(buf, buf->size + memchunk) < 0) {
132                                 fprintf(stderr, "Out of memory!\n");
133                                 exit(1);
134                         }
135                 }
136                 ret = (long)fread(&buf->s[inputsize], 1, memchunk - 1, pFile);
137                 if ((ret <= 0) && ferror(pFile)) {
138                         r_buffer_destroy(buf);
139                         return (void*)0;
140                 }
141                 inputsize += ret;
142                 buf->s[inputsize] = '\0';
143                 buf->size = inputsize;
144         } while (!feof(pFile));
145
146         return buf;
147 }
148
149
150 int main(int argc, const char *argv[])
151 {
152         int i, ret = 0, dumponly = 0;;
153         rexcc_t *pCC;
154         int withsubstates = 0;
155         FILE *devnull = NULL;
156         rexdb_t *tempdb = NULL;
157         FILE *cfile = stdout;
158         FILE *hfile = NULL;
159
160         pCC = rex_cc_create();
161         if (argc <= 1) {
162                 usage(argc, argv);
163                 goto end;
164         }
165         for (i = 1; i < argc; i++) {
166                 if (strcmp(argv[i], "-t") == 0) {
167                         pCC->showtime = 1;
168                 }
169         }
170         for (i = 1; i < argc; i++) {
171                 if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "/?") == 0 || strcmp(argv[i], "-h") == 0) {
172                         usage(argc, argv);
173                         goto end;
174                 }
175         }
176         for (i = 1; i < argc; i++) {
177                 if (strcmp(argv[i], "-v") == 0) {
178                         fprintf(stderr, "REXCC with REX library version: %s\n", rex_db_version());
179                         goto end;
180                 }
181         }
182         for (i = 1; i < argc; i++) {
183                 if (strcmp(argv[i], "-o") == 0) {
184                         if (++i < argc) {
185                                 cfile = fopen(argv[i], "wb");
186                                 if (!cfile) {
187                                         fprintf(stderr, "Failed to create file: %s, %s\n", argv[i], strerror(errno));
188                                         goto error;
189                                 }
190
191                         }
192                 }
193         }
194         for (i = 1; i < argc; i++) {
195                 if (strcmp(argv[i], "-s") == 0) {
196                         withsubstates = 1;
197                 }
198         }
199         for (i = 1; i < argc; i++) {
200                 if (strcmp(argv[i], "-D") == 0) {
201                         dumponly = 1;
202                 }
203         }
204         for (i = 1; i < argc; i++) {
205                 if (strcmp(argv[i], "-N") == 0) {
206                         dumponly = 2;
207                 }
208         }
209         for (i = 1; i < argc; i++) {
210                 if (argv[i][0] != '-') {
211                         rbuffer_t *text = rex_buffer_map_file(argv[i]);
212                         if (text) {
213                                 if (rex_cc_load_buffer(pCC, text) < 0) {
214                                         /*
215                                          * Error
216                                          */
217                                 }
218                                 if (pCC->startuid >= 0) {
219                                         tempdb = rex_db_createdfa(pCC->nfa, pCC->startuid);
220                                         pCC->dfa = rex_db_todfa(tempdb, withsubstates);
221                                         rex_db_destroy(tempdb);
222                                         if (pCC->dfa && !dumponly)
223                                                 rex_cc_output(pCC, cfile);
224                                 }
225                                 r_buffer_destroy(text);
226                         } else {
227                                 /*
228                                  * Error
229                                  */
230                         }
231                         break;
232                 } else if (argv[i][1] == 'o'){
233                         ++i;
234                 }
235         }
236         if (dumponly == 1) {
237                 for (i = 0; i < pCC->dfa->nstates; i++) {
238                         rex_dfa_dumpstate(pCC->dfa, i);
239                 }
240                 goto end;
241         } else if (dumponly == 2) {
242                 rexdb_t *db = pCC->nfa;
243                 for (i = 0; i < r_array_length(db->states); i++) {
244                         rex_db_dumpstate(db, i);
245                 }
246                 goto end;
247         }
248
249 end:
250         rex_cc_destroy(pCC);
251         if (pCC->showtime) {
252                 fprintf(stdout, "memory: %ld KB (leaked %ld Bytes)\n", (long)r_debug_get_maxmem()/1024, (long)r_debug_get_allocmem());
253         }
254         if (devnull)
255                 fclose(devnull);
256         if (cfile)
257                 fclose(cfile);
258         if (hfile)
259                 fclose(hfile);
260         return ret;
261
262 error:
263         if (devnull)
264                 fclose(devnull);
265         if (cfile)
266                 fclose(cfile);
267         if (hfile)
268                 fclose(hfile);
269         rex_cc_destroy(pCC);
270         return 2;
271 }