Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / tools / faust2ck-1.0 / src / faust2ck.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 char *chuck_faust_template[] = {
7 #include "chuck_faust.template.h"
8 NULL
9 };
10
11 char *ctrl_cget_query[] = {
12 "\n func = make_new_mfun( \"float\", \"%var_label%\",",
13 " %dsp_name%_ctrl_%var_name% );",
14 " func->add_arg( \"float\", \"%var_label%\" );",
15 " if (!type_engine_import_mfun( env, func ))",
16 " goto error;",
17 NULL
18 };
19
20 char *ctrl_cget_funcs[] = {
21 "static void %dsp_name%_ctrl_%var_name%( Chuck_Object * SELF, void * ARGS,",
22 " Chuck_DL_Return * RETURN,",
23 " Chuck_VM_Shred * SHRED)",
24 "{",
25 " %dsp_name% *d = (%dsp_name%*)OBJ_MEMBER_UINT(SELF, %dsp_name%_offset_data);",
26 " d->%var_name% = (SAMPLE)GET_CK_FLOAT(ARGS);",
27 " RETURN->v_float = (t_CKFLOAT)(d->%var_name%);",
28 "}\n",
29 NULL
30 };
31
32
33 typedef struct _variable_t
34 {
35 char name[256];
36 char label[256];
37 struct _variable_t *next;
38 } variable_t;
39
40 variable_t variables;
41 variable_t *current_v = &variables;
42 FILE *out = 0;
43 char dspname[256] = "mydsp";
44 int in_widget = 0;
45 char outfilename[2048];
46
47 void strip(char *to, char *from, int quotes, int replace_spaces)
48 {
49 int i=0, j=0;
50 while (from[i] && (from[i]==' ' || from[i]=='\t'
51 || (from[i]=='"' && quotes)))
52 i++;
53 while (from[i]) {
54 if (replace_spaces && from[i]==' ')
55 to[j++] = '_';
56 else
57 to[j++] = from[i];
58 i++;
59 }
60 j--;
61 while (j>0 && (to[j]==' ' || to[j]=='\t'
62 || (to[j]=='"' && quotes)
63 || (to[j]=='_' && replace_spaces) ))
64 to[j--] = 0;
65 }
66
67 void on_beg_tag(char *name)
68 {
69 /* TODO: here would be a good place for parsing attributes if we
70 * were interested in doing so. */
71
72 if (strncmp(name, "widget", 6)==0) {
73 if (name[6]!=0 && name[6]!=' ')
74 return;
75 current_v->next = malloc(sizeof(variable_t));
76 current_v = current_v->next;
77 current_v->next = 0;
78 in_widget = 1;
79 }
80 }
81
82 void on_end_tag(char *name, char *value)
83 {
84 if (strcmp(name, "widget")==0) {
85 in_widget = 0;
86 }
87
88 else if (strcmp(name, "varname")==0 && in_widget) {
89 strip(current_v->name, value, 1, 1);
90 }
91
92 else if (strcmp(name, "label")==0 && in_widget) {
93 strip(current_v->label, value, 1, 1);
94 }
95
96 else if (strcmp(name, "name")==0) {
97 strip(dspname, value, 1, 1);
98 }
99 }
100
101 /*
102 * See the technical section of README for an explanation of this insanity.
103 */
104
105 int parseXml(FILE* f)
106 {
107 typedef enum
108 {
109 in_open_tag,
110 in_close_tag,
111 in_text,
112 } state_t;
113
114 typedef struct
115 {
116 int pos;
117 char buf[2048];
118 int no_text;
119 } stack_frame;
120
121 int line = 1;
122
123 state_t state = in_text;
124
125 char c = 0, last_c = 0;
126 stack_frame stack[50];
127
128 int level=0;
129
130 while (!feof(f))
131 {
132 last_c = c;
133 c = fgetc(f);
134
135 if (c=='\r' || c=='\n') {
136 if (last_c!='\r' && last_c!='\n')
137 line++;
138 continue;
139 }
140
141 switch (state)
142 {
143 case in_open_tag:
144 if (c == '>') {
145 on_beg_tag(stack[level].buf);
146 state = in_text;
147 if (stack[level].no_text) {
148 level --;
149 continue;
150 }
151 level ++;
152 stack[level].pos = 0;
153 stack[level].buf[0] = 0;
154 continue;
155 }
156 if (c == '/' && last_c == '<') {
157 state = in_close_tag;
158 continue;
159 }
160 if (c == '/') {
161 stack[level].no_text = 1; // empty tag
162 continue;
163 }
164 stack[level].buf[stack[level].pos++] = c;
165 stack[level].buf[stack[level].pos] = 0;
166 break;
167 case in_close_tag:
168 if (c == '>') {
169 state = in_text;
170 if (strncmp(stack[level].buf, stack[level-2].buf,
171 strlen(stack[level].buf))!=0) {
172 printf("Error with '%s', line %d\n",
173 stack[level].buf, line);
174 return -1;
175 }
176 level -= 3;
177 on_end_tag(stack[level+3].buf, stack[level+2].buf);
178 continue;
179 }
180 stack[level].buf[stack[level].pos++] = c;
181 stack[level].buf[stack[level].pos] = 0;
182 break;
183 case in_text:
184 if (c == '<') {
185 state = in_open_tag;
186 level ++;
187 stack[level].pos = 0;
188 stack[level].buf[0] = 0;
189 stack[level].no_text = 0;
190 continue;
191 }
192 stack[level].buf[stack[level].pos++] = c;
193 stack[level].buf[stack[level].pos] = 0;
194 break;
195 }
196 }
197
198 return 0;
199 }
200
201 void do_template(char *template[]);
202
203 int on_replace(char *var)
204 {
205 if (strcmp(var, "dsp_name")==0) {
206 fprintf(out, dspname);
207 }
208 else if (strcmp(var, "var_name")==0) {
209 fprintf(out, current_v->name);
210 }
211 else if (strcmp(var, "var_label")==0) {
212 fprintf(out, current_v->label);
213 }
214 else if (strcmp(var, "ctrl_cget_functions")==0) {
215 variable_t *v = variables.next;
216 while (v) {
217 current_v = v;
218 do_template(ctrl_cget_funcs);
219 v = v->next;
220 }
221 }
222 else if (strcmp(var, "ctrl_cget_query")==0) {
223 variable_t *v = variables.next;
224 while (v) {
225 current_v = v;
226 do_template(ctrl_cget_query);
227 v = v->next;
228 }
229 }
230 else
231 return 1;
232 return 0;
233 }
234
235 void do_template(char *template[])
236 {
237 int line, pos, k, i;
238 char str[256];
239 line = 0;
240 while (template[line])
241 {
242 int len = strlen(template[line]);
243 for (pos=0; pos < len; pos++) {
244 char c = template[line][pos];
245 if (c == '%') {
246 k = 0;
247 i = pos;
248 pos++;
249 while (template[line][pos] && template[line][pos]!='%')
250 str[k++] = template[line][pos++];
251 str[k] = 0;
252 if (on_replace(str)) {
253 fprintf(out,"%%");
254 pos = i;
255 }
256 }
257 else
258 fprintf(out,"%c", template[line][pos]);
259 }
260 fprintf(out,"\n");
261 line++;
262 }
263 }
264
265 int main(int argc, char *argv[])
266 {
267 int i, rc=0;
268 FILE *fxml = 0;
269 out = stdout;
270
271 if (argc != 2) {
272 printf("Usage: faust2ck <filename.dsp.xml>\n");
273 rc = 1;
274 goto error;
275 }
276
277 fxml = fopen(argv[1], "r");
278 if (!fxml) {
279 printf("Error: Could not open %s.\n", argv[1]);
280 rc = 2;
281 goto error;
282 }
283
284 if (parseXml(fxml)) {
285 printf("Error parsing XML in %s\n", argv[1]);
286 rc = 3;
287 goto error;
288 }
289
290 fclose(fxml);
291 fxml = 0;
292
293 // determine output file name
294 strcpy(outfilename, argv[1]);
295 i=strlen(outfilename)-1;
296 while (i>0 && outfilename[i]!='.')
297 i--;
298 if (i==0) i=strlen(outfilename);
299 strcpy(&outfilename[i], "-wrapper.cpp");
300
301 out = fopen(outfilename, "w");
302 if (!out) {
303 printf("Could not open output file %s\n", outfilename);
304 rc = 4;
305 goto error;
306 }
307
308 do_template(chuck_faust_template);
309
310 error:
311
312 if (fxml)
313 fclose(fxml);
314
315 if (out && out!=stdout)
316 fclose(out);
317
318 variable_t *v = variables.next;
319 while (v) {
320 variable_t *t = v->next;
321 free(v);
322 v = t;
323 }
324
325 return rc;
326 }