Mercurial > mplayer.hg
annotate stream/realrtsp/asmrp.c @ 22129:32a28daf0cf4
beckend -> backend typo fix in printf
author | reimar |
---|---|
date | Mon, 05 Feb 2007 17:15:44 +0000 |
parents | 899739212237 |
children | 80ff3962cef4 |
rev | line source |
---|---|
9922 | 1 /* |
2 * This file was ported to MPlayer from xine CVS asmrp.c,v 1.2 2002/12/17 16:49:48 | |
3 */ | |
4 | |
5 /* | |
6 * Copyright (C) 2002 the xine project | |
7 * | |
8 * This file is part of xine, a free video player. | |
9 * | |
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. | |
14 * | |
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. | |
19 * | |
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 | |
23 * | |
24 * | |
25 * a parser for real's asm rules | |
26 * | |
27 * grammar for these rules: | |
28 * | |
29 | |
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 ')' ) | |
37 | |
38 */ | |
39 | |
40 #include <stdlib.h> | |
41 #include <stdio.h> | |
42 #include <string.h> | |
20701 | 43 #include "mp_msg.h" |
21783
4511c04bc4a0
Fix potential buffer overflow in asm rules matching code
rtogni
parents:
20701
diff
changeset
|
44 #include "asmrp.h" |
9922 | 45 |
46 /* | |
47 #define LOG | |
48 */ | |
49 | |
50 #define ASMRP_SYM_NONE 0 | |
51 #define ASMRP_SYM_EOF 1 | |
52 | |
53 #define ASMRP_SYM_NUM 2 | |
54 #define ASMRP_SYM_ID 3 | |
55 #define ASMRP_SYM_STRING 4 | |
56 | |
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 | |
70 | |
71 #define ASMRP_MAX_ID 1024 | |
72 | |
73 #define ASMRP_MAX_SYMTAB 10 | |
74 | |
75 typedef struct { | |
76 char *id; | |
77 int v; | |
78 } asmrp_sym_t; | |
79 | |
80 typedef struct { | |
81 | |
82 /* public part */ | |
83 | |
84 int sym; | |
85 int num; | |
86 | |
87 char str[ASMRP_MAX_ID]; | |
88 | |
89 /* private part */ | |
90 | |
91 char *buf; | |
92 int pos; | |
93 char ch; | |
94 | |
95 asmrp_sym_t sym_tab[ASMRP_MAX_SYMTAB]; | |
96 int sym_tab_num; | |
97 | |
98 } asmrp_t; | |
99 | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
13203
diff
changeset
|
100 static asmrp_t *asmrp_new (void) { |
9922 | 101 |
102 asmrp_t *p; | |
103 | |
104 p = malloc (sizeof (asmrp_t)); | |
105 | |
106 p->sym_tab_num = 0; | |
107 p->sym = ASMRP_SYM_NONE; | |
108 | |
109 return p; | |
110 } | |
111 | |
112 static void asmrp_dispose (asmrp_t *p) { | |
113 | |
114 int i; | |
115 | |
116 for (i=0; i<p->sym_tab_num; i++) | |
117 free (p->sym_tab[i].id); | |
118 | |
119 free (p); | |
120 } | |
121 | |
122 static void asmrp_getch (asmrp_t *p) { | |
123 p->ch = p->buf[p->pos]; | |
124 p->pos++; | |
125 | |
126 #ifdef LOG | |
127 printf ("%c\n", p->ch); | |
128 #endif | |
129 | |
130 } | |
131 | |
132 static void asmrp_init (asmrp_t *p, const char *str) { | |
133 | |
134 p->buf = strdup (str); | |
135 p->pos = 0; | |
136 | |
137 asmrp_getch (p); | |
138 } | |
139 | |
140 static void asmrp_number (asmrp_t *p) { | |
141 | |
142 int num; | |
143 | |
144 num = 0; | |
145 while ( (p->ch>='0') && (p->ch<='9') ) { | |
146 | |
147 num = num*10 + (p->ch - '0'); | |
148 | |
149 asmrp_getch (p); | |
150 } | |
151 | |
152 p->sym = ASMRP_SYM_NUM; | |
153 p->num = num; | |
154 } | |
155 | |
156 static void asmrp_string (asmrp_t *p) { | |
157 | |
158 int l; | |
159 | |
160 l = 0; | |
161 | |
162 while ( (p->ch!='"') && (p->ch>=32) ) { | |
163 | |
164 p->str[l] = p->ch; | |
165 | |
166 l++; | |
167 asmrp_getch (p); | |
168 } | |
169 p->str[l]=0; | |
170 | |
171 if (p->ch=='"') | |
172 asmrp_getch (p); | |
173 | |
174 p->sym = ASMRP_SYM_STRING; | |
175 } | |
176 | |
177 static void asmrp_identifier (asmrp_t *p) { | |
178 | |
179 int l; | |
180 | |
181 l = 0; | |
182 | |
183 while ( ((p->ch>='A') && (p->ch<='z')) | |
184 || ((p->ch>='0') && (p->ch<='9'))) { | |
185 | |
186 p->str[l] = p->ch; | |
187 | |
188 l++; | |
189 asmrp_getch (p); | |
190 } | |
191 p->str[l]=0; | |
192 | |
193 p->sym = ASMRP_SYM_ID; | |
194 } | |
195 | |
196 #ifdef LOG | |
197 static void asmrp_print_sym (asmrp_t *p) { | |
198 | |
199 printf ("symbol: "); | |
200 | |
201 switch (p->sym) { | |
202 | |
203 case ASMRP_SYM_NONE: | |
204 printf ("NONE\n"); | |
205 break; | |
206 | |
207 case ASMRP_SYM_EOF: | |
208 printf ("EOF\n"); | |
209 break; | |
210 | |
211 case ASMRP_SYM_NUM: | |
212 printf ("NUM %d\n", p->num); | |
213 break; | |
214 | |
215 case ASMRP_SYM_ID: | |
216 printf ("ID '%s'\n", p->str); | |
217 break; | |
218 | |
219 case ASMRP_SYM_STRING: | |
220 printf ("STRING \"%s\"\n", p->str); | |
221 break; | |
222 | |
223 case ASMRP_SYM_HASH: | |
224 printf ("#\n"); | |
225 break; | |
226 | |
227 case ASMRP_SYM_SEMICOLON: | |
228 printf (";\n"); | |
229 break; | |
230 case ASMRP_SYM_COMMA: | |
231 printf (",\n"); | |
232 break; | |
233 case ASMRP_SYM_EQUALS: | |
234 printf ("==\n"); | |
235 break; | |
236 case ASMRP_SYM_AND: | |
237 printf ("&&\n"); | |
238 break; | |
239 case ASMRP_SYM_OR: | |
240 printf ("||\n"); | |
241 break; | |
242 case ASMRP_SYM_LESS: | |
243 printf ("<\n"); | |
244 break; | |
245 case ASMRP_SYM_LEQ: | |
246 printf ("<=\n"); | |
247 break; | |
248 case ASMRP_SYM_GEQ: | |
249 printf (">=\n"); | |
250 break; | |
251 case ASMRP_SYM_GREATER: | |
252 printf (">\n"); | |
253 break; | |
254 case ASMRP_SYM_DOLLAR: | |
255 printf ("$\n"); | |
256 break; | |
257 case ASMRP_SYM_LPAREN: | |
258 printf ("(\n"); | |
259 break; | |
260 case ASMRP_SYM_RPAREN: | |
261 printf (")\n"); | |
262 break; | |
263 | |
264 default: | |
265 printf ("unknown symbol %d\n", p->sym); | |
266 } | |
267 } | |
268 #endif | |
269 | |
270 static void asmrp_get_sym (asmrp_t *p) { | |
271 | |
272 while (p->ch <= 32) { | |
273 if (p->ch == 0) { | |
274 p->sym = ASMRP_SYM_EOF; | |
275 return; | |
276 } | |
277 | |
278 asmrp_getch (p); | |
279 } | |
280 | |
281 if (p->ch == '\\') | |
282 asmrp_getch (p); | |
283 | |
284 switch (p->ch) { | |
285 | |
286 case '#': | |
287 p->sym = ASMRP_SYM_HASH; | |
288 asmrp_getch (p); | |
289 break; | |
290 case ';': | |
291 p->sym = ASMRP_SYM_SEMICOLON; | |
292 asmrp_getch (p); | |
293 break; | |
294 case ',': | |
295 p->sym = ASMRP_SYM_COMMA; | |
296 asmrp_getch (p); | |
297 break; | |
298 case '=': | |
299 p->sym = ASMRP_SYM_EQUALS; | |
300 asmrp_getch (p); | |
301 if (p->ch=='=') | |
302 asmrp_getch (p); | |
303 break; | |
304 case '&': | |
305 p->sym = ASMRP_SYM_AND; | |
306 asmrp_getch (p); | |
307 if (p->ch=='&') | |
308 asmrp_getch (p); | |
309 break; | |
310 case '|': | |
311 p->sym = ASMRP_SYM_OR; | |
312 asmrp_getch (p); | |
313 if (p->ch=='|') | |
314 asmrp_getch (p); | |
315 break; | |
316 case '<': | |
317 p->sym = ASMRP_SYM_LESS; | |
318 asmrp_getch (p); | |
319 if (p->ch=='=') { | |
320 p->sym = ASMRP_SYM_LEQ; | |
321 asmrp_getch (p); | |
322 } | |
323 break; | |
324 case '>': | |
325 p->sym = ASMRP_SYM_GREATER; | |
326 asmrp_getch (p); | |
327 if (p->ch=='=') { | |
328 p->sym = ASMRP_SYM_GEQ; | |
329 asmrp_getch (p); | |
330 } | |
331 break; | |
332 case '$': | |
333 p->sym = ASMRP_SYM_DOLLAR; | |
334 asmrp_getch (p); | |
335 break; | |
336 case '(': | |
337 p->sym = ASMRP_SYM_LPAREN; | |
338 asmrp_getch (p); | |
339 break; | |
340 case ')': | |
341 p->sym = ASMRP_SYM_RPAREN; | |
342 asmrp_getch (p); | |
343 break; | |
344 | |
345 case '"': | |
346 asmrp_getch (p); | |
347 asmrp_string (p); | |
348 break; | |
349 | |
350 case '0': case '1': case '2': case '3': case '4': | |
351 case '5': case '6': case '7': case '8': case '9': | |
352 asmrp_number (p); | |
353 break; | |
354 | |
355 default: | |
356 asmrp_identifier (p); | |
357 } | |
358 | |
359 #ifdef LOG | |
360 asmrp_print_sym (p); | |
361 #endif | |
362 | |
363 } | |
364 | |
365 static int asmrp_find_id (asmrp_t *p, char *s) { | |
366 | |
367 int i; | |
368 | |
369 for (i=0; i<p->sym_tab_num; i++) { | |
370 if (!strcmp (s, p->sym_tab[i].id)) | |
371 return i; | |
372 } | |
373 | |
374 return -1; | |
375 } | |
376 | |
377 static int asmrp_set_id (asmrp_t *p, char *s, int v) { | |
378 | |
379 int i; | |
380 | |
381 i = asmrp_find_id (p, s); | |
382 | |
383 if (i<0) { | |
384 i = p->sym_tab_num; | |
385 p->sym_tab_num++; | |
386 p->sym_tab[i].id = strdup (s); | |
387 | |
388 #ifdef LOG | |
389 printf ("new symbol '%s'\n", s); | |
390 #endif | |
391 | |
392 } | |
393 | |
394 p->sym_tab[i].v = v; | |
395 | |
396 #ifdef LOG | |
397 printf ("symbol '%s' assigned %d\n", s, v); | |
398 #endif | |
399 | |
400 return i; | |
401 } | |
402 | |
403 static int asmrp_condition (asmrp_t *p) ; | |
404 | |
405 static int asmrp_operand (asmrp_t *p) { | |
406 | |
407 int i, ret; | |
408 | |
409 #ifdef LOG | |
410 printf ("operand\n"); | |
411 #endif | |
412 | |
413 ret = 0; | |
414 | |
415 switch (p->sym) { | |
416 | |
417 case ASMRP_SYM_DOLLAR: | |
418 | |
419 asmrp_get_sym (p); | |
420 | |
421 if (p->sym != ASMRP_SYM_ID) { | |
20699 | 422 mp_msg(MSGT_STREAM, MSGL_ERR, "error: identifier expected.\n"); |
20697 | 423 break; |
9922 | 424 } |
425 | |
426 i = asmrp_find_id (p, p->str); | |
427 if (i<0) { | |
20699 | 428 mp_msg(MSGT_STREAM, MSGL_ERR, "error: unknown identifier %s\n", p->str); |
21787
899739212237
Fix invalid memory access if identifier is unknown
rtogni
parents:
21783
diff
changeset
|
429 } else |
9922 | 430 ret = p->sym_tab[i].v; |
431 | |
432 asmrp_get_sym (p); | |
433 break; | |
434 | |
435 case ASMRP_SYM_NUM: | |
436 ret = p->num; | |
437 | |
438 asmrp_get_sym (p); | |
439 break; | |
440 | |
441 case ASMRP_SYM_LPAREN: | |
442 asmrp_get_sym (p); | |
443 | |
444 ret = asmrp_condition (p); | |
445 | |
446 if (p->sym != ASMRP_SYM_RPAREN) { | |
20699 | 447 mp_msg(MSGT_STREAM, MSGL_ERR, "error: ) expected.\n"); |
20697 | 448 break; |
9922 | 449 } |
450 | |
451 asmrp_get_sym (p); | |
452 break; | |
453 | |
454 default: | |
20699 | 455 mp_msg(MSGT_STREAM, MSGL_ERR, "syntax error, $ number or ( expected\n"); |
9922 | 456 } |
457 | |
458 #ifdef LOG | |
459 printf ("operand done, =%d\n", ret); | |
460 #endif | |
461 | |
462 return ret; | |
463 } | |
464 | |
20697 | 465 |
9922 | 466 static int asmrp_comp_expression (asmrp_t *p) { |
467 | |
468 int a; | |
469 | |
470 #ifdef LOG | |
471 printf ("comp_expression\n"); | |
472 #endif | |
473 | |
474 a = asmrp_operand (p); | |
475 | |
476 while ( (p->sym == ASMRP_SYM_LESS) | |
477 || (p->sym == ASMRP_SYM_LEQ) | |
478 || (p->sym == ASMRP_SYM_EQUALS) | |
479 || (p->sym == ASMRP_SYM_GEQ) | |
480 || (p->sym == ASMRP_SYM_GREATER) ) { | |
481 int op = p->sym; | |
482 int b; | |
483 | |
484 asmrp_get_sym (p); | |
485 | |
486 b = asmrp_operand (p); | |
487 | |
488 switch (op) { | |
489 case ASMRP_SYM_LESS: | |
490 a = a<b; | |
491 break; | |
492 case ASMRP_SYM_LEQ: | |
493 a = a<=b; | |
494 break; | |
495 case ASMRP_SYM_EQUALS: | |
496 a = a==b; | |
497 break; | |
498 case ASMRP_SYM_GEQ: | |
499 a = a>=b; | |
500 break; | |
501 case ASMRP_SYM_GREATER: | |
502 a = a>b; | |
503 break; | |
504 } | |
505 | |
506 } | |
507 | |
508 #ifdef LOG | |
509 printf ("comp_expression done = %d\n", a); | |
510 #endif | |
511 return a; | |
512 } | |
513 | |
514 static int asmrp_condition (asmrp_t *p) { | |
515 | |
516 int a; | |
517 | |
518 #ifdef LOG | |
519 printf ("condition\n"); | |
520 #endif | |
521 | |
522 a = asmrp_comp_expression (p); | |
523 | |
524 while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) { | |
525 int op, b; | |
526 | |
527 op = p->sym; | |
528 | |
529 asmrp_get_sym (p); | |
530 | |
531 b = asmrp_comp_expression (p); | |
532 | |
533 switch (op) { | |
534 case ASMRP_SYM_AND: | |
535 a = a & b; | |
536 break; | |
537 case ASMRP_SYM_OR: | |
538 a = a | b; | |
539 break; | |
540 } | |
541 } | |
542 | |
543 #ifdef LOG | |
544 printf ("condition done = %d\n", a); | |
545 #endif | |
546 return a; | |
547 } | |
548 | |
549 static void asmrp_assignment (asmrp_t *p) { | |
550 | |
551 #ifdef LOG | |
552 printf ("assignment\n"); | |
553 #endif | |
554 | |
13203
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
555 if (p->sym == ASMRP_SYM_COMMA || p->sym == ASMRP_SYM_SEMICOLON) { |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
556 #ifdef LOG |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
557 printf ("empty assignment\n"); |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
558 #endif |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
559 return; |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
560 } |
0d38a501c6a5
allow empty assignments, necessary for some weird servers...
reimar
parents:
9922
diff
changeset
|
561 |
9922 | 562 if (p->sym != ASMRP_SYM_ID) { |
20699 | 563 mp_msg(MSGT_STREAM, MSGL_ERR, "error: identifier expected\n"); |
20697 | 564 return; |
9922 | 565 } |
566 asmrp_get_sym (p); | |
567 | |
568 if (p->sym != ASMRP_SYM_EQUALS) { | |
20699 | 569 mp_msg(MSGT_STREAM, MSGL_ERR, "error: = expected\n"); |
20697 | 570 return; |
9922 | 571 } |
572 asmrp_get_sym (p); | |
573 | |
574 if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) | |
575 && (p->sym != ASMRP_SYM_ID)) { | |
20699 | 576 mp_msg(MSGT_STREAM, MSGL_ERR, "error: number or string expected\n"); |
20697 | 577 return; |
9922 | 578 } |
579 asmrp_get_sym (p); | |
580 | |
581 #ifdef LOG | |
582 printf ("assignment done\n"); | |
583 #endif | |
584 } | |
585 | |
586 static int asmrp_rule (asmrp_t *p) { | |
587 | |
588 int ret; | |
589 | |
590 #ifdef LOG | |
591 printf ("rule\n"); | |
592 #endif | |
593 | |
594 ret = 1; | |
595 | |
596 if (p->sym == ASMRP_SYM_HASH) { | |
597 | |
598 asmrp_get_sym (p); | |
599 ret = asmrp_condition (p); | |
600 | |
601 while (p->sym == ASMRP_SYM_COMMA) { | |
602 | |
603 asmrp_get_sym (p); | |
604 | |
605 asmrp_assignment (p); | |
606 } | |
607 | |
608 } else if (p->sym != ASMRP_SYM_SEMICOLON) { | |
609 | |
610 asmrp_assignment (p); | |
611 | |
612 while (p->sym == ASMRP_SYM_COMMA) { | |
613 | |
614 asmrp_get_sym (p); | |
615 asmrp_assignment (p); | |
616 } | |
617 } | |
618 | |
619 #ifdef LOG | |
620 printf ("rule done = %d\n", ret); | |
621 #endif | |
622 | |
623 if (p->sym != ASMRP_SYM_SEMICOLON) { | |
20699 | 624 mp_msg(MSGT_STREAM, MSGL_ERR, "semicolon expected.\n"); |
20697 | 625 return ret; |
9922 | 626 } |
627 | |
628 asmrp_get_sym (p); | |
629 | |
630 return ret; | |
631 } | |
632 | |
633 static int asmrp_eval (asmrp_t *p, int *matches) { | |
634 | |
635 int rule_num, num_matches; | |
636 | |
637 #ifdef LOG | |
638 printf ("eval\n"); | |
639 #endif | |
640 | |
641 asmrp_get_sym (p); | |
642 | |
643 rule_num = 0; num_matches = 0; | |
644 while (p->sym != ASMRP_SYM_EOF) { | |
645 | |
646 if (asmrp_rule (p)) { | |
647 #ifdef LOG | |
648 printf ("rule #%d is true\n", rule_num); | |
649 #endif | |
21783
4511c04bc4a0
Fix potential buffer overflow in asm rules matching code
rtogni
parents:
20701
diff
changeset
|
650 if(num_matches < MAX_RULEMATCHES - 1) |
4511c04bc4a0
Fix potential buffer overflow in asm rules matching code
rtogni
parents:
20701
diff
changeset
|
651 matches[num_matches++] = rule_num; |
4511c04bc4a0
Fix potential buffer overflow in asm rules matching code
rtogni
parents:
20701
diff
changeset
|
652 else |
4511c04bc4a0
Fix potential buffer overflow in asm rules matching code
rtogni
parents:
20701
diff
changeset
|
653 mp_msg(MSGT_STREAM, MSGL_ERR, |
4511c04bc4a0
Fix potential buffer overflow in asm rules matching code
rtogni
parents:
20701
diff
changeset
|
654 "Ignoring matched asm rule %d, too many matched rules.\n", rule_num); |
9922 | 655 } |
656 | |
657 rule_num++; | |
658 } | |
659 | |
660 matches[num_matches] = -1; | |
661 return num_matches; | |
662 } | |
663 | |
664 int asmrp_match (const char *rules, int bandwidth, int *matches) { | |
665 | |
666 asmrp_t *p; | |
667 int num_matches; | |
668 | |
669 p = asmrp_new (); | |
670 | |
671 asmrp_init (p, rules); | |
672 | |
673 asmrp_set_id (p, "Bandwidth", bandwidth); | |
674 asmrp_set_id (p, "OldPNMPlayer", 0); | |
675 | |
676 num_matches = asmrp_eval (p, matches); | |
677 | |
678 asmrp_dispose (p); | |
679 | |
680 return num_matches; | |
681 } | |
682 |