]> git.sesse.net Git - vlc/blob - modules/access/rtsp/real_asmrp.c
* modules/access/rtsp: real rtsp access module.
[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: asmrp.c,v 1.8 2004/08/27 18:34:16 miguelfreitas Exp $
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 () {
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
98   return p;
99 }
100
101 static void asmrp_dispose (asmrp_t *p) {
102
103   int i;
104
105   for (i=0; i<p->sym_tab_num; i++) 
106     free (p->sym_tab[i].id);
107
108   free (p);
109 }
110
111 static void asmrp_getch (asmrp_t *p) {
112   p->ch = p->buf[p->pos];
113   p->pos++;
114
115   lprintf ("%c\n", p->ch);
116
117 }
118
119 static void asmrp_init (asmrp_t *p, const char *str) {
120
121   p->buf = strdup (str);
122   p->pos = 0;
123   
124   asmrp_getch (p);
125 }
126
127 static void asmrp_number (asmrp_t *p) {
128
129   int num;
130
131   num = 0;
132   while ( (p->ch>='0') && (p->ch<='9') ) {
133
134     num = num*10 + (p->ch - '0');
135
136     asmrp_getch (p);
137   }
138
139   p->sym = ASMRP_SYM_NUM;
140   p->num = num;
141 }
142
143 static void asmrp_string (asmrp_t *p) {
144
145   int l;
146
147   l = 0;
148
149   while ( (p->ch!='"') && (p->ch>=32) ) {
150
151     p->str[l] = p->ch;
152
153     l++;
154     asmrp_getch (p);
155   }
156   p->str[l]=0;
157   
158   if (p->ch=='"')
159     asmrp_getch (p);
160   
161   p->sym = ASMRP_SYM_STRING;
162 }
163
164 static void asmrp_identifier (asmrp_t *p) {
165
166   int l;
167
168   l = 0;
169
170   while ( ((p->ch>='A') && (p->ch<='z'))
171           || ((p->ch>='0') && (p->ch<='9'))) {
172
173     p->str[l] = p->ch;
174
175     l++;
176     asmrp_getch (p);
177   }
178   p->str[l]=0;
179   
180   p->sym = ASMRP_SYM_ID;
181 }
182
183 #ifdef LOG
184 static void asmrp_print_sym (asmrp_t *p) {
185
186   printf ("symbol: ");
187
188   switch (p->sym) {
189
190   case ASMRP_SYM_NONE:
191     printf ("NONE\n");
192     break;
193
194   case ASMRP_SYM_EOF:
195     printf ("EOF\n");
196     break;
197
198   case ASMRP_SYM_NUM:
199     printf ("NUM %d\n", p->num);
200     break;
201
202   case ASMRP_SYM_ID:
203     printf ("ID '%s'\n", p->str);
204     break;
205
206   case ASMRP_SYM_STRING:
207     printf ("STRING \"%s\"\n", p->str);
208     break;
209
210   case ASMRP_SYM_HASH:
211     printf ("#\n");
212     break;
213
214   case ASMRP_SYM_SEMICOLON:
215     printf (";\n");
216     break;
217   case ASMRP_SYM_COMMA:
218     printf (",\n");
219     break;
220   case ASMRP_SYM_EQUALS:
221     printf ("==\n");
222     break;
223   case ASMRP_SYM_AND:
224     printf ("&&\n");
225     break;
226   case ASMRP_SYM_OR:
227     printf ("||\n");
228     break;
229   case ASMRP_SYM_LESS:
230     printf ("<\n");
231     break;
232   case ASMRP_SYM_LEQ:
233     printf ("<=\n");
234     break;
235   case ASMRP_SYM_GEQ:
236     printf (">=\n");
237     break;
238   case ASMRP_SYM_GREATER:
239     printf (">\n");
240     break;
241   case ASMRP_SYM_DOLLAR:
242     printf ("$\n");
243     break;
244   case ASMRP_SYM_LPAREN:
245     printf ("(\n");
246     break;
247   case ASMRP_SYM_RPAREN:
248     printf (")\n");
249     break;
250
251   default:
252     printf ("unknown symbol %d\n", p->sym);
253   }
254 }
255 #endif
256
257 static void asmrp_get_sym (asmrp_t *p) {
258
259   while (p->ch <= 32) {
260     if (p->ch == 0) {
261       p->sym = ASMRP_SYM_EOF;
262       return;
263     }
264
265     asmrp_getch (p);
266   }
267
268   if (p->ch == '\\')
269     asmrp_getch (p);
270
271   switch (p->ch) {
272
273   case '#':
274     p->sym = ASMRP_SYM_HASH;
275     asmrp_getch (p);
276     break;
277   case ';':
278     p->sym = ASMRP_SYM_SEMICOLON;
279     asmrp_getch (p);
280     break;
281   case ',':
282     p->sym = ASMRP_SYM_COMMA;
283     asmrp_getch (p);
284     break;
285   case '=':
286     p->sym = ASMRP_SYM_EQUALS;
287     asmrp_getch (p);
288     if (p->ch=='=')
289       asmrp_getch (p);
290     break;
291   case '&':
292     p->sym = ASMRP_SYM_AND;
293     asmrp_getch (p);
294     if (p->ch=='&')
295       asmrp_getch (p);
296     break;
297   case '|':
298     p->sym = ASMRP_SYM_OR;
299     asmrp_getch (p);
300     if (p->ch=='|')
301       asmrp_getch (p);
302     break;
303   case '<':
304     p->sym = ASMRP_SYM_LESS;
305     asmrp_getch (p);
306     if (p->ch=='=') {
307       p->sym = ASMRP_SYM_LEQ;
308       asmrp_getch (p);
309     }
310     break;
311   case '>':
312     p->sym = ASMRP_SYM_GREATER;
313     asmrp_getch (p);
314     if (p->ch=='=') {
315       p->sym = ASMRP_SYM_GEQ;
316       asmrp_getch (p);
317     }
318     break;
319   case '$':
320     p->sym = ASMRP_SYM_DOLLAR;
321     asmrp_getch (p);
322     break;
323   case '(':
324     p->sym = ASMRP_SYM_LPAREN;
325     asmrp_getch (p);
326     break;
327   case ')':
328     p->sym = ASMRP_SYM_RPAREN;
329     asmrp_getch (p);
330     break;
331
332   case '"':
333     asmrp_getch (p);
334     asmrp_string (p);
335     break;
336
337   case '0': case '1': case '2': case '3': case '4':
338   case '5': case '6': case '7': case '8': case '9':
339     asmrp_number (p);
340     break;
341
342   default:
343     asmrp_identifier (p);
344   }
345
346 #ifdef LOG
347   asmrp_print_sym (p);
348 #endif
349
350 }
351
352 static int asmrp_find_id (asmrp_t *p, char *s) {
353
354   int i;
355
356   for (i=0; i<p->sym_tab_num; i++) {
357     if (!strcmp (s, p->sym_tab[i].id))
358       return i;
359   }
360
361   return -1;
362 }
363
364 static int asmrp_set_id (asmrp_t *p, char *s, int v) {
365
366   int i;
367
368   i = asmrp_find_id (p, s);
369
370   if (i<0) {
371     i = p->sym_tab_num;
372     p->sym_tab_num++;
373     p->sym_tab[i].id = strdup (s);
374
375     lprintf ("new symbol '%s'\n", s);
376
377   }    
378
379   p->sym_tab[i].v = v;
380  
381   lprintf ("symbol '%s' assigned %d\n", s, v);
382
383   return i;
384 }
385
386 static int asmrp_condition (asmrp_t *p) ;
387
388 static int asmrp_operand (asmrp_t *p) {
389
390   int i, ret;
391   
392   lprintf ("operand\n");
393
394   ret = 0;
395
396   switch (p->sym) {
397
398   case ASMRP_SYM_DOLLAR:
399
400     asmrp_get_sym (p);
401     
402     if (p->sym != ASMRP_SYM_ID) {
403       printf ("error: identifier expected.\n");
404       break;
405     }
406
407     i = asmrp_find_id (p, p->str);
408     if (i<0) {
409       lprintf ("error: unknown identifier %s\n", p->str);
410     }
411     ret = p->sym_tab[i].v;
412
413     asmrp_get_sym (p);
414     break;
415
416   case ASMRP_SYM_NUM:
417     ret = p->num;
418
419     asmrp_get_sym (p);
420     break;
421
422   case ASMRP_SYM_LPAREN:
423     asmrp_get_sym (p);
424
425     ret = asmrp_condition (p);
426
427     if (p->sym != ASMRP_SYM_RPAREN) {
428       printf ("error: ) expected.\n");
429       break;
430     }
431
432     asmrp_get_sym (p);
433     break;
434
435   default:
436     lprintf ("syntax error, $ number or ( expected\n");
437     break;
438   }
439
440   lprintf ("operand done, =%d\n", ret);
441   
442   return ret;
443 }
444
445 static int asmrp_comp_expression (asmrp_t *p) {
446
447   int a;
448
449   lprintf ("comp_expression\n");
450
451   a = asmrp_operand (p);
452
453   while ( (p->sym == ASMRP_SYM_LESS)
454           || (p->sym == ASMRP_SYM_LEQ)
455           || (p->sym == ASMRP_SYM_EQUALS)
456           || (p->sym == ASMRP_SYM_GEQ)
457           || (p->sym == ASMRP_SYM_GREATER) ) {
458     int op = p->sym;
459     int b;
460
461     asmrp_get_sym (p);
462
463     b = asmrp_operand (p);
464
465     switch (op) {
466     case ASMRP_SYM_LESS:
467       a = a<b;
468       break;
469     case ASMRP_SYM_LEQ:
470       a = a<=b;
471       break;
472     case ASMRP_SYM_EQUALS:
473       a = a==b;
474       break;
475     case ASMRP_SYM_GEQ:
476       a = a>=b;
477       break;
478     case ASMRP_SYM_GREATER:
479       a = a>b;
480       break;
481     }
482
483   }
484
485   lprintf ("comp_expression done = %d\n", a);
486
487   return a;
488 }
489
490 static int asmrp_condition (asmrp_t *p) {
491   
492   int a;
493
494   lprintf ("condition\n");
495
496   a = asmrp_comp_expression (p);
497
498   while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) {
499     int op, b;
500
501     op = p->sym;
502
503     asmrp_get_sym (p);
504
505     b = asmrp_comp_expression (p);
506
507     switch (op) {
508     case ASMRP_SYM_AND:
509       a = a & b;
510       break;
511     case ASMRP_SYM_OR:
512       a = a | b;
513       break;
514     }
515   }
516
517   lprintf ("condition done = %d\n", a);
518
519   return a;
520 }
521
522 static void asmrp_assignment (asmrp_t *p) {
523
524   lprintf ("assignment\n");
525
526   if (p->sym == ASMRP_SYM_COMMA || p->sym == ASMRP_SYM_SEMICOLON) {
527     lprintf ("empty assignment\n");
528     return;
529   }
530   
531   if (p->sym != ASMRP_SYM_ID) {
532     printf ("error: identifier expected\n");
533     return;
534   }
535   asmrp_get_sym (p);
536
537   if (p->sym != ASMRP_SYM_EQUALS) {
538     printf ("error: = expected\n");
539     return;
540   }
541   asmrp_get_sym (p);
542
543   if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) 
544        && (p->sym != ASMRP_SYM_ID)) {
545     printf ("error: number or string expected\n");
546     return;
547   }
548   asmrp_get_sym (p);
549
550   lprintf ("assignment done\n");
551 }
552
553 static int asmrp_rule (asmrp_t *p) {
554   
555   int ret;
556
557   lprintf ("rule\n");
558
559   ret = 1;
560   
561   if (p->sym == ASMRP_SYM_HASH) {
562
563     asmrp_get_sym (p);
564     ret = asmrp_condition (p);
565
566     while (p->sym == ASMRP_SYM_COMMA) {
567       
568       asmrp_get_sym (p);
569       
570       asmrp_assignment (p);
571     }
572
573   } else if (p->sym != ASMRP_SYM_SEMICOLON) {
574
575     asmrp_assignment (p);
576
577     while (p->sym == ASMRP_SYM_COMMA) {
578
579       asmrp_get_sym (p);
580       asmrp_assignment (p);
581     }
582   }
583
584   lprintf ("rule done = %d\n", ret);
585
586   if (p->sym != ASMRP_SYM_SEMICOLON) {
587     printf ("semicolon expected.\n");
588     return ret;
589   }
590
591   asmrp_get_sym (p);
592
593   return ret;
594 }
595
596 static int asmrp_eval (asmrp_t *p, int *matches) {
597
598   int rule_num, num_matches;
599
600   lprintf ("eval\n");
601
602   asmrp_get_sym (p);
603
604   rule_num = 0; num_matches = 0;
605   while (p->sym != ASMRP_SYM_EOF) {
606
607     if (asmrp_rule (p)) {
608       lprintf ("rule #%d is true\n", rule_num);
609
610       matches[num_matches] = rule_num;
611       num_matches++;
612     }
613
614     rule_num++;
615   }
616
617   matches[num_matches] = -1;
618   return num_matches;
619 }
620
621 int asmrp_match (const char *rules, int bandwidth, int *matches) {
622
623   asmrp_t *p;
624   int      num_matches;
625
626   p = asmrp_new ();
627
628   asmrp_init (p, rules);
629
630   asmrp_set_id (p, "Bandwidth", bandwidth);
631   asmrp_set_id (p, "OldPNMPlayer", 0);
632
633   num_matches = asmrp_eval (p, matches);
634
635   asmrp_dispose (p);
636
637   return num_matches;
638 }
639