1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB and Kjell Winblad 2019. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 /*
22 * Author: Kjell Winblad
23 */
24
25
26 #include "ycf_utils.h"
27 #include "ycf_yield_fun.h"
28 #include "ycf_node.h"
29 #include "lib/simple_c_gc/simple_c_gc.h"
30
31 #include <stdlib.h>
32 #include <stdio.h>
33
34
file_to_str(const char * filename)35 char* file_to_str(const char* filename) {
36 char * buffer;
37 long length;
38 FILE * f = fopen (filename, "rb");
39
40 if (f) {
41 fseek (f, 0, SEEK_END);
42 length = ftell (f);
43 fseek (f, 0, SEEK_SET);
44 buffer = ycf_malloc (length+1);
45 size_t nr_of_read_bytes =
46 fread (buffer, 1, length, f);
47 if (nr_of_read_bytes != length) {
48 printf("error: while reading file %s\n", filename);
49 exit (1);
50 }
51 fclose (f);
52 buffer[length] = 0;
53 } else {
54 printf("error: could not open file %s\n", filename);
55 exit(1);
56 }
57
58 return buffer;
59 }
60
str_to_file(const char * filepath,const char * data)61 void str_to_file(const char *filepath, const char *data)
62 {
63 FILE *fp = fopen(filepath, "w");
64 if (fp != NULL)
65 {
66 fputs(data, fp);
67 fclose(fp);
68 }
69 }
70
parse_and_repeat_src_from_ast(const char * file_name)71 void parse_and_repeat_src_from_ast(const char* file_name){
72 char* content = file_to_str(file_name);
73 ycf_node* tree = ycf_node_from_string(content);
74 ycf_node_print(tree, NULL);
75 }
76
parse_and_print_symbols(const char * file_name)77 void parse_and_print_symbols(const char* file_name){
78 char* content = file_to_str(file_name);
79 ycf_symbol_list_print(content);
80 }
81
parse_and_print_ast(const char * file_name)82 void parse_and_print_ast(const char* file_name){
83 char* content = file_to_str(file_name);
84 ycf_node* tree = ycf_node_from_string(content);
85 print_abstract_syntax_tree(tree);
86 }
87
print_help_text_and_exit(char * program_name,int error_code)88 void print_help_text_and_exit(char* program_name, int error_code) {
89 printf("Usage: %s [-h]\n"
90 " %s [-use_gc [-print_gc_info]]\n"
91 " [-log_max_mem_usage log_file]\n"
92 " [(( -f | -frec | -fnoauto | -fextenal) function_name)...\n"
93 " [-output_file_name output_file]\n"
94 " [-header_file_name header_file]\n"
95 " [-debug]\n"
96 " [-only_yielding_funs]\n"
97 " [-static_aux_funs]\n"
98 " input_c_file]]\n"
99 "\n"
100 "Please see the README.md file for more details.\n",
101 program_name,
102 program_name);
103 exit(0);
104 }
105
ycf_main(int argc,char * argv[])106 int ycf_main( int argc, char* argv[] )
107 {
108 int i = 1;
109 for(i = 1; i < argc; i++ ){
110 bool repeat = ycf_string_is_equal("-repeat", argv[i]);
111 bool print_symbols = ycf_string_is_equal("-print_symbols", argv[i]);
112 bool print_ast = ycf_string_is_equal("-print_ast", argv[i]);;
113 bool yield = ycf_string_is_equal("-yield", argv[i]);
114 if(repeat || print_symbols || print_ast || yield){
115 i++;
116 if(i >= argc){
117 printf("ERROR: Expected at least one more argument\n\n");
118 print_help_text_and_exit(argv[0], 1);
119 }
120 }
121 if (print_ast) {
122 parse_and_print_ast(argv[i]);
123 } else if (repeat) {
124 parse_and_repeat_src_from_ast(argv[i]);
125 } else if (print_symbols) {
126 parse_and_print_symbols(argv[i]);
127 } else /* Default is yield */ {
128 ycf_string_item_list funs_to_yield = ycf_string_item_list_empty();
129 ycf_string_item_list funs_to_yield_no_auto = ycf_string_item_list_empty();
130 ycf_string_item_list funs_to_yield_frec = ycf_string_item_list_empty();
131 ycf_string_item_list funs_to_yield_external = ycf_string_item_list_empty();
132 ycf_string_item_list all_yield_funs = ycf_string_item_list_empty();
133 char* header_file_name = NULL;
134 char* output_file_name = NULL;
135 bool debug = false;
136 bool only_yielding_funs = false;
137 bool static_aux_funs = false;
138 while(i < argc && (ycf_string_is_equal(argv[i], "-f") ||
139 ycf_string_is_equal(argv[i], "-frec") ||
140 ycf_string_is_equal(argv[i], "-fnoauto") ||
141 ycf_string_is_equal(argv[i], "-fexternal") ||
142 ycf_string_is_equal(argv[i], "-header_file_name") ||
143 ycf_string_is_equal(argv[i], "-output_file_name") ||
144 ycf_string_is_equal(argv[i], "-debug") ||
145 ycf_string_is_equal(argv[i], "-only_yielding_funs") ||
146 ycf_string_is_equal(argv[i], "-static_aux_funs"))){
147 bool frec = ycf_string_is_equal(argv[i], "-frec");
148 bool noauto = ycf_string_is_equal(argv[i], "-fnoauto");
149 bool external = ycf_string_is_equal(argv[i], "-fexternal");
150 bool header = ycf_string_is_equal(argv[i], "-header_file_name");
151 bool output = ycf_string_is_equal(argv[i], "-output_file_name");
152 i++;
153 if(ycf_string_is_equal(argv[i-1], "-debug")){
154 debug = true;
155 continue;
156 }
157 if(ycf_string_is_equal(argv[i-1], "-only_yielding_funs")){
158 only_yielding_funs = true;
159 continue;
160 }
161 if(ycf_string_is_equal(argv[i-1], "-static_aux_funs")){
162 static_aux_funs = true;
163 continue;
164 }
165 if(i >= argc){
166 fprintf(stderr, "ERROR: Expected a name after %s\n\n", argv[i-1]);
167 print_help_text_and_exit(argv[0], 1);
168 }
169 if(header){
170 if(header_file_name != NULL){
171 fprintf(stderr, "ERROR: Can only print a single header file\n\n");
172 print_help_text_and_exit(argv[0], 1);
173 }
174 header_file_name = (char*)argv[i];
175 } else if(output){
176 if(output_file_name != NULL){
177 fprintf(stderr, "ERROR: Can only print a single output file\n\n");
178 print_help_text_and_exit(argv[0], 1);
179 }
180 output_file_name = (char*)argv[i];
181 } else if(external){
182 ycf_string_item_list_append(&funs_to_yield_external, ycf_string_item_new((char *) argv[i]));
183 } else if(frec){
184 ycf_string_item_list_append(&funs_to_yield_frec, ycf_string_item_new((char *) argv[i]));
185 } else if(noauto){
186 ycf_string_item_list_append(&funs_to_yield_no_auto, ycf_string_item_new((char *) argv[i]));
187 } else{
188 ycf_string_item_list_append(&funs_to_yield, ycf_string_item_new((char *) argv[i]));
189 }
190 i++;
191 }
192 ycf_string_item_list funs_to_yield_copy = ycf_string_item_list_shallow_copy(funs_to_yield);
193 ycf_string_item_list funs_to_yield_no_auto_copy = ycf_string_item_list_shallow_copy(funs_to_yield_no_auto);
194 ycf_string_item_list funs_to_yield_frec_copy = ycf_string_item_list_shallow_copy(funs_to_yield_frec);
195 ycf_string_item_list funs_to_yield_external_copy = ycf_string_item_list_shallow_copy(funs_to_yield_external);
196 ycf_string_item_list_concat(&all_yield_funs, &funs_to_yield_copy);
197 ycf_string_item_list_concat(&all_yield_funs, &funs_to_yield_no_auto_copy);
198 ycf_string_item_list_concat(&all_yield_funs, &funs_to_yield_frec_copy);
199 ycf_string_item_list_concat(&all_yield_funs, &funs_to_yield_external_copy);
200 if(funs_to_yield.head == NULL && funs_to_yield_no_auto.head == NULL && funs_to_yield_frec.head == NULL){
201 fprintf(stderr, "ERROR: Expected at least one \"(-f|-frec|-fnoauto) function_name\" argument\n\n");
202 print_help_text_and_exit(argv[0], 1);
203 }
204 if(i >= argc){
205 fprintf(stderr, "ERROR: Expected an input file name as the last parameter\n\n");
206 print_help_text_and_exit(argv[0], 1);
207 }
208 {
209 char* file_name = (char*)argv[i];
210 char* src = file_to_str(file_name);
211 ycf_string_item* current_fun = funs_to_yield.head;
212 ycf_node* header_file = ycf_node_from_string("");
213 ycf_node* tree = ycf_node_from_string(src);
214 ycf_node* only_yielding_funs_tree = NULL;
215 while(current_fun != NULL){
216 tree = ast_get_ast_with_yieldified_function(tree,
217 header_file,
218 current_fun->str,
219 &all_yield_funs,
220 true,
221 false,
222 debug,
223 only_yielding_funs,
224 &only_yielding_funs_tree,
225 static_aux_funs);
226 current_fun = current_fun->next;
227 }
228 current_fun = funs_to_yield_no_auto.head;
229 while(current_fun != NULL){
230 tree = ast_get_ast_with_yieldified_function(tree,
231 header_file,
232 current_fun->str,
233 &all_yield_funs,
234 false,
235 false,
236 debug,
237 only_yielding_funs,
238 &only_yielding_funs_tree,
239 static_aux_funs);
240 current_fun = current_fun->next;
241 }
242 current_fun = funs_to_yield_frec.head;
243 while(current_fun != NULL){
244 tree = ast_get_ast_with_yieldified_function(tree,
245 header_file,
246 current_fun->str,
247 &all_yield_funs,
248 true,
249 true,
250 debug,
251 only_yielding_funs,
252 &only_yielding_funs_tree,
253 static_aux_funs);
254 current_fun = current_fun->next;
255 }
256 ast_add_yield_code_generated_define(tree, debug);
257 ast_add_yield_code_generated_define(header_file, debug);
258 if(only_yielding_funs){
259 ast_add_yield_code_generated_define(only_yielding_funs_tree, debug);
260 }
261 if(header_file_name != NULL){
262 ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
263 ycf_node_print(header_file, b);
264 str_to_file(header_file_name, b->buffer);
265 }
266 if(only_yielding_funs){
267 tree = only_yielding_funs_tree;
268 }
269 if(output_file_name != NULL){
270 ycf_string_printable_buffer* b = ycf_string_printable_buffer_new();
271 ycf_node_print(tree, b);
272 str_to_file(output_file_name, b->buffer);
273 } else {
274 ycf_node_print(tree, NULL);
275 }
276 }
277 }
278 }
279 return 0;
280 }
281
is_help_option(char * string)282 bool is_help_option(char* string) {
283 return
284 ycf_string_is_equal("-h", string) ||
285 ycf_string_is_equal("--h", string) ||
286 ycf_string_is_equal("-help", string) ||
287 ycf_string_is_equal("--help", string);
288 }
289
main(int argc,char * argv[])290 int main( int argc, char* argv[] )
291 {
292 bool log_max_mem_usage = false;
293 bool use_gc = false;
294 char * log_max_mem_usage_file = NULL;
295 int i = 1;
296 if (argc == 1) {
297 print_help_text_and_exit(argv[0], 0);
298 }
299 while(i < argc &&
300 (ycf_string_is_equal("-use_gc", argv[i]) ||
301 ycf_string_is_equal("-log_max_mem_usage", argv[i]) ||
302 ycf_string_is_equal("-print_gc_info", argv[i]) ||
303 is_help_option(argv[i]))) {
304 if (is_help_option(argv[i])) {
305 print_help_text_and_exit(argv[0], 0);
306 } else if (ycf_string_is_equal("-use_gc", argv[i])) {
307 use_gc = true;
308 i++;
309 } else if(ycf_string_is_equal("-print_gc_info", argv[i])) {
310 scgc_enable_print_gc_info();
311 i++;
312 } else if(ycf_string_is_equal(argv[i], "-log_max_mem_usage")) {
313 ycf_enable_memory_tracking();
314 log_max_mem_usage = true;
315 i++;
316 log_max_mem_usage_file = (char*)argv[i];
317 i++;
318 }
319 }
320 int nr_of_params_to_remove = i - 1;
321 int ret;
322 if (!use_gc) {
323 ret = ycf_main(argc - nr_of_params_to_remove ,
324 argv + nr_of_params_to_remove);
325 } else {
326 ycf_enable_gc();
327 ret = scgc_start_gced_code(ycf_main,
328 argc - nr_of_params_to_remove,
329 argv + nr_of_params_to_remove,
330 ycf_raw_malloc,
331 ycf_free);
332 }
333 if(log_max_mem_usage){
334 ycf_malloc_log(log_max_mem_usage_file, "all");
335 }
336 return ret;
337 }
338