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