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