Windows: ao_pcm: add io.h include for MinGW64
[mplayer.git] / stream / realrtsp / asmrp.c
blobbcbe1c9389aec6d0dc139841941cf8c9ec76c967
1 /*
2 * This file was ported to MPlayer from xine CVS asmrp.c,v 1.2 2002/12/17 16:49:48
3 */
5 /*
6 * Copyright (C) 2002 the xine project
8 * This file is part of xine, a free video player.
10 * xine is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * xine is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
25 * a parser for real's asm rules
27 * grammar for these rules:
30 rule_book = { rule }
31 rule = ( '#' condition { ',' assignment } | [ assignment {',' assignment} ]) ';'
32 assignment = id '=' const
33 const = ( number | string )
34 condition = comp_expr { ( '&&' | '||' ) comp_expr }
35 comp_expr = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand }
36 operand = ( '$' id | num | '(' condition ')' )
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include "mp_msg.h"
44 #include "asmrp.h"
47 #define LOG
50 #define ASMRP_SYM_NONE 0
51 #define ASMRP_SYM_EOF 1
53 #define ASMRP_SYM_NUM 2
54 #define ASMRP_SYM_ID 3
55 #define ASMRP_SYM_STRING 4
57 #define ASMRP_SYM_HASH 10
58 #define ASMRP_SYM_SEMICOLON 11
59 #define ASMRP_SYM_COMMA 12
60 #define ASMRP_SYM_EQUALS 13
61 #define ASMRP_SYM_AND 14
62 #define ASMRP_SYM_OR 15
63 #define ASMRP_SYM_LESS 16
64 #define ASMRP_SYM_LEQ 17
65 #define ASMRP_SYM_GEQ 18
66 #define ASMRP_SYM_GREATER 19
67 #define ASMRP_SYM_DOLLAR 20
68 #define ASMRP_SYM_LPAREN 21
69 #define ASMRP_SYM_RPAREN 22
71 #define ASMRP_MAX_ID 1024
73 #define ASMRP_MAX_SYMTAB 10
75 typedef struct {
76 char *id;
77 int v;
78 } asmrp_sym_t;
80 typedef struct {
82 /* public part */
84 int sym;
85 int num;
87 char str[ASMRP_MAX_ID];
89 /* private part */
91 char *buf;
92 int pos;
93 char ch;
95 asmrp_sym_t sym_tab[ASMRP_MAX_SYMTAB];
96 int sym_tab_num;
98 } asmrp_t;
100 static asmrp_t *asmrp_new (void) {
102 asmrp_t *p;
104 p = malloc (sizeof (asmrp_t));
106 p->sym_tab_num = 0;
107 p->sym = ASMRP_SYM_NONE;
109 return p;
112 static void asmrp_dispose (asmrp_t *p) {
114 int i;
116 for (i=0; i<p->sym_tab_num; i++)
117 free (p->sym_tab[i].id);
119 free(p->buf);
120 free (p);
123 static void asmrp_getch (asmrp_t *p) {
124 p->ch = p->buf[p->pos];
125 p->pos++;
127 #ifdef LOG
128 printf ("%c\n", p->ch);
129 #endif
133 static void asmrp_init (asmrp_t *p, const char *str) {
135 p->buf = strdup (str);
136 p->pos = 0;
138 asmrp_getch (p);
141 static void asmrp_number (asmrp_t *p) {
143 int num;
145 num = 0;
146 while ( (p->ch>='0') && (p->ch<='9') ) {
148 num = num*10 + (p->ch - '0');
150 asmrp_getch (p);
153 p->sym = ASMRP_SYM_NUM;
154 p->num = num;
157 static void asmrp_string (asmrp_t *p) {
159 int l;
161 l = 0;
163 while ( (p->ch!='"') && (p->ch>=32) ) {
165 if(l < ASMRP_MAX_ID - 1)
166 p->str[l++] = p->ch;
167 else
168 mp_msg(MSGT_STREAM, MSGL_ERR, "error: string too long, ignoring char %c.\n", p->ch);
170 asmrp_getch (p);
172 p->str[l]=0;
174 if (p->ch=='"')
175 asmrp_getch (p);
177 p->sym = ASMRP_SYM_STRING;
180 static void asmrp_identifier (asmrp_t *p) {
182 int l;
184 l = 0;
186 while ( ((p->ch>='A') && (p->ch<='z'))
187 || ((p->ch>='0') && (p->ch<='9'))) {
189 if(l < ASMRP_MAX_ID - 1)
190 p->str[l++] = p->ch;
191 else
192 mp_msg(MSGT_STREAM, MSGL_ERR, "error: identifier too long, ignoring char %c.\n", p->ch);
194 asmrp_getch (p);
196 p->str[l]=0;
198 p->sym = ASMRP_SYM_ID;
201 #ifdef LOG
202 static void asmrp_print_sym (asmrp_t *p) {
204 printf ("symbol: ");
206 switch (p->sym) {
208 case ASMRP_SYM_NONE:
209 printf ("NONE\n");
210 break;
212 case ASMRP_SYM_EOF:
213 printf ("EOF\n");
214 break;
216 case ASMRP_SYM_NUM:
217 printf ("NUM %d\n", p->num);
218 break;
220 case ASMRP_SYM_ID:
221 printf ("ID '%s'\n", p->str);
222 break;
224 case ASMRP_SYM_STRING:
225 printf ("STRING \"%s\"\n", p->str);
226 break;
228 case ASMRP_SYM_HASH:
229 printf ("#\n");
230 break;
232 case ASMRP_SYM_SEMICOLON:
233 printf (";\n");
234 break;
235 case ASMRP_SYM_COMMA:
236 printf (",\n");
237 break;
238 case ASMRP_SYM_EQUALS:
239 printf ("==\n");
240 break;
241 case ASMRP_SYM_AND:
242 printf ("&&\n");
243 break;
244 case ASMRP_SYM_OR:
245 printf ("||\n");
246 break;
247 case ASMRP_SYM_LESS:
248 printf ("<\n");
249 break;
250 case ASMRP_SYM_LEQ:
251 printf ("<=\n");
252 break;
253 case ASMRP_SYM_GEQ:
254 printf (">=\n");
255 break;
256 case ASMRP_SYM_GREATER:
257 printf (">\n");
258 break;
259 case ASMRP_SYM_DOLLAR:
260 printf ("$\n");
261 break;
262 case ASMRP_SYM_LPAREN:
263 printf ("(\n");
264 break;
265 case ASMRP_SYM_RPAREN:
266 printf (")\n");
267 break;
269 default:
270 printf ("unknown symbol %d\n", p->sym);
273 #endif
275 static void asmrp_get_sym (asmrp_t *p) {
277 while (p->ch <= 32) {
278 if (p->ch == 0) {
279 p->sym = ASMRP_SYM_EOF;
280 return;
283 asmrp_getch (p);
286 if (p->ch == '\\')
287 asmrp_getch (p);
289 switch (p->ch) {
291 case '#':
292 p->sym = ASMRP_SYM_HASH;
293 asmrp_getch (p);
294 break;
295 case ';':
296 p->sym = ASMRP_SYM_SEMICOLON;
297 asmrp_getch (p);
298 break;
299 case ',':
300 p->sym = ASMRP_SYM_COMMA;
301 asmrp_getch (p);
302 break;
303 case '=':
304 p->sym = ASMRP_SYM_EQUALS;
305 asmrp_getch (p);
306 if (p->ch=='=')
307 asmrp_getch (p);
308 break;
309 case '&':
310 p->sym = ASMRP_SYM_AND;
311 asmrp_getch (p);
312 if (p->ch=='&')
313 asmrp_getch (p);
314 break;
315 case '|':
316 p->sym = ASMRP_SYM_OR;
317 asmrp_getch (p);
318 if (p->ch=='|')
319 asmrp_getch (p);
320 break;
321 case '<':
322 p->sym = ASMRP_SYM_LESS;
323 asmrp_getch (p);
324 if (p->ch=='=') {
325 p->sym = ASMRP_SYM_LEQ;
326 asmrp_getch (p);
328 break;
329 case '>':
330 p->sym = ASMRP_SYM_GREATER;
331 asmrp_getch (p);
332 if (p->ch=='=') {
333 p->sym = ASMRP_SYM_GEQ;
334 asmrp_getch (p);
336 break;
337 case '$':
338 p->sym = ASMRP_SYM_DOLLAR;
339 asmrp_getch (p);
340 break;
341 case '(':
342 p->sym = ASMRP_SYM_LPAREN;
343 asmrp_getch (p);
344 break;
345 case ')':
346 p->sym = ASMRP_SYM_RPAREN;
347 asmrp_getch (p);
348 break;
350 case '"':
351 asmrp_getch (p);
352 asmrp_string (p);
353 break;
355 case '0': case '1': case '2': case '3': case '4':
356 case '5': case '6': case '7': case '8': case '9':
357 asmrp_number (p);
358 break;
360 default:
361 asmrp_identifier (p);
364 #ifdef LOG
365 asmrp_print_sym (p);
366 #endif
370 static int asmrp_find_id (asmrp_t *p, char *s) {
372 int i;
374 for (i=0; i<p->sym_tab_num; i++) {
375 if (!strcmp (s, p->sym_tab[i].id))
376 return i;
379 return -1;
382 static int asmrp_set_id (asmrp_t *p, char *s, int v) {
384 int i;
386 i = asmrp_find_id (p, s);
388 if (i<0) {
389 if (p->sym_tab_num == ASMRP_MAX_SYMTAB - 1) {
390 mp_msg(MSGT_STREAM, MSGL_ERR, "sym_tab overflow, ignoring identifier %s\n", s);
391 return 0;
393 i = p->sym_tab_num;
394 p->sym_tab_num++;
395 p->sym_tab[i].id = strdup (s);
397 #ifdef LOG
398 printf ("new symbol '%s'\n", s);
399 #endif
403 p->sym_tab[i].v = v;
405 #ifdef LOG
406 printf ("symbol '%s' assigned %d\n", s, v);
407 #endif
409 return i;
412 static int asmrp_condition (asmrp_t *p) ;
414 static int asmrp_operand (asmrp_t *p) {
416 int i, ret;
418 #ifdef LOG
419 printf ("operand\n");
420 #endif
422 ret = 0;
424 switch (p->sym) {
426 case ASMRP_SYM_DOLLAR:
428 asmrp_get_sym (p);
430 if (p->sym != ASMRP_SYM_ID) {
431 mp_msg(MSGT_STREAM, MSGL_ERR, "error: identifier expected.\n");
432 break;
435 i = asmrp_find_id (p, p->str);
436 if (i<0) {
437 mp_msg(MSGT_STREAM, MSGL_ERR, "error: unknown identifier %s\n", p->str);
438 } else
439 ret = p->sym_tab[i].v;
441 asmrp_get_sym (p);
442 break;
444 case ASMRP_SYM_NUM:
445 ret = p->num;
447 asmrp_get_sym (p);
448 break;
450 case ASMRP_SYM_LPAREN:
451 asmrp_get_sym (p);
453 ret = asmrp_condition (p);
455 if (p->sym != ASMRP_SYM_RPAREN) {
456 mp_msg(MSGT_STREAM, MSGL_ERR, "error: ) expected.\n");
457 break;
460 asmrp_get_sym (p);
461 break;
463 default:
464 mp_msg(MSGT_STREAM, MSGL_ERR, "syntax error, $ number or ( expected\n");
467 #ifdef LOG
468 printf ("operand done, =%d\n", ret);
469 #endif
471 return ret;
475 static int asmrp_comp_expression (asmrp_t *p) {
477 int a;
479 #ifdef LOG
480 printf ("comp_expression\n");
481 #endif
483 a = asmrp_operand (p);
485 while ( (p->sym == ASMRP_SYM_LESS)
486 || (p->sym == ASMRP_SYM_LEQ)
487 || (p->sym == ASMRP_SYM_EQUALS)
488 || (p->sym == ASMRP_SYM_GEQ)
489 || (p->sym == ASMRP_SYM_GREATER) ) {
490 int op = p->sym;
491 int b;
493 asmrp_get_sym (p);
495 b = asmrp_operand (p);
497 switch (op) {
498 case ASMRP_SYM_LESS:
499 a = a<b;
500 break;
501 case ASMRP_SYM_LEQ:
502 a = a<=b;
503 break;
504 case ASMRP_SYM_EQUALS:
505 a = a==b;
506 break;
507 case ASMRP_SYM_GEQ:
508 a = a>=b;
509 break;
510 case ASMRP_SYM_GREATER:
511 a = a>b;
512 break;
517 #ifdef LOG
518 printf ("comp_expression done = %d\n", a);
519 #endif
520 return a;
523 static int asmrp_condition (asmrp_t *p) {
525 int a;
527 #ifdef LOG
528 printf ("condition\n");
529 #endif
531 a = asmrp_comp_expression (p);
533 while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) {
534 int op, b;
536 op = p->sym;
538 asmrp_get_sym (p);
540 b = asmrp_comp_expression (p);
542 switch (op) {
543 case ASMRP_SYM_AND:
544 a = a & b;
545 break;
546 case ASMRP_SYM_OR:
547 a = a | b;
548 break;
552 #ifdef LOG
553 printf ("condition done = %d\n", a);
554 #endif
555 return a;
558 static void asmrp_assignment (asmrp_t *p) {
560 #ifdef LOG
561 printf ("assignment\n");
562 #endif
564 if (p->sym == ASMRP_SYM_COMMA || p->sym == ASMRP_SYM_SEMICOLON) {
565 #ifdef LOG
566 printf ("empty assignment\n");
567 #endif
568 return;
571 if (p->sym != ASMRP_SYM_ID) {
572 mp_msg(MSGT_STREAM, MSGL_ERR, "error: identifier expected\n");
573 return;
575 asmrp_get_sym (p);
577 if (p->sym != ASMRP_SYM_EQUALS) {
578 mp_msg(MSGT_STREAM, MSGL_ERR, "error: = expected\n");
579 return;
581 asmrp_get_sym (p);
583 if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING)
584 && (p->sym != ASMRP_SYM_ID)) {
585 mp_msg(MSGT_STREAM, MSGL_ERR, "error: number or string expected\n");
586 return;
588 asmrp_get_sym (p);
590 #ifdef LOG
591 printf ("assignment done\n");
592 #endif
595 static int asmrp_rule (asmrp_t *p) {
597 int ret;
599 #ifdef LOG
600 printf ("rule\n");
601 #endif
603 ret = 1;
605 if (p->sym == ASMRP_SYM_HASH) {
607 asmrp_get_sym (p);
608 ret = asmrp_condition (p);
610 while (p->sym == ASMRP_SYM_COMMA) {
612 asmrp_get_sym (p);
614 asmrp_assignment (p);
617 } else if (p->sym != ASMRP_SYM_SEMICOLON) {
619 asmrp_assignment (p);
621 while (p->sym == ASMRP_SYM_COMMA) {
623 asmrp_get_sym (p);
624 asmrp_assignment (p);
628 #ifdef LOG
629 printf ("rule done = %d\n", ret);
630 #endif
632 if (p->sym != ASMRP_SYM_SEMICOLON) {
633 mp_msg(MSGT_STREAM, MSGL_ERR, "semicolon expected.\n");
634 return ret;
637 asmrp_get_sym (p);
639 return ret;
642 static int asmrp_eval (asmrp_t *p, int *matches) {
644 int rule_num, num_matches;
646 #ifdef LOG
647 printf ("eval\n");
648 #endif
650 asmrp_get_sym (p);
652 rule_num = 0; num_matches = 0;
653 while (p->sym != ASMRP_SYM_EOF) {
655 if (asmrp_rule (p)) {
656 #ifdef LOG
657 printf ("rule #%d is true\n", rule_num);
658 #endif
659 if(num_matches < MAX_RULEMATCHES - 1)
660 matches[num_matches++] = rule_num;
661 else
662 mp_msg(MSGT_STREAM, MSGL_ERR,
663 "Ignoring matched asm rule %d, too many matched rules.\n", rule_num);
666 rule_num++;
669 matches[num_matches] = -1;
670 return num_matches;
673 int asmrp_match (const char *rules, int bandwidth, int *matches) {
675 asmrp_t *p;
676 int num_matches;
678 p = asmrp_new ();
680 asmrp_init (p, rules);
682 asmrp_set_id (p, "Bandwidth", bandwidth);
683 asmrp_set_id (p, "OldPNMPlayer", 0);
685 num_matches = asmrp_eval (p, matches);
687 asmrp_dispose (p);
689 return num_matches;