]> git.sesse.net Git - vlc/blob - modules/access/rtsp/real_asmrp.c
Fix roundoff issues in i_length.
[vlc] / modules / access / rtsp / real_asmrp.c
1 /*
2  * Copyright (C) 2002-2004 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
19  *
20  * $Id$
21  *
22  * a parser for real's asm rules
23  *
24  * grammar for these rules:
25  *
26
27    rule_book  = { rule }
28    rule       = ( '#' condition { ',' assignment } | [ assignment {',' assignment} ]) ';'
29    assignment = id '=' const
30    const      = ( number | string )
31    condition  = comp_expr { ( '&&' | '||' ) comp_expr }
32    comp_expr  = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand }
33    operand    = ( '$' id | num | '(' condition ')' )
34
35  */
36
37 #include "real.h"
38
39 #define ASMRP_SYM_NONE         0
40 #define ASMRP_SYM_EOF          1
41
42 #define ASMRP_SYM_NUM          2
43 #define ASMRP_SYM_ID           3
44 #define ASMRP_SYM_STRING       4
45
46 #define ASMRP_SYM_HASH         10
47 #define ASMRP_SYM_SEMICOLON    11
48 #define ASMRP_SYM_COMMA        12
49 #define ASMRP_SYM_EQUALS       13
50 #define ASMRP_SYM_AND          14
51 #define ASMRP_SYM_OR           15
52 #define ASMRP_SYM_LESS         16
53 #define ASMRP_SYM_LEQ          17
54 #define ASMRP_SYM_GEQ          18
55 #define ASMRP_SYM_GREATER      19
56 #define ASMRP_SYM_DOLLAR       20
57 #define ASMRP_SYM_LPAREN       21
58 #define ASMRP_SYM_RPAREN       22
59
60 #define ASMRP_MAX_ID         1024
61
62 #define ASMRP_MAX_SYMTAB       10
63
64 typedef struct {
65   char *id;
66   int   v;
67 } asmrp_sym_t;
68
69 typedef struct {
70
71   /* public part */
72
73   int         sym;
74   int         num;
75  
76   char        str[ASMRP_MAX_ID];
77
78   /* private part */
79
80   char       *buf;
81   int         pos;
82   char        ch;
83
84   asmrp_sym_t sym_tab[ASMRP_MAX_SYMTAB];
85   int         sym_tab_num;
86
87 } asmrp_t;
88
89 static asmrp_t *asmrp_new (void ) {
90
91   asmrp_t *p;
92
93   p = malloc (sizeof (asmrp_t));
94
95   p->sym_tab_num = 0;
96   p->sym         = ASMRP_SYM_NONE;
97   p->buf         = NULL;
98
99   return p;
100 }
101
102 static void asmrp_dispose (asmrp_t *p) {
103
104   int i;
105
106   for (i=0; i<p->sym_tab_num; i++)
107     free (p->sym_tab[i].id);
108
109   free( p->buf );
110   free( p );
111 }
112
113 static void asmrp_getch (asmrp_t *p) {
114   p->ch = p->buf[p->pos];
115   p->pos++;
116
117   lprintf ("%c\n", p->ch);
118
119 }
120
121 static void asmrp_init (asmrp_t *p, const char *str) {
122
123   p->buf = strdup (str);
124   p->pos = 0;
125  
126   asmrp_getch (p);
127 }
128
129 static void asmrp_number (asmrp_t *p) {
130
131   int num;
132
133   num = 0;
134   while ( (p->ch>='0') && (p->ch<='9') ) {
135
136     num = num*10 + (p->ch - '0');
137
138     asmrp_getch (p);
139   }
140
141   p->sym = ASMRP_SYM_NUM;
142   p->num = num;
143 }
144
145 static void asmrp_string (asmrp_t *p) {
146
147   int l;
148
149   l = 0;
150
151   while ( (p->ch!='"') && (p->ch>=32) ) {
152
153     p->str[l] = p->ch;
154
155     l++;
156     asmrp_getch (p);
157   }
158   p->str[l]=0;
159  
160   if (p->ch=='"')
161     asmrp_getch (p);
162  
163   p->sym = ASMRP_SYM_STRING;
164 }
165
166 static void asmrp_identifier (asmrp_t *p) {
167
168   int l;
169
170   l = 0;
171
172   while ( ((p->ch>='A') && (p->ch<='z'))
173       || ((p->ch>='0') && (p->ch<='9'))) {
174
175     p->str[l] = p->ch;
176
177     l++;
178     asmrp_getch (p);
179   }
180   p->str[l]=0;
181  
182   p->sym = ASMRP_SYM_ID;
183 }
184
185 #ifdef LOG
186 static void asmrp_print_sym (asmrp_t *p) {
187
188   printf ("symbol: ");
189
190   switch (p->sym) {
191
192   case ASMRP_SYM_NONE:
193     printf ("NONE\n");
194     break;
195
196   case ASMRP_SYM_EOF:
197     printf ("EOF\n");
198     break;
199
200   case ASMRP_SYM_NUM:
201     printf ("NUM %d\n", p->num);
202     break;
203
204   case ASMRP_SYM_ID:
205     printf ("ID '%s'\n", p->str);
206     break;
207
208   case ASMRP_SYM_STRING:
209     printf ("STRING \"%s\"\n", p->str);
210     break;
211
212   case ASMRP_SYM_HASH:
213     printf ("#\n");
214     break;
215
216   case ASMRP_SYM_SEMICOLON:
217     printf (";\n");
218     break;
219   case ASMRP_SYM_COMMA:
220     printf (",\n");
221     break;
222   case ASMRP_SYM_EQUALS:
223     printf ("==\n");
224     break;
225   case ASMRP_SYM_AND:
226     printf ("&&\n");
227     break;
228   case ASMRP_SYM_OR:
229     printf ("||\n");
230     break;
231   case ASMRP_SYM_LESS:
232     printf ("<\n");
233     break;
234   case ASMRP_SYM_LEQ:
235     printf ("<=\n");
236     break;
237   case ASMRP_SYM_GEQ:
238     printf (">=\n");
239     break;
240   case ASMRP_SYM_GREATER:
241     printf (">\n");
242     break;
243   case ASMRP_SYM_DOLLAR:
244     printf ("$\n");
245     break;
246   case ASMRP_SYM_LPAREN:
247     printf ("(\n");
248     break;
249   case ASMRP_SYM_RPAREN:
250     printf (")\n");
251     break;
252
253   default:
254     printf ("unknown symbol %d\n", p->sym);
255   }
256 }
257 #endif
258
259 static void asmrp_get_sym (asmrp_t *p) {
260
261   while (p->ch <= 32) {
262     if (p->ch == 0) {
263       p->sym = ASMRP_SYM_EOF;
264       return;
265     }
266
267     asmrp_getch (p);
268   }
269
270   if (p->ch == '\\')
271     asmrp_getch (p);
272
273   switch (p->ch) {
274
275   case '#':
276     p->sym = ASMRP_SYM_HASH;
277     asmrp_getch (p);
278     break;
279   case ';':
280     p->sym = ASMRP_SYM_SEMICOLON;
281     asmrp_getch (p);
282     break;
283   case ',':
284     p->sym = ASMRP_SYM_COMMA;
285     asmrp_getch (p);
286     break;
287   case '=':
288     p->sym = ASMRP_SYM_EQUALS;
289     asmrp_getch (p);
290     if (p->ch=='=')
291       asmrp_getch (p);
292     break;
293   case '&':
294     p->sym = ASMRP_SYM_AND;
295     asmrp_getch (p);
296     if (p->ch=='&')
297       asmrp_getch (p);
298     break;
299   case '|':
300     p->sym = ASMRP_SYM_OR;
301     asmrp_getch (p);
302     if (p->ch=='|')
303       asmrp_getch (p);
304     break;
305   case '<':
306     p->sym = ASMRP_SYM_LESS;
307     asmrp_getch (p);
308     if (p->ch=='=') {
309       p->sym = ASMRP_SYM_LEQ;
310       asmrp_getch (p);
311     }
312     break;
313   case '>':
314     p->sym = ASMRP_SYM_GREATER;
315     asmrp_getch (p);
316     if (p->ch=='=') {
317       p->sym = ASMRP_SYM_GEQ;
318       asmrp_getch (p);
319     }
320     break;
321   case '$':
322     p->sym = ASMRP_SYM_DOLLAR;
323     asmrp_getch (p);
324     break;
325   case '(':
326     p->sym = ASMRP_SYM_LPAREN;
327     asmrp_getch (p);
328     break;
329   case ')':
330     p->sym = ASMRP_SYM_RPAREN;
331     asmrp_getch (p);
332     break;
333
334   case '"':
335     asmrp_getch (p);
336     asmrp_string (p);
337     break;
338
339   case '0': case '1': case '2': case '3': case '4':
340   case '5': case '6': case '7': case '8': case '9':
341     asmrp_number (p);
342     break;
343
344   default:
345     asmrp_identifier (p);
346   }
347
348 #ifdef LOG
349   asmrp_print_sym (p);
350 #endif
351
352 }
353
354 static int asmrp_find_id (asmrp_t *p, const char *s) {
355
356   int i;
357
358   for (i=0; i<p->sym_tab_num; i++) {
359     if (!strcmp (s, p->sym_tab[i].id))
360       return i;
361   }
362
363   return -1;
364 }
365
366 static int asmrp_set_id (asmrp_t *p, const char *s, int v) {
367
368   int i;
369
370   i = asmrp_find_id (p, s);
371
372   if (i<0) {
373     i = p->sym_tab_num;
374     p->sym_tab_num++;
375     p->sym_tab[i].id = strdup (s);
376
377     lprintf ("new symbol '%s'\n", s);
378
379   }
380
381   p->sym_tab[i].v = v;
382  
383   lprintf ("symbol '%s' assigned %d\n", s, v);
384
385   return i;
386 }
387
388 static int asmrp_condition (asmrp_t *p) ;
389
390 static int asmrp_operand (asmrp_t *p) {
391
392   int i, ret;
393  
394   lprintf ("operand\n");
395
396   ret = 0;
397
398   switch (p->sym) {
399
400   case ASMRP_SYM_DOLLAR:
401
402     asmrp_get_sym (p);
403  
404     if (p->sym != ASMRP_SYM_ID) {
405       printf ("error: identifier expected.\n");
406       break;
407     }
408
409     i = asmrp_find_id (p, p->str);
410     if (i<0) {
411       lprintf ("error: unknown identifier %s\n", p->str);
412     }
413     ret = p->sym_tab[i].v;
414
415     asmrp_get_sym (p);
416     break;
417
418   case ASMRP_SYM_NUM:
419     ret = p->num;
420
421     asmrp_get_sym (p);
422     break;
423
424   case ASMRP_SYM_LPAREN:
425     asmrp_get_sym (p);
426
427     ret = asmrp_condition (p);
428
429     if (p->sym != ASMRP_SYM_RPAREN) {
430       printf ("error: ) expected.\n");
431       break;
432     }
433
434     asmrp_get_sym (p);
435     break;
436
437   default:
438     lprintf ("syntax error, $ number or ( expected\n");
439     break;
440   }
441
442   lprintf ("operand done, =%d\n", ret);
443  
444   return ret;
445 }
446
447 static int asmrp_comp_expression (asmrp_t *p) {
448
449   int a;
450
451   lprintf ("comp_expression\n");
452
453   a = asmrp_operand (p);
454
455   while ( (p->sym == ASMRP_SYM_LESS)
456       || (p->sym == ASMRP_SYM_LEQ)
457       || (p->sym == ASMRP_SYM_EQUALS)
458       || (p->sym == ASMRP_SYM_GEQ)
459       || (p->sym == ASMRP_SYM_GREATER) ) {
460     int op = p->sym;
461     int b;
462
463     asmrp_get_sym (p);
464
465     b = asmrp_operand (p);
466
467     switch (op) {
468     case ASMRP_SYM_LESS:
469       a = a<b;
470       break;
471     case ASMRP_SYM_LEQ:
472       a = a<=b;
473       break;
474     case ASMRP_SYM_EQUALS:
475       a = a==b;
476       break;
477     case ASMRP_SYM_GEQ:
478       a = a>=b;
479       break;
480     case ASMRP_SYM_GREATER:
481       a = a>b;
482       break;
483     }
484
485   }
486
487   lprintf ("comp_expression done = %d\n", a);
488
489   return a;
490 }
491
492 static int asmrp_condition (asmrp_t *p) {
493  
494   int a;
495
496   lprintf ("condition\n");
497
498   a = asmrp_comp_expression (p);
499
500   while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) {
501     int op, b;
502
503     op = p->sym;
504
505     asmrp_get_sym (p);
506
507     b = asmrp_comp_expression (p);
508
509     switch (op) {
510     case ASMRP_SYM_AND:
511       a = a & b;
512       break;
513     case ASMRP_SYM_OR:
514       a = a | b;
515       break;
516     }
517   }
518
519   lprintf ("condition done = %d\n", a);
520
521   return a;
522 }
523
524 static void asmrp_assignment (asmrp_t *p) {
525
526   lprintf ("assignment\n");
527
528   if (p->sym == ASMRP_SYM_COMMA || p->sym == ASMRP_SYM_SEMICOLON) {
529     lprintf ("empty assignment\n");
530     return;
531   }
532  
533   if (p->sym != ASMRP_SYM_ID) {
534     printf ("error: identifier expected\n");
535     return;
536   }
537   asmrp_get_sym (p);
538
539   if (p->sym != ASMRP_SYM_EQUALS) {
540     printf ("error: = expected\n");
541     return;
542   }
543   asmrp_get_sym (p);
544
545   if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING)
546        && (p->sym != ASMRP_SYM_ID)) {
547     printf ("error: number or string expected\n");
548     return;
549   }
550   asmrp_get_sym (p);
551
552   lprintf ("assignment done\n");
553 }
554
555 static int asmrp_rule (asmrp_t *p) {
556  
557   int ret;
558
559   lprintf ("rule\n");
560
561   ret = 1;
562  
563   if (p->sym == ASMRP_SYM_HASH) {
564
565     asmrp_get_sym (p);
566     ret = asmrp_condition (p);
567
568     while (p->sym == ASMRP_SYM_COMMA) {
569  
570       asmrp_get_sym (p);
571  
572       asmrp_assignment (p);
573     }
574
575   } else if (p->sym != ASMRP_SYM_SEMICOLON) {
576
577     asmrp_assignment (p);
578
579     while (p->sym == ASMRP_SYM_COMMA) {
580
581       asmrp_get_sym (p);
582       asmrp_assignment (p);
583     }
584   }
585
586   lprintf ("rule done = %d\n", ret);
587
588   if (p->sym != ASMRP_SYM_SEMICOLON) {
589     printf ("semicolon expected.\n");
590     return ret;
591   }
592
593   asmrp_get_sym (p);
594
595   return ret;
596 }
597
598 static int asmrp_eval (asmrp_t *p, int *matches, int matchsize) {
599
600   int rule_num, num_matches;
601
602   lprintf ("eval\n");
603
604   asmrp_get_sym (p);
605
606   rule_num = 0; num_matches = 0;
607   while (p->sym != ASMRP_SYM_EOF && num_matches < matchsize - 1) {
608
609     if (asmrp_rule (p)) {
610       lprintf ("rule #%d is true\n", rule_num);
611
612       matches[num_matches] = rule_num;
613       num_matches++;
614     }
615
616     rule_num++;
617   }
618
619   matches[num_matches] = -1;
620   return num_matches;
621 }
622
623 int asmrp_match (const char *rules, int bandwidth, int *matches, int matchsize) {
624
625   asmrp_t *p;
626   int      num_matches;
627
628   p = asmrp_new ();
629
630   asmrp_init (p, rules);
631
632   asmrp_set_id (p, "Bandwidth", bandwidth);
633   asmrp_set_id (p, "OldPNMPlayer", 0);
634
635   num_matches = asmrp_eval (p, matches, matchsize);
636
637   asmrp_dispose (p);
638
639   return num_matches;
640 }
641