1 /*
2 * meta_parser.cpp -- IceMetaL parser module
3 *
4 * Copyright (C) 2004 Tony Sin(x) '76 <administrator@tortugalabs.it>
5 * All rights reserved.
6 *
7 */
8
9 /*
10 * GNU GENERAL PUBLIC LICENSE
11 * Version 2, June 1991
12 *
13 * Copyright (C) 1989, 1991 Free Software Foundation, Inc.
14 * 675 Mass Ave, Cambridge, MA 02139, USA
15 * Everyone is permitted to copy and distribute verbatim copies
16 * of this license document, but changing it is not allowed.
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 *
32 */
33
34 #ifdef HAVE_CONFIG_H
35 #ifndef __main_config_h__
36 #define __main_config_h__
37 #include "../config.h"
38 #endif
39
40 #ifdef HAVE_STDLIB_H
41 #include <stdlib.h>
42 #endif
43
44 #ifdef HAVE_STRING_H
45 #include <string.h>
46 #endif
47
48 #ifdef HAVE_STDIO_H
49 #include <stdio.h>
50 #endif
51
52 #ifdef HAVE_CTYPE_H
53 #include <ctype.h>
54 #endif
55 #endif
56
57 #include "meta_parser.h"
58
cMetaDataItem()59 cMetaDataItem::cMetaDataItem()
60 {
61 Index = 0;
62 Next = Loop = NULL;
63 }
64
~cMetaDataItem()65 cMetaDataItem::~cMetaDataItem()
66 {
67 }
68
SetMeta(int idx)69 void cMetaDataItem::SetMeta(int idx)
70 {
71 Index = idx;
72 }
73
SetLoop(int l)74 void cMetaDataItem::SetLoop(int l)
75 {
76 Index = (l | IS_LOOP);
77 }
78
SetEndLoop(cMetaDataItem * p)79 void cMetaDataItem::SetEndLoop(cMetaDataItem *p)
80 {
81 Index = ((p->Index & RETRIEVE_DATA) | IS_ENDLOOP);
82 Loop = p;
83 }
84
SetNext(cMetaDataItem * p)85 void cMetaDataItem::SetNext(cMetaDataItem *p)
86 {
87 Next = p;
88 }
89
GetNext(bool always_next)90 cMetaDataItem *cMetaDataItem::GetNext(bool always_next)
91 {
92 cMetaDataItem *p;
93
94 if ((Index & IS_ENDLOOP) && !always_next)
95 {
96 if ((Loop->Index & RETRIEVE_DATA) == 0)
97 p = Loop;
98 else
99 {
100 if ((Index & RETRIEVE_DATA) > 0)
101 {
102 p = Loop;
103 Index = (((Index & RETRIEVE_DATA)-1) | IS_ENDLOOP);
104 }
105 else
106 {
107 p = Next;
108 Index = ((Loop->Index & RETRIEVE_DATA) | IS_ENDLOOP);
109 }
110 }
111 }
112 else
113 p = Next;
114
115 return p;
116 }
117
GetMeta()118 int cMetaDataItem::GetMeta()
119 {
120 return Index;
121 }
122
cMetaDataList()123 cMetaDataList::cMetaDataList()
124 {
125 int i = 0;
126
127 Loops_Stack_Ptr = -1;
128 Constants_Idx = 0;
129 Root = Ptr = NULL;
130 for (i = 0; i < MAX_LOOPS; i++)
131 Loops_Stack[i] = NULL;
132 for (i = 0; i < MAX_CONSTANTS; i++)
133 Constants[i] = NULL;
134
135 int_buf = new char[INTERNAL_BUF_SIZE];
136 }
137
~cMetaDataList()138 cMetaDataList::~cMetaDataList()
139 {
140 PurgeMeta();
141
142 delete [] int_buf;
143 }
144
ParseLine(const char * buf,char * key,char * value)145 bool cMetaDataList::ParseLine(const char *buf, char *key, char *value)
146 {
147 int state = 0, idx, key_idx, value_idx;
148 bool err = false;
149
150 key_idx = value_idx = 0;
151
152 for (idx = 0; (!err) && buf[idx] && (buf[idx] != '\n') && (state != 8); idx++)
153 switch(state)
154 {
155 case 0: if (isalpha(buf[idx]))
156 {
157 key[key_idx++] = toupper(buf[idx]);
158 state = 2;
159 }
160 else if (buf[idx] == '#')
161 state = 8;
162 else if (buf[idx] == ' ')
163 state = 1;
164 else
165 err = true;
166 break;
167 case 1: if (isalpha(buf[idx]))
168 {
169 key[key_idx++] = toupper(buf[idx]);
170 state = 2;
171 }
172 else if (buf[idx] == '#')
173 state = 8;
174 else if (buf[idx] != ' ')
175 err = true;
176 break;
177 case 2: if (isalpha(buf[idx]))
178 key[key_idx++] = toupper(buf[idx]);
179 else if (buf[idx] == ' ')
180 {
181 key[key_idx] = '\0';
182 state = 3;
183 }
184 else
185 err = true;
186 break;
187 case 3: if (buf[idx] != ' ')
188 {
189 if (!strcmp(key,"PRINT"))
190 {
191 if (isalpha(buf[idx]))
192 {
193 value[value_idx++] = toupper(buf[idx]);
194 state = 4;
195 }
196 else if (buf[idx] == '"')
197 state = 5;
198 else
199 err = true;
200 }
201 else if (isdigit(buf[idx]) && (!strcmp(key,"LOOP")))
202 {
203 value[value_idx++] = buf[idx];
204 state = 6;
205 }
206 else
207 err = true;
208 }
209 break;
210 case 4: if (isalnum(buf[idx]))
211 value[value_idx++] = toupper(buf[idx]);
212 else if ((buf[idx] == ' ') || (buf[idx] == '\n'))
213 state = 7;
214 else
215 err = true;
216 break;
217 case 5: if (buf[idx] == '"')
218 state = 7;
219 else
220 value[value_idx++] = buf[idx];
221 break;
222 case 6: if (isdigit(buf[idx]))
223 value[value_idx++] = buf[idx];
224 else if ((buf[idx] == ' ') || (buf[idx] == '\n'))
225 state = 7;
226 else
227 err = true;
228 break;
229 case 7: if ((buf[idx] != ' ') && (buf[idx] != '\n'))
230 err = true;
231 break;
232 }
233
234 key[key_idx] = '\0';
235 value[value_idx] = '\0';
236
237 return err;
238 }
239
FillMeta(const char * key,int idx)240 void cMetaDataList::FillMeta(const char *key, int idx)
241 {
242 cMetaDataItem *temp = new cMetaDataItem;
243
244 if (Root == NULL)
245 Root = temp;
246 else
247 Ptr->SetNext(temp);
248
249 Ptr = temp;
250
251 if (!strcmp(key,"LOOP"))
252 {
253 temp->SetLoop(idx);
254 Loops_Stack[++Loops_Stack_Ptr] = temp;
255 }
256 else if (!strcmp(key,"ENDLOOP"))
257 temp->SetEndLoop(Loops_Stack[Loops_Stack_Ptr--]);
258 else
259 temp->SetMeta(idx);
260 }
261
262 #ifdef HAVE_ID3
GetNextMeta(char * buf,struct ID3TableType * ID3)263 void cMetaDataList::GetNextMeta(char *buf, struct ID3TableType *ID3)
264 {
265 while ((Ptr != NULL) && (Ptr->GetMeta() & (IS_LOOP | IS_ENDLOOP)))
266 Ptr = Ptr->GetNext();
267 if (Ptr != NULL)
268 {
269 if (Ptr->GetMeta() & IS_CONSTANT)
270 strcpy(buf,Constants[Ptr->GetMeta() & RETRIEVE_DATA]);
271 else
272 strcpy(buf,ID3[Ptr->GetMeta() & RETRIEVE_DATA].str);
273
274 Ptr = Ptr->GetNext();
275 }
276 else
277 buf[0] = '\0';
278 }
279 #else
GetNextMeta(char * buf)280 void cMetaDataList::GetNextMeta(char *buf)
281 {
282 while ((Ptr != NULL) && (Ptr->GetMeta() & (IS_LOOP | IS_ENDLOOP)))
283 Ptr = Ptr->GetNext();
284 if (Ptr != NULL)
285 {
286 strcpy(buf,Constants[Ptr->GetMeta() & RETRIEVE_DATA]);
287
288 Ptr = Ptr->GetNext();
289 }
290 else
291 buf[0] = '\0';
292 }
293 #endif
294
StartMeta()295 void cMetaDataList::StartMeta()
296 {
297 Ptr = Root;
298 }
299
LoadMeta(const char * meta)300 void cMetaDataList::LoadMeta(const char *meta)
301 {
302 FILE *fp = fopen(meta,"r");
303
304 if (fp != NULL)
305 {
306 char *key, *loc_value;
307 int value;
308
309 key = new char[127];
310 loc_value = new char[127];
311
312 while (fgets(int_buf,INTERNAL_BUF_SIZE,fp) != NULL)
313 {
314 if (!ParseLine(int_buf,key,loc_value) && (strlen(key) > 0))
315 {
316 if (!strcmp(key,"PRINT"))
317 {
318 bool found = false;
319 int i;
320
321 #ifdef HAVE_ID3
322 for (i = 0; (i < MAX_ID3_TAGS) && (!found); i++)
323 found = (!strcmp(loc_value,ID3Table[i].str));
324 #else
325 found = false;
326 #endif
327
328 if (found)
329 value = i-1;
330 else
331 { /* found is already false */
332 for (i = 0; (i < Constants_Idx) && (!found); i++)
333 found = (!strcmp(loc_value,Constants[i]));
334
335 if (found)
336 value = i | IS_CONSTANT;
337 else
338 {
339 Constants[Constants_Idx] = new char[strlen(loc_value)+1];
340 strcpy(Constants[Constants_Idx],loc_value);
341 value = Constants_Idx++ | IS_CONSTANT;
342 }
343 }
344 }
345 else if (!strcmp(key,"LOOP"))
346 {
347 if (strlen(loc_value) > 0)
348 value = atoi(loc_value);
349 else
350 value = 0;
351 }
352 else
353 value = 0;
354
355 FillMeta(key,value);
356 }
357 }
358
359 delete [] key;
360 delete [] loc_value;
361
362 fclose(fp);
363 }
364 }
365
IsEmpty()366 bool cMetaDataList::IsEmpty()
367 {
368 return (Root == NULL);
369 }
370
PurgeMeta()371 void cMetaDataList::PurgeMeta()
372 {
373 cMetaDataItem *temp;
374 int i;
375
376 for (i = 0; i < Constants_Idx; i++)
377 {
378 delete [] Constants[i];
379 Constants[i] = NULL;
380 }
381 Constants_Idx = 0;
382
383 Ptr = Root;
384 while (Ptr != NULL)
385 {
386 temp = Ptr;
387 Ptr = Ptr->GetNext(true);
388 delete temp;
389 }
390
391 Root = Ptr = NULL;
392 }
393