New function ss_gen_vibrato() (API still not clear).
[ahxm.git] / preprocessor.c
blobf9e787cbd9b71b18488f4ad8955a1b21a6f41a3b
1 /*
3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2004 Angel Ortega <angel@triptico.com>
6 preprocessor.c - Language preprocessor
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <ctype.h>
34 #include "core.h"
35 #include "preprocessor.h"
37 /*******************
38 Data
39 ********************/
41 struct _named_block
43 char * name;
44 char * block;
47 static struct _named_block * _named_blocks=NULL;
48 static int _n_named_blocks=0;
49 static int _named_blocks_size=0;
52 /*******************
53 Code
54 ********************/
56 char * ds_load(char * file)
58 struct ds s;
59 int c;
60 FILE * f;
62 if((f=fopen(file, "r")) == NULL)
63 return(NULL);
65 ds_init(s);
67 while((c=fgetc(f)) != EOF)
68 ds_poke(s, c);
70 return(s.d);
74 static int _set_named_block(char * name, char * block)
76 int n;
78 /* find first if block is previously defined */
79 for(n=0;n < _n_named_blocks;n++)
81 if(strcmp(name, _named_blocks[n].name) == 0)
83 free(_named_blocks[n].name);
84 free(_named_blocks[n].block);
85 break;
89 if(n == _n_named_blocks)
91 /* need to expand? */
92 if(_n_named_blocks == _named_blocks_size)
94 _named_blocks_size += 4;
96 _named_blocks=(struct _named_block *)
97 realloc(_named_blocks,
98 _named_blocks_size *
99 sizeof(struct _named_block));
102 _n_named_blocks++;
105 _named_blocks[n].name=name;
106 _named_blocks[n].block=block;
108 return(1);
112 static char * _find_named_block(char * name)
114 int n;
116 for(n=0;n < _n_named_blocks;n++)
118 if(strcmp(name, _named_blocks[n].name) == 0)
119 return(_named_blocks[n].block);
122 return(NULL);
126 #define _isblockname(c) (isalpha(c) || c == '-' || c == '_')
128 char * preprocess(char * i)
130 struct ds o;
131 struct ds block;
132 struct ds tmp;
133 int c;
134 int pc=0;
135 int mode=' ';
136 char * ptr;
137 int line=0;
139 ds_init(o); ds_init(block); ds_init(tmp);
141 while(mode != '\0')
143 c=*i;
145 if(mode == ' ')
147 /* pass through mode */
148 if(c == '/')
149 mode='/';
150 else
151 if(c == '(')
152 mode='(';
153 else
154 if(c == '$')
155 mode='$';
156 else
157 if(c == '%')
158 mode='%';
159 else
160 ds_poke(o, c);
162 else
163 if(mode == '/')
165 /* possible start of comment */
166 if(c == '*')
167 mode='c';
168 else
169 if(c == '/')
170 mode='C';
171 else
173 ds_poke(o, '/');
174 mode=' ';
176 continue;
179 else
180 if(mode == 'c')
182 /* C style comment */
183 if(c == '*')
184 mode='k';
186 else
187 if(mode == 'k')
189 /* * found in C style comment */
190 if(c == '/')
191 mode=' ';
192 else
193 if(c != '*')
194 mode='c';
196 else
197 if(mode == 'C')
199 /* C++ style comment */
200 if(c == '\n')
201 mode=' ';
203 else
204 if(mode == '(')
206 /* in block */
207 if(c == ')')
209 if(pc == 0)
210 mode=')';
211 else
212 pc--;
214 else
215 if(c == '(')
216 pc++;
218 if(mode == '(')
219 ds_poke(block, c);
221 else
222 if(mode == ')')
224 /* what to do with block? */
225 ds_poke(block, '\0');
227 if(c == '*')
228 mode='*';
229 else
230 if(c == '=')
231 mode='=';
232 else
233 if(!isspace(c))
235 ds_pokes(o, "?bad-block-command:");
236 ds_poke(o, c);
238 break;
241 else
242 if(mode == '*')
244 /* repeat block */
245 if(isdigit(c))
246 ds_poke(tmp, c);
247 else
248 if(!(isspace(c) && tmp.p == 0))
250 int t;
252 /* take count */
253 ds_poke(tmp, '\0');
254 sscanf(tmp.d, "%d", &t);
256 /* preprocess block */
257 ptr=preprocess(block.d);
259 /* insert t times */
260 for(;t > 0;t--)
261 ds_pokes(o, ptr);
263 free(ptr);
264 ds_rewind(block);
265 ds_rewind(tmp);
266 mode=' ';
268 continue;
271 else
272 if(mode == '=')
274 /* assign block */
275 if(_isblockname(c))
276 ds_poke(tmp, c);
277 else
278 if(!(isspace(c) && tmp.p == 0))
280 ds_poke(tmp, '\0');
281 _set_named_block(tmp.d, block.d);
283 ds_init(block);
284 ds_init(tmp);
285 mode=' ';
287 continue;
290 else
291 if(mode == '$')
293 /* named block insertion */
294 if(_isblockname(c))
295 ds_poke(tmp, c);
296 else
298 ds_poke(tmp, '\0');
300 if((ptr=_find_named_block(tmp.d)))
302 /* insert block */
303 ptr=preprocess(ptr);
304 ds_pokes(o, ptr);
305 free(ptr);
307 ds_rewind(tmp);
308 mode=' ';
310 continue;
313 /* trigger error */
314 ds_pokes(o, "?undefined-block:");
315 ds_pokes(o, tmp.d);
316 ds_poke(o, ' ');
318 break;
321 else
322 if(mode == '%')
324 /* include */
325 if(c && !isspace(c))
326 ds_poke(tmp, c);
327 else
329 ds_poke(tmp, '\0');
331 if((ptr=ds_load(tmp.d)) != NULL)
333 /* FIXME: leak */
334 ptr=preprocess(ptr);
335 ds_pokes(o, ptr);
336 free(ptr);
338 ds_rewind(tmp);
339 mode=' ';
341 continue;
344 ds_pokes(o, "?file-not-found:");
345 ds_pokes(o, tmp.d);
346 ds_poke(o, ' ');
348 break;
352 if(c == '\0')
353 mode='\0';
355 /* insert line number */
356 if(c == '\n')
358 char str[64];
360 sprintf(str, "$%d ", ++line + 1);
361 ds_pokes(o, str);
364 i++;
367 ds_poke(o, '\0');
369 ds_free(block);
370 ds_free(tmp);
372 return(o.d);