Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

real_asmrp.c

00001 /*
00002  * Copyright (C) 2002-2004 the xine project
00003  *
00004  * This file is part of xine, a free video player.
00005  * 
00006  * xine is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * xine is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00019  *
00020  * $Id$
00021  *
00022  * a parser for real's asm rules
00023  *
00024  * grammar for these rules:
00025  *
00026 
00027    rule_book  = { rule }
00028    rule       = ( '#' condition { ',' assignment } | [ assignment {',' assignment} ]) ';'
00029    assignment = id '=' const
00030    const      = ( number | string )
00031    condition  = comp_expr { ( '&&' | '||' ) comp_expr }
00032    comp_expr  = operand { ( '<' | '<=' | '==' | '>=' | '>' ) operand }
00033    operand    = ( '$' id | num | '(' condition ')' )
00034 
00035  */
00036 
00037 #include "real.h"
00038 
00039 #define ASMRP_SYM_NONE         0
00040 #define ASMRP_SYM_EOF          1
00041 
00042 #define ASMRP_SYM_NUM          2
00043 #define ASMRP_SYM_ID           3
00044 #define ASMRP_SYM_STRING       4
00045 
00046 #define ASMRP_SYM_HASH         10
00047 #define ASMRP_SYM_SEMICOLON    11
00048 #define ASMRP_SYM_COMMA        12
00049 #define ASMRP_SYM_EQUALS       13
00050 #define ASMRP_SYM_AND          14
00051 #define ASMRP_SYM_OR           15
00052 #define ASMRP_SYM_LESS         16
00053 #define ASMRP_SYM_LEQ          17
00054 #define ASMRP_SYM_GEQ          18
00055 #define ASMRP_SYM_GREATER      19
00056 #define ASMRP_SYM_DOLLAR       20
00057 #define ASMRP_SYM_LPAREN       21
00058 #define ASMRP_SYM_RPAREN       22
00059 
00060 #define ASMRP_MAX_ID         1024
00061 
00062 #define ASMRP_MAX_SYMTAB       10
00063 
00064 typedef struct {
00065   char *id;
00066   int   v;
00067 } asmrp_sym_t;
00068 
00069 typedef struct {
00070 
00071   /* public part */
00072 
00073   int         sym;
00074   int         num;
00075   
00076   char        str[ASMRP_MAX_ID];
00077 
00078   /* private part */
00079 
00080   char       *buf;
00081   int         pos;
00082   char        ch;
00083 
00084   asmrp_sym_t sym_tab[ASMRP_MAX_SYMTAB];
00085   int         sym_tab_num;
00086 
00087 } asmrp_t;
00088 
00089 static asmrp_t *asmrp_new () {
00090 
00091   asmrp_t *p;
00092 
00093   p = malloc (sizeof (asmrp_t));
00094 
00095   p->sym_tab_num = 0;
00096   p->sym         = ASMRP_SYM_NONE;
00097   p->buf         = 0;
00098 
00099   return p;
00100 }
00101 
00102 static void asmrp_dispose (asmrp_t *p) {
00103 
00104   int i;
00105 
00106   for (i=0; i<p->sym_tab_num; i++) 
00107     free (p->sym_tab[i].id);
00108 
00109   if (p->buf) free (p->buf);
00110   free (p);
00111 }
00112 
00113 static void asmrp_getch (asmrp_t *p) {
00114   p->ch = p->buf[p->pos];
00115   p->pos++;
00116 
00117   lprintf ("%c\n", p->ch);
00118 
00119 }
00120 
00121 static void asmrp_init (asmrp_t *p, const char *str) {
00122 
00123   p->buf = strdup (str);
00124   p->pos = 0;
00125   
00126   asmrp_getch (p);
00127 }
00128 
00129 static void asmrp_number (asmrp_t *p) {
00130 
00131   int num;
00132 
00133   num = 0;
00134   while ( (p->ch>='0') && (p->ch<='9') ) {
00135 
00136     num = num*10 + (p->ch - '0');
00137 
00138     asmrp_getch (p);
00139   }
00140 
00141   p->sym = ASMRP_SYM_NUM;
00142   p->num = num;
00143 }
00144 
00145 static void asmrp_string (asmrp_t *p) {
00146 
00147   int l;
00148 
00149   l = 0;
00150 
00151   while ( (p->ch!='"') && (p->ch>=32) ) {
00152 
00153     p->str[l] = p->ch;
00154 
00155     l++;
00156     asmrp_getch (p);
00157   }
00158   p->str[l]=0;
00159   
00160   if (p->ch=='"')
00161     asmrp_getch (p);
00162   
00163   p->sym = ASMRP_SYM_STRING;
00164 }
00165 
00166 static void asmrp_identifier (asmrp_t *p) {
00167 
00168   int l;
00169 
00170   l = 0;
00171 
00172   while ( ((p->ch>='A') && (p->ch<='z'))
00173           || ((p->ch>='0') && (p->ch<='9'))) {
00174 
00175     p->str[l] = p->ch;
00176 
00177     l++;
00178     asmrp_getch (p);
00179   }
00180   p->str[l]=0;
00181   
00182   p->sym = ASMRP_SYM_ID;
00183 }
00184 
00185 #ifdef LOG
00186 static void asmrp_print_sym (asmrp_t *p) {
00187 
00188   printf ("symbol: ");
00189 
00190   switch (p->sym) {
00191 
00192   case ASMRP_SYM_NONE:
00193     printf ("NONE\n");
00194     break;
00195 
00196   case ASMRP_SYM_EOF:
00197     printf ("EOF\n");
00198     break;
00199 
00200   case ASMRP_SYM_NUM:
00201     printf ("NUM %d\n", p->num);
00202     break;
00203 
00204   case ASMRP_SYM_ID:
00205     printf ("ID '%s'\n", p->str);
00206     break;
00207 
00208   case ASMRP_SYM_STRING:
00209     printf ("STRING \"%s\"\n", p->str);
00210     break;
00211 
00212   case ASMRP_SYM_HASH:
00213     printf ("#\n");
00214     break;
00215 
00216   case ASMRP_SYM_SEMICOLON:
00217     printf (";\n");
00218     break;
00219   case ASMRP_SYM_COMMA:
00220     printf (",\n");
00221     break;
00222   case ASMRP_SYM_EQUALS:
00223     printf ("==\n");
00224     break;
00225   case ASMRP_SYM_AND:
00226     printf ("&&\n");
00227     break;
00228   case ASMRP_SYM_OR:
00229     printf ("||\n");
00230     break;
00231   case ASMRP_SYM_LESS:
00232     printf ("<\n");
00233     break;
00234   case ASMRP_SYM_LEQ:
00235     printf ("<=\n");
00236     break;
00237   case ASMRP_SYM_GEQ:
00238     printf (">=\n");
00239     break;
00240   case ASMRP_SYM_GREATER:
00241     printf (">\n");
00242     break;
00243   case ASMRP_SYM_DOLLAR:
00244     printf ("$\n");
00245     break;
00246   case ASMRP_SYM_LPAREN:
00247     printf ("(\n");
00248     break;
00249   case ASMRP_SYM_RPAREN:
00250     printf (")\n");
00251     break;
00252 
00253   default:
00254     printf ("unknown symbol %d\n", p->sym);
00255   }
00256 }
00257 #endif
00258 
00259 static void asmrp_get_sym (asmrp_t *p) {
00260 
00261   while (p->ch <= 32) {
00262     if (p->ch == 0) {
00263       p->sym = ASMRP_SYM_EOF;
00264       return;
00265     }
00266 
00267     asmrp_getch (p);
00268   }
00269 
00270   if (p->ch == '\\')
00271     asmrp_getch (p);
00272 
00273   switch (p->ch) {
00274 
00275   case '#':
00276     p->sym = ASMRP_SYM_HASH;
00277     asmrp_getch (p);
00278     break;
00279   case ';':
00280     p->sym = ASMRP_SYM_SEMICOLON;
00281     asmrp_getch (p);
00282     break;
00283   case ',':
00284     p->sym = ASMRP_SYM_COMMA;
00285     asmrp_getch (p);
00286     break;
00287   case '=':
00288     p->sym = ASMRP_SYM_EQUALS;
00289     asmrp_getch (p);
00290     if (p->ch=='=')
00291       asmrp_getch (p);
00292     break;
00293   case '&':
00294     p->sym = ASMRP_SYM_AND;
00295     asmrp_getch (p);
00296     if (p->ch=='&')
00297       asmrp_getch (p);
00298     break;
00299   case '|':
00300     p->sym = ASMRP_SYM_OR;
00301     asmrp_getch (p);
00302     if (p->ch=='|')
00303       asmrp_getch (p);
00304     break;
00305   case '<':
00306     p->sym = ASMRP_SYM_LESS;
00307     asmrp_getch (p);
00308     if (p->ch=='=') {
00309       p->sym = ASMRP_SYM_LEQ;
00310       asmrp_getch (p);
00311     }
00312     break;
00313   case '>':
00314     p->sym = ASMRP_SYM_GREATER;
00315     asmrp_getch (p);
00316     if (p->ch=='=') {
00317       p->sym = ASMRP_SYM_GEQ;
00318       asmrp_getch (p);
00319     }
00320     break;
00321   case '$':
00322     p->sym = ASMRP_SYM_DOLLAR;
00323     asmrp_getch (p);
00324     break;
00325   case '(':
00326     p->sym = ASMRP_SYM_LPAREN;
00327     asmrp_getch (p);
00328     break;
00329   case ')':
00330     p->sym = ASMRP_SYM_RPAREN;
00331     asmrp_getch (p);
00332     break;
00333 
00334   case '"':
00335     asmrp_getch (p);
00336     asmrp_string (p);
00337     break;
00338 
00339   case '0': case '1': case '2': case '3': case '4':
00340   case '5': case '6': case '7': case '8': case '9':
00341     asmrp_number (p);
00342     break;
00343 
00344   default:
00345     asmrp_identifier (p);
00346   }
00347 
00348 #ifdef LOG
00349   asmrp_print_sym (p);
00350 #endif
00351 
00352 }
00353 
00354 static int asmrp_find_id (asmrp_t *p, char *s) {
00355 
00356   int i;
00357 
00358   for (i=0; i<p->sym_tab_num; i++) {
00359     if (!strcmp (s, p->sym_tab[i].id))
00360       return i;
00361   }
00362 
00363   return -1;
00364 }
00365 
00366 static int asmrp_set_id (asmrp_t *p, char *s, int v) {
00367 
00368   int i;
00369 
00370   i = asmrp_find_id (p, s);
00371 
00372   if (i<0) {
00373     i = p->sym_tab_num;
00374     p->sym_tab_num++;
00375     p->sym_tab[i].id = strdup (s);
00376 
00377     lprintf ("new symbol '%s'\n", s);
00378 
00379   }    
00380 
00381   p->sym_tab[i].v = v;
00382  
00383   lprintf ("symbol '%s' assigned %d\n", s, v);
00384 
00385   return i;
00386 }
00387 
00388 static int asmrp_condition (asmrp_t *p) ;
00389 
00390 static int asmrp_operand (asmrp_t *p) {
00391 
00392   int i, ret;
00393   
00394   lprintf ("operand\n");
00395 
00396   ret = 0;
00397 
00398   switch (p->sym) {
00399 
00400   case ASMRP_SYM_DOLLAR:
00401 
00402     asmrp_get_sym (p);
00403     
00404     if (p->sym != ASMRP_SYM_ID) {
00405       printf ("error: identifier expected.\n");
00406       break;
00407     }
00408 
00409     i = asmrp_find_id (p, p->str);
00410     if (i<0) {
00411       lprintf ("error: unknown identifier %s\n", p->str);
00412     }
00413     ret = p->sym_tab[i].v;
00414 
00415     asmrp_get_sym (p);
00416     break;
00417 
00418   case ASMRP_SYM_NUM:
00419     ret = p->num;
00420 
00421     asmrp_get_sym (p);
00422     break;
00423 
00424   case ASMRP_SYM_LPAREN:
00425     asmrp_get_sym (p);
00426 
00427     ret = asmrp_condition (p);
00428 
00429     if (p->sym != ASMRP_SYM_RPAREN) {
00430       printf ("error: ) expected.\n");
00431       break;
00432     }
00433 
00434     asmrp_get_sym (p);
00435     break;
00436 
00437   default:
00438     lprintf ("syntax error, $ number or ( expected\n");
00439     break;
00440   }
00441 
00442   lprintf ("operand done, =%d\n", ret);
00443   
00444   return ret;
00445 }
00446 
00447 static int asmrp_comp_expression (asmrp_t *p) {
00448 
00449   int a;
00450 
00451   lprintf ("comp_expression\n");
00452 
00453   a = asmrp_operand (p);
00454 
00455   while ( (p->sym == ASMRP_SYM_LESS)
00456           || (p->sym == ASMRP_SYM_LEQ)
00457           || (p->sym == ASMRP_SYM_EQUALS)
00458           || (p->sym == ASMRP_SYM_GEQ)
00459           || (p->sym == ASMRP_SYM_GREATER) ) {
00460     int op = p->sym;
00461     int b;
00462 
00463     asmrp_get_sym (p);
00464 
00465     b = asmrp_operand (p);
00466 
00467     switch (op) {
00468     case ASMRP_SYM_LESS:
00469       a = a<b;
00470       break;
00471     case ASMRP_SYM_LEQ:
00472       a = a<=b;
00473       break;
00474     case ASMRP_SYM_EQUALS:
00475       a = a==b;
00476       break;
00477     case ASMRP_SYM_GEQ:
00478       a = a>=b;
00479       break;
00480     case ASMRP_SYM_GREATER:
00481       a = a>b;
00482       break;
00483     }
00484 
00485   }
00486 
00487   lprintf ("comp_expression done = %d\n", a);
00488 
00489   return a;
00490 }
00491 
00492 static int asmrp_condition (asmrp_t *p) {
00493   
00494   int a;
00495 
00496   lprintf ("condition\n");
00497 
00498   a = asmrp_comp_expression (p);
00499 
00500   while ( (p->sym == ASMRP_SYM_AND) || (p->sym == ASMRP_SYM_OR) ) {
00501     int op, b;
00502 
00503     op = p->sym;
00504 
00505     asmrp_get_sym (p);
00506 
00507     b = asmrp_comp_expression (p);
00508 
00509     switch (op) {
00510     case ASMRP_SYM_AND:
00511       a = a & b;
00512       break;
00513     case ASMRP_SYM_OR:
00514       a = a | b;
00515       break;
00516     }
00517   }
00518 
00519   lprintf ("condition done = %d\n", a);
00520 
00521   return a;
00522 }
00523 
00524 static void asmrp_assignment (asmrp_t *p) {
00525 
00526   lprintf ("assignment\n");
00527 
00528   if (p->sym == ASMRP_SYM_COMMA || p->sym == ASMRP_SYM_SEMICOLON) {
00529     lprintf ("empty assignment\n");
00530     return;
00531   }
00532   
00533   if (p->sym != ASMRP_SYM_ID) {
00534     printf ("error: identifier expected\n");
00535     return;
00536   }
00537   asmrp_get_sym (p);
00538 
00539   if (p->sym != ASMRP_SYM_EQUALS) {
00540     printf ("error: = expected\n");
00541     return;
00542   }
00543   asmrp_get_sym (p);
00544 
00545   if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) 
00546        && (p->sym != ASMRP_SYM_ID)) {
00547     printf ("error: number or string expected\n");
00548     return;
00549   }
00550   asmrp_get_sym (p);
00551 
00552   lprintf ("assignment done\n");
00553 }
00554 
00555 static int asmrp_rule (asmrp_t *p) {
00556   
00557   int ret;
00558 
00559   lprintf ("rule\n");
00560 
00561   ret = 1;
00562   
00563   if (p->sym == ASMRP_SYM_HASH) {
00564 
00565     asmrp_get_sym (p);
00566     ret = asmrp_condition (p);
00567 
00568     while (p->sym == ASMRP_SYM_COMMA) {
00569       
00570       asmrp_get_sym (p);
00571       
00572       asmrp_assignment (p);
00573     }
00574 
00575   } else if (p->sym != ASMRP_SYM_SEMICOLON) {
00576 
00577     asmrp_assignment (p);
00578 
00579     while (p->sym == ASMRP_SYM_COMMA) {
00580 
00581       asmrp_get_sym (p);
00582       asmrp_assignment (p);
00583     }
00584   }
00585 
00586   lprintf ("rule done = %d\n", ret);
00587 
00588   if (p->sym != ASMRP_SYM_SEMICOLON) {
00589     printf ("semicolon expected.\n");
00590     return ret;
00591   }
00592 
00593   asmrp_get_sym (p);
00594 
00595   return ret;
00596 }
00597 
00598 static int asmrp_eval (asmrp_t *p, int *matches) {
00599 
00600   int rule_num, num_matches;
00601 
00602   lprintf ("eval\n");
00603 
00604   asmrp_get_sym (p);
00605 
00606   rule_num = 0; num_matches = 0;
00607   while (p->sym != ASMRP_SYM_EOF) {
00608 
00609     if (asmrp_rule (p)) {
00610       lprintf ("rule #%d is true\n", rule_num);
00611 
00612       matches[num_matches] = rule_num;
00613       num_matches++;
00614     }
00615 
00616     rule_num++;
00617   }
00618 
00619   matches[num_matches] = -1;
00620   return num_matches;
00621 }
00622 
00623 int asmrp_match (const char *rules, int bandwidth, int *matches) {
00624 
00625   asmrp_t *p;
00626   int      num_matches;
00627 
00628   p = asmrp_new ();
00629 
00630   asmrp_init (p, rules);
00631 
00632   asmrp_set_id (p, "Bandwidth", bandwidth);
00633   asmrp_set_id (p, "OldPNMPlayer", 0);
00634 
00635   num_matches = asmrp_eval (p, matches);
00636 
00637   asmrp_dispose (p);
00638 
00639   return num_matches;
00640 }
00641 

Generated on Tue Dec 20 10:14:26 2005 for vlc-0.8.4a by  doxygen 1.4.2