Main Page | Class List | File List | Class Members | File Members

med.c

Go to the documentation of this file.
00001 /*
00002  * This file handles the multiplex table entry descriptors.
00003  *
00004  * Format for MED strings (and examples):  See H.223.
00005  *  
00006  * External Interface:
00007  * 
00008  * mux_table_entry *new_mux_table(char *name);
00009  * 
00010  */
00011 #include <stdio.h>
00012 #include "med.h"
00013 
00014 extern int debug;
00015 
00016 
00017 int prefix (char *s1, char *s2)
00018      /* 
00019       * Returns 1 iff s1 is a prefix of s2.
00020       */
00021 {
00022   while ((*s1) && (*s2) && (*s1==*s2)) {
00023     s1++;
00024     s2++;
00025   }
00026   return (!*s1);
00027 }
00028 
00029 
00030 static void upstring(char *s)
00031      /*
00032       * Converts a string to upper case.  Assumes ASCII.
00033       */
00034 {
00035   while (*s) {
00036     if ((*s >= 'a') && (*s <= 'z'))
00037       *s = *s - 'a' + 'A';
00038     s++;
00039   }
00040 }
00041 
00042 
00043 static void stripwhitespace(char *s)
00044      /*
00045       * This function does exactly what it says it does.
00046       */
00047 {
00048   char *r = s;
00049 
00050   while (*s) {
00051     if ((*s!=' ') && (*s!='\t') && (*s!='\n')) {
00052       *r=*s;
00053       r++;
00054     }
00055     s++;
00056   }
00057   *r='\0';
00058 }
00059 
00060 
00061 static int balanced(char *s)
00062      /*
00063       * Returns 1 iff the sequence of {'s and }'s in *s forms a DYCK word. 
00064       */
00065 {
00066   int leftbraces=0,rightbraces=0;
00067   int good=1;
00068   while (*s) {
00069     if (*s=='{')
00070       leftbraces++;
00071     else if (*s=='}')
00072       rightbraces++;
00073     if (rightbraces > leftbraces)
00074       good = 0;
00075     s++;
00076   }
00077   return((good) && (leftbraces==rightbraces));
00078 }
00079 
00080 
00081 static int atom(char *s)
00082      /*
00083       * Returns 1 iff prefix(s) is an atom (i.e. one { followed by one }).  
00084       */
00085 {
00086   int leftbraces=0;
00087   while ((*s) && (*s != '}')) {
00088     if (*s=='{')
00089       leftbraces++;
00090     s++;
00091   }
00092   return(leftbraces==1);
00093 }
00094 
00095 
00096 
00097 static char *advance_past_comma(char *s)
00098 /*
00099  * Advances to just past the next comma, ignoring stuff in nested {}'s. 
00100  */
00101 {
00102   int paren=0;
00103   while (*s) {
00104     if (*s=='{')
00105       paren++;
00106     else if (*s=='}')
00107       paren--;
00108     else if ((*s==',') && (paren==0)) {
00109       s++;
00110       break;
00111     }
00112     s++;
00113   }
00114   return (s);
00115 }
00116 
00117 
00118 static med *new_med(void)
00119 {
00120   med *bob = (med *) malloc(sizeof(med));
00121   if (bob==NULL) {
00122     fflush(stdout);
00123     fprintf(stderr, "new_med(): malloc() returned NULL.\n");
00124     exit(1);
00125   }
00126   return(bob);
00127 }
00128 
00129 
00130 
00131 
00132 
00133 /* 
00134  * Variable used by check_med() and check_med1()
00135  */
00136 static int depth;               
00137 static int gotucf;
00138 
00139 static void check_med1(med *m)
00140 {
00141   depth++;
00142   while (m != NULL) {
00143     if (m->type == MedList)
00144       check_med1(m->list);
00145     if (m->rc == UCF) {
00146       if (gotucf) {
00147         fflush(stdout);
00148         fprintf(stderr, "check_med1(): Multiple 'RC UCF's are not allowed.\n");
00149         exit(1);
00150       }
00151       else {
00152         gotucf=1;
00153       }
00154       if (depth > 1) {
00155         fflush(stdout);
00156         fprintf(stderr, "check_med1(): 'RC UCF's not allowed in a nested sub-expression.\n");
00157         exit(1);
00158       } 
00159     }
00160     m = m->next;
00161   }
00162   depth--;
00163 }
00164 
00165 static void check_med(med *m)
00166 /*
00167  * Checks multiplex entry for multiple RC UCF's or an RC UCF in a nested sub-expression.
00168  * Most of the code is in check_med1();
00169  */
00170 {
00171   depth=0;
00172   gotucf=0;
00173 
00174   check_med1(m);
00175 
00176   while (m->next != NULL) {
00177     m = m->next;
00178   }
00179 
00180   if ((m->next == NULL) && (m->rc != UCF)) {
00181     printf("check_med(): Last entry in MultiplexEntryDescriptor should contain a 'RC UCF'.\n");
00182     exit(1);
00183   }
00184 }
00185 
00186 
00187 
00188 /*
00189  * Main parsing functions. 
00190  */
00191 
00192 static med *parse_med1(char *s)
00193      /*
00194       * Returns a med structure from a string (i.e., a pointer to the start 
00195       * of a MED list).  String is expected to have been removed of whitespace
00196       * and converted to uppercase.
00197       *
00198       * Recursion: See *parse_med(char *s).
00199       *
00200       */
00201 {
00202   int i=0, paren=0;
00203   char *r, *t;
00204   med *head, *bob;
00205 
00206   /*
00207    * Two possible cases here.  Either we have something like "{LCN<i>,RC<j>}",
00208    * or we have something like "{{...}, ..., RC<j>}".
00209    */
00210   
00211   s++;
00212   if (*s == '{') { 
00213     /* 
00214      * Make a list, recursing when necessary. 
00215      */
00216     head = new_med();
00217     head->type = MedList;
00218     head->next = NULL;
00219 
00220     head->list = bob = parse_med1(s);
00221     
00222     s = advance_past_comma(s);
00223     
00224     while (*s == '{') {
00225       bob->next = parse_med1(s);
00226       bob = bob->next;
00227       bob->next = NULL;
00228 
00229       s = advance_past_comma(s);
00230     }
00231 
00232     if (prefix("RCUCF", s)) {
00233       head->rc = UCF;
00234     }
00235     else if (prefix("RC", s)) {      head->rc = atoi(s+2);
00236     }
00237     else {
00238       fflush(stdout);
00239       fprintf(stderr, "parse_med1(): Parse error at %s.\n", s);
00240       exit(1);
00241     }
00242   } 
00243   /* Base case (just a single channel) */
00244   else {
00245     if (prefix("LCN", s)) {
00246       head = new_med();
00247       s+=3;
00248       head->type = MedAtom;
00249       head->ch = atoi(s);
00250       head->next = NULL;
00251       
00252       s = advance_past_comma(s);
00253       if (prefix("RCUCF", s)) {
00254         head->rc = UCF;
00255       }
00256       else if (prefix("RC", s)) {
00257         head->rc = atoi(s+2);
00258       }
00259       else {
00260         fflush(stdout);
00261         fprintf(stdout,"parse_med1(): Parse_error at %s.\n", s);
00262         exit(1);
00263       }
00264     }
00265     else {
00266       fflush(stdout);
00267       fprintf(stderr,"parse_med1(): Parse error at %s.\n", s);
00268       exit(1);
00269     }
00270   }   
00271   return (head);
00272 }
00273 
00274 
00275 static med *parse_med(char *s)
00276      /*
00277       * This is the toplevel function. 
00278       * The top layer is different, since we can have stuff like:
00279       * {...},{...}
00280       */
00281 {
00282   med *bob, *alice;
00283 
00284   upstring(s);
00285   stripwhitespace(s);
00286   
00287   if (!balanced(s)) {
00288     printf("Error: Unbalanced {}'s.\n");
00289   }
00290 
00291   if (*s != '{') {
00292     fflush(stdout);
00293     fprintf(stderr, "parse_med(): Parse error at %s.\n", s);
00294     exit(1);
00295   }
00296   bob = alice = parse_med1(s);
00297   
00298   s = advance_past_comma(s);
00299   
00300   while (*s) {
00301     alice->next = parse_med1(s);
00302     alice = alice->next;
00303     alice->next = NULL;
00304     s = advance_past_comma(s);
00305   }
00306 
00307   check_med(bob);
00308   return(bob);
00309 }
00310 
00311 
00312 static void print_med(med *m)
00313      /*
00314       * Prints out the med pointed to by m.
00315       *
00316       * Is recursive (i.e. See print_med(med *m)).
00317       */
00318 {
00319   while (m != NULL) {
00320     printf("{");
00321     if (m->type == MedAtom) {
00322       printf("LCN%d", m->ch);
00323     } 
00324     else {
00325       print_med(m->list);
00326     }
00327     if (m->rc == -1)
00328       printf(",RC UCF}");
00329     else
00330       printf(",RC %d}", m->rc);
00331     if (m->next != NULL)
00332       printf(",");
00333     m = m->next;
00334   }
00335 }
00336 
00337 
00338 static void print_sample(med *m)
00339      /* 
00340       * Prints out a sample of what output the code will produce. 
00341       *
00342       * Ex.  {{LCN1,RC5},{LCN2,RC2},RC UCF} will produce:
00343       *
00344       * 1111122 repeat until closing flag
00345       */
00346 {
00347   int i;
00348 
00349   while (m) {
00350     if (m->type == MedAtom) {
00351       if (m->rc == UCF) {
00352         printf("{%d} repeat until closing flag", m->ch);
00353       }
00354       else {
00355         for (i=0;i<m->rc;i++) {
00356           printf("%d", m->ch);
00357         }
00358       }
00359     }
00360     else if (m->type == MedList) {
00361       if (m->rc == UCF) {
00362         printf("{");
00363         print_sample(m->list);
00364         printf("} repeat until closing flag");
00365       }
00366       else {
00367         for (i=0; i<m->rc; i++) {
00368           print_sample(m->list);
00369         }
00370       }
00371     }
00372     m = m->next;
00373   }
00374 }
00375 
00376 
00377 static int figure_length1(med *m)
00378      /*
00379       * Only called on (*m)'s of depth greater than 1 from valid 
00380       * MultiplexEntryDescriptors.  Therefore we can ignore
00381       * checking for RC UCF's.  
00382       */
00383 {
00384   int sum=0;
00385   while (m != NULL) {
00386     if (m->type == MedAtom) {
00387       sum += m->rc;
00388     } 
00389     else {
00390       sum += m->rc * figure_length1(m->list);
00391     }
00392     m = m->next;
00393   }
00394   return (sum);
00395 }
00396 
00397 static int figure_length(med *m)
00398      /*
00399       * Figure out the length of a pattern a med produces.  
00400       * Do not follow (*next) pointers of (*m).
00401       */
00402 {
00403   int sum=0;
00404   if (m->type == MedAtom) {
00405     if (m->rc == UCF)
00406       sum = 1;
00407     else
00408       sum = m->rc;
00409   }
00410   else {
00411     if (m->rc == UCF) {
00412       sum += figure_length1(m->list);
00413     }
00414     else {
00415       sum += m->rc * figure_length1(m->list);
00416     }
00417   }
00418   return(sum);
00419 }
00420 
00421 
00422 static void write_pattern1(int *pattern, int *offset, med *m)
00423      /*
00424       * We won't overwrite the (*pattern) array, because I checked how 
00425       * big to make it before the call to this function.  
00426       */ 
00427 {
00428   int i;
00429   while (m != NULL) { 
00430     if (m->type == MedAtom) {
00431       if (m->rc == UCF) {
00432         pattern[(*offset)++]=m->ch;
00433       }
00434       else {
00435         for (i=0; i<m->rc; i++)
00436           pattern[(*offset)++]=m->ch;
00437       }
00438     }
00439     else if (m->type == MedList) {
00440       if (m->rc == UCF) {
00441         write_pattern1(pattern, offset, m->list);
00442       }
00443       else {
00444         for (i=0; i<m->rc; i++)
00445           write_pattern1(pattern, offset, m->list);
00446       }
00447     }
00448     m = m->next;
00449   }
00450 }
00451 
00452 
00453 static void write_pattern(int *pattern, int *offset, med *m)
00454      /*
00455       * We won't overwrite the (*pattern) array, because I checked how 
00456       * big to make it before the call to this function.  
00457       */ 
00458 {
00459   int i;
00460 
00461   if (m->type == MedAtom) {
00462     if (m->rc == UCF) {
00463       pattern[(*offset)++]=m->ch;
00464     }
00465     else {
00466       for (i=0; i<m->rc; i++)
00467         pattern[(*offset)++]=m->ch;
00468     }
00469   }
00470   else if (m->type == MedList) {
00471     if (m->rc == UCF) {
00472       write_pattern1(pattern, offset, m->list);
00473     }
00474     else {
00475       for (i=0; i<m->rc; i++)
00476         write_pattern1(pattern, offset, m->list);
00477     }
00478   }
00479 }
00480 
00481 
00482 
00483 static med_pattern *make_pattern(med *m)
00484      /*
00485       * Makes a pattern for putting data in a MUX-PDU payload packet 
00486       * or removing data from a MUX-PDU payload.
00487       * 
00488       * Assumes (*m) is a vaild med structure;
00489       * 
00490       * See med.h for struct med_pattern.
00491       * 
00492       * Since logical channel numbers can only be between 0 and 65535, 
00493       * (according to H.223/AnnexA), an unnsigned short int array would 
00494       * suffice.  If logical channel numbers were between 0 and 255, an 
00495       * unsigned char would be fine.  I don't really care about storage, 
00496       * so I'm making them natural ints.
00497       */
00498 {
00499   med_pattern *pat; 
00500   med *save_m;
00501   int x, y;
00502 
00503   pat = (med_pattern *) malloc(sizeof(med_pattern));
00504   if (debug)
00505     printf("make_pattern at %x...............................................\n",pat);
00506   if (pat == NULL) {
00507     /* 
00508      * I hate running out of memory.
00509      */
00510     warn("make_pattern", "malloc failed");
00511   }
00512   else {
00513     /*
00514      * First figure out how much space to allocate for patterns.
00515      */
00516     pat->non_repeating_part_length = 0;
00517     pat->non_repeating_part = NULL;
00518     pat->repeating_part_length = 0;
00519     pat->repeating_part = NULL;
00520     save_m = m;
00521     while (m != NULL) {
00522       if (m->rc != UCF)
00523         pat->non_repeating_part_length += figure_length(m);
00524       else
00525         pat->repeating_part_length += figure_length(m);
00526 
00527       m = m->next;
00528     }
00529     pat->non_repeating_part = (int *) malloc(pat->non_repeating_part_length * sizeof(int));
00530     pat->repeating_part = (int *) malloc(pat->repeating_part_length * sizeof(int));
00531 
00532     if (((pat->non_repeating_part == NULL)&&(pat->non_repeating_part_length>0)) ||
00533         ((pat->repeating_part == NULL)&&(pat->repeating_part_length>0))) {
00534       warn("make_pattern", "malloc failed");
00535     }
00536     else {
00537       m = save_m;
00538       x = 0;
00539       y = 0;
00540       while (m != NULL) {
00541         if (m->rc != UCF) {
00542           write_pattern(pat->non_repeating_part, &x, m);
00543         } 
00544         else {
00545           write_pattern(pat->repeating_part, &y, m);
00546         }
00547         m = m->next;
00548       } 
00549     }
00550   }
00551   return (pat);
00552 }
00553 
00554 
00555 static void print_pattern(med_pattern *pat)
00556 {
00557   int i;
00558   printf("non-repeating part length: %d\n", pat->non_repeating_part_length);
00559   printf("non-repeating part: ");
00560   for (i=0; i<pat->non_repeating_part_length; i++) 
00561     printf("%d", pat->non_repeating_part[i]);
00562   printf("\n");
00563   printf("repeating part length: %d\n", pat->repeating_part_length);
00564   printf("repeating part    : ");
00565   for (i=0; i<pat->repeating_part_length; i++) 
00566     printf("%d", pat->repeating_part[i]);
00567   printf("\n");
00568 }
00569 
00570 
00571 
00572 void add_to_mux_table(mux_table_entry *mt, int *size, char *medstr)
00573 {
00574   mt[*size].entry = parse_med(medstr);
00575   mt[*size].pattern = make_pattern(mt[*size].entry);
00576   
00577   if (debug)
00578     print_pattern(mt[*size].pattern);
00579 
00580   (*size)++;
00581 }
00582 

Generated on Sun Jul 16 16:27:45 2006 by  doxygen 1.3.9.1