6af8a198bb991d035f9cf0b06739e764802da4f7
[litex.git] / litex / build / sim / core / parse.c
1 /* Copyright (C) 2017 LambdaConcept */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <json-c/json.h>
7 #include "error.h"
8 #include "modules.h"
9
10 static int file_to_js(char *filename, json_object **obj)
11 {
12 int ret = RC_OK;
13 struct json_tokener *tok=NULL;
14 json_object *pobj=NULL;
15 enum json_tokener_error jerr;
16 FILE *in=NULL;
17 int linenum=0;
18 char *lineptr=NULL;
19 size_t len, len2;
20
21 if(!filename || !obj)
22 {
23 ret=RC_INVARG;
24 goto out;
25 }
26
27 in = fopen(filename, "r");
28 if(!in)
29 {
30 eprintf("Can't open configuration file: %s\n", filename);
31 ret= RC_ERROR;
32 goto out;
33 }
34
35 tok = json_tokener_new();
36 if(!tok)
37 {
38 ret=RC_ERROR;
39 eprintf("Can't create new tokener\n");
40 goto out;
41 }
42
43 do
44 {
45 linenum++;
46 len=32768;
47 len2 = getline(&lineptr, &len, in);
48 if(len2 == -1)
49 {
50 ret=RC_ERROR;
51 eprintf("End of file !\n");
52 goto out;
53 }
54 pobj = json_tokener_parse_ex(tok, lineptr, len2);
55 if((jerr = json_tokener_get_error(tok)) == json_tokener_success)
56 {
57 break;
58 }
59
60 if((jerr = json_tokener_get_error(tok)) != json_tokener_continue)
61 {
62 fprintf(stderr, "ERROR in %s:\n", filename);
63 fprintf(stderr, "line:%d:\n%s",linenum, lineptr);
64 jerr = json_tokener_get_error(tok);
65 fprintf(stderr, "json parse error: %s\n", json_tokener_error_desc(jerr));
66 goto out;
67 }
68 free(lineptr);
69 lineptr=NULL;
70 }while(1);
71
72 *obj=pobj;
73 pobj=NULL;
74 out:
75
76 if(pobj)
77 {
78 json_object_put(pobj);
79 }
80 if(tok)
81 {
82 json_tokener_free(tok);
83 }
84 if(lineptr)
85 {
86 free(lineptr);
87 }
88 if(in)
89 {
90 fclose(in);
91 }
92 return ret;
93 }
94
95 static int json_to_interface_list(json_object *interface, struct interface_s **iface)
96 {
97 int ret=RC_OK;
98 int n, i;
99 json_object *obj;
100 json_object *name;
101 json_object *index;
102
103 struct interface_s *t_iface=NULL;
104
105 if(!interface || !iface)
106 {
107 ret = RC_INVARG;
108 eprintf("Invalid argument\n");
109 goto out;
110 }
111
112 if(!json_object_is_type(interface, json_type_array))
113 {
114 ret=RC_JSERROR;
115 eprintf("Interface must be an array\n");
116 goto out;
117 }
118
119 n = json_object_array_length(interface);
120 t_iface = (struct interface_s *)malloc(sizeof(struct interface_s) * (n + 1));
121 if(!t_iface)
122 {
123 ret= RC_NOENMEM;
124 eprintf("Not enough memory\n");
125 goto out;
126 }
127 memset(t_iface, 0,sizeof(struct interface_s) * (n + 1));
128
129 for(i = 0; i < n; i++)
130 {
131 obj = json_object_array_get_idx(interface, i);
132 if(json_object_is_type(obj, json_type_object))
133 {
134 if(!json_object_object_get_ex(obj, "name", &name))
135 {
136 ret=RC_JSERROR;
137 eprintf("Module interface must have a name (%s)!\n", json_object_to_json_string(obj));
138 goto out;
139 }
140 t_iface[i].name = strdup(json_object_get_string(name));
141
142 if(json_object_object_get_ex(obj, "index", &index))
143 {
144 if(!json_object_is_type(index, json_type_int))
145 {
146 ret = RC_JSERROR;
147 eprintf("Interface Index must be an int ! (%s)\n", json_object_to_json_string(obj));
148 }
149 t_iface[i].index = json_object_get_int(index);
150 }
151 }
152 if(json_object_is_type(obj, json_type_string))
153 {
154 t_iface[i].name = strdup(json_object_get_string(obj));
155 }
156 }
157 *iface = t_iface;
158 t_iface = NULL;
159 out:
160 if(t_iface)
161 {
162 free(t_iface);
163 }
164 return ret;
165 }
166
167 static int module_list_free(struct module_s *mod)
168 {
169 int ret=RC_OK;
170 struct module_s *mnext;
171 int i;
172 while(mod)
173 {
174 mnext = mod->next;
175 if(mod->iface)
176 {
177 for(i = 0; i < mod->niface; i++)
178 {
179 if(mod->iface[i].name)
180 {
181 free(mod->iface[i].name);
182 }
183 }
184 free(mod->iface);
185 if(mod->name)
186 {
187 free(mod->name);
188 }
189 if(mod->args)
190 {
191 free(mod->args);
192 }
193 }
194 free(mod);
195 mod = mnext;
196 }
197 return ret;
198 }
199
200 static int json_to_module_list(json_object *obj, struct module_s **mod)
201 {
202 struct module_s *m=NULL;
203 struct module_s *first=NULL;
204
205 json_object *tobj;
206 int ret=RC_OK;
207 int i, n, len;
208 json_object *name;
209 json_object *args;
210 json_object *interface;
211 json_object *tickfirst;
212
213 if(!obj || !mod)
214 {
215 ret = RC_INVARG;
216 eprintf("Wrong arguments\n");
217 goto out;
218 }
219
220 if(!json_object_is_type(obj, json_type_array))
221 {
222 ret=RC_JSERROR;
223 eprintf("Config file must be an array\n");
224 goto out;
225 }
226
227 n = json_object_array_length(obj);
228 for(i = 0; i < n; i++)
229 {
230 tobj = json_object_array_get_idx(obj, i);
231 if(!json_object_object_get_ex(tobj, "module", &name))
232 {
233 ret=RC_JSERROR;
234 eprintf("expected \"module\" in object (%s)\n", json_object_to_json_string(tobj));
235 goto out;
236 }
237
238 if(!json_object_object_get_ex(tobj, "interface", &interface))
239 {
240 ret=RC_JSERROR;
241 eprintf("expected \"interface\" in object (%s)\n", json_object_to_json_string(tobj));
242 goto out;
243 }
244
245 args = NULL;
246 json_object_object_get_ex(tobj, "args", &args);
247
248 tickfirst=NULL;
249 json_object_object_get_ex(tobj, "tickfirst", &tickfirst);
250
251
252 if(m)
253 {
254 m->next=(struct module_s *)malloc(sizeof(struct module_s));
255 m=m->next;
256 }
257 else
258 {
259 m=(struct module_s *)malloc(sizeof(struct module_s));
260 }
261 if(!m)
262 {
263 ret = RC_NOENMEM;
264 eprintf("Not enough memory\n");
265 goto out;
266 }
267 if(!first)
268 {
269 first = m;
270 }
271 memset(m, 0, sizeof(struct module_s));
272 ret = json_to_interface_list(interface, &m->iface);
273 if(RC_OK != ret)
274 {
275 goto out;
276 }
277 len = 0;
278
279 while(m->iface[len++].name);
280 m->niface= len-1;
281 m->name = strdup(json_object_get_string(name));
282 if(args)
283 {
284 m->args = strdup(json_object_to_json_string(args));
285 }
286 if(tickfirst)
287 {
288 m->tickfirst = json_object_get_boolean(tickfirst);
289 }
290 }
291 *mod = first;
292 first=NULL;
293
294 out:
295 if(first)
296 {
297 module_list_free(first);
298 }
299 return ret;
300 }
301
302 int litex_sim_file_to_module_list(char *filename, struct module_s **mod)
303 {
304 struct module_s *m=NULL;
305 json_object *obj=NULL;
306 int ret=RC_OK;
307
308 if(!filename || !mod)
309 {
310 ret = RC_INVARG;
311 eprintf("Invalid argument\n");
312 goto out;
313 }
314
315 ret = file_to_js(filename, &obj);
316 if(RC_OK != ret)
317 {
318 goto out;
319 }
320
321 ret = json_to_module_list(obj, &m);
322 if(RC_OK != ret)
323 {
324 goto out;
325 }
326
327 *mod = m;
328 m = NULL;
329 out:
330 if(m)
331 {
332 module_list_free(m);
333 }
334 if(obj)
335 {
336 json_object_put(obj);
337 }
338 return ret;
339 }