nfs-ganesha 1.4

nodelist.c

Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include "config.h"
00003 #endif
00004 
00005 #include <unistd.h>
00006 #include <stdlib.h>
00007 #include <stdio.h>
00008 
00009 #include <string.h>
00010 
00011 #include <search.h>
00012 
00013 #include <limits.h>
00014 #include <ctype.h>
00015 
00016 #include "nodelist.h"
00017 #include "nodelist_internals.h"
00018 
00019 #define MAX_LONG_INT_STRING_SIZE      128
00020 
00031 int
00032 nodelist_nodelist_equal_patterns(nodelist_nodelist_t * first_list,
00033                                  nodelist_nodelist_t * second_list)
00034 {
00035   int fstatus = 1;
00036   fstatus = nodelist_nodepattern_equals(&(first_list->pattern), &(second_list->pattern));
00037   return fstatus;
00038 }
00039 
00050 int
00051 nodelist_nodelist_non_recursive_intersects(nodelist_nodelist_t * first_list,
00052                                            nodelist_nodelist_t * second_list)
00053 {
00054 
00055   int fstatus = 0;
00056   int same_pattern = 0;
00057 
00058   /* first list must not be empty */
00059   if(first_list->rangelist.ranges_nb <= 0)
00060     return fstatus;
00061 
00062   /* test if the two lists represent the same node name pattern (prefix...suffix) */
00063   same_pattern = nodelist_nodelist_equal_patterns(first_list, second_list);
00064 
00065   /* we go further only if they represent the same node name pattern */
00066   if(same_pattern)
00067     {
00068       /* now we just have to test if ranges array intersect */
00069       fstatus = nodelist_rangelist_intersects(&(first_list->rangelist),
00070                                               &(second_list->rangelist));
00071     }
00072 
00073   return fstatus;
00074 }
00075 
00086 int
00087 nodelist_nodelist_intersects(nodelist_nodelist_t * first_list,
00088                              nodelist_nodelist_t * second_list)
00089 {
00090 
00091   int fstatus = 0;
00092   nodelist_nodelist_t *list1;
00093   nodelist_nodelist_t *list2;
00094 
00095   list2 = second_list;
00096   /* we have to check that at least one sub list of the second arg list */
00097   /* intersects with one sublist of the fist arg */
00098   while(list2 != NULL)
00099     {
00100       list1 = first_list;
00101       while(list1 != NULL)
00102         {
00103           fstatus = nodelist_nodelist_non_recursive_intersects(list1, list2);
00104           /* intersects! break! */
00105           if(fstatus)
00106             break;
00107           list1 = list1->next;
00108         }
00109       /* intersects! break! */
00110       if(fstatus)
00111         break;
00112       list2 = list2->next;
00113     }
00114 
00115   return fstatus;
00116 }
00117 
00128 int
00129 nodelist_nodelist_non_recursive_includes(nodelist_nodelist_t * first_list,
00130                                          nodelist_nodelist_t * second_list)
00131 {
00132   int fstatus = 0;
00133   int same_pattern = 0;
00134   /* lists must not be empty */
00135   if(first_list->rangelist.ranges_nb <= 0 || second_list->rangelist.ranges_nb <= 0)
00136     return fstatus;
00137   /* test if the two lists represent the same node name pattern (prefix...suffix) */
00138   same_pattern = nodelist_nodelist_equal_patterns(first_list, second_list);
00139 
00140   /* we go further only if they represent the same node name pattern */
00141   if(same_pattern)
00142     {
00143       /* now we juste have to test if second list ranges are included in the first list ranges */
00144       fstatus =
00145           nodelist_rangelist_includes(&(first_list->rangelist),
00146                                       &(second_list->rangelist));
00147     }
00148   return fstatus;
00149 }
00150 
00161 int
00162 nodelist_nodelist_includes(nodelist_nodelist_t * first_list,
00163                            nodelist_nodelist_t * second_list)
00164 {
00165   int fstatus = 0;
00166   nodelist_nodelist_t *list1;
00167   nodelist_nodelist_t *list2;
00168 
00169   list2 = second_list;
00170   /* we have to check that every node list in the second arg */
00171   /* are included in one list of the fist arg */
00172   while(list2 != NULL)
00173     {
00174       list1 = first_list;
00175       while(list1 != NULL)
00176         {
00177           fstatus = nodelist_nodelist_non_recursive_includes(list1, list2);
00178           /* included! go to next second list sublist */
00179           if(fstatus)
00180             break;
00181           list1 = list1->next;
00182         }
00183       /* this second list sublist is not included, so break with fstatus=0 */
00184       if(fstatus == 0)
00185         break;
00186       list2 = list2->next;
00187     }
00188   return fstatus;
00189 }
00190 
00201 int nodelist_nodelist_add_ids(nodelist_nodelist_t * nodelist, char *idlist)
00202 {
00203   int fstatus = 0;
00204   fstatus = nodelist_rangelist_add_list(&(nodelist->rangelist), idlist);
00205   return fstatus;
00206 }
00207 
00208 int nodelist_common_split_nodelist_entry(char *list, char **p_prefix, char **p_idlist,
00209                                          char **p_suffix)
00210 {
00211 
00212   int fstatus = 0;
00213 
00214   char *list_end;
00215 
00216   char *prefix = NULL;
00217   char *prefix_begin;
00218   char *prefix_end;
00219   char *suffix = NULL;
00220   char *suffix_begin;
00221 
00222   char *idlist = NULL;
00223   char *idlist_begin;
00224   char *idlist_end;
00225 
00226   /* create working copy of input list */
00227   list_end = list + (strlen(list));
00228   prefix_begin = list;
00229   prefix_end = list;
00230 
00231   /* get prefix */
00232   prefix = (char *)malloc((strlen(list) + 1) * sizeof(char));
00233   if(prefix != NULL)
00234     {
00235       while(*prefix_end != '[' && !isdigit(*prefix_end) && prefix_end < list_end)
00236         prefix_end++;
00237       if(prefix_end != prefix_begin && prefix_end <= list_end)
00238         {
00239           memcpy(prefix, list, (prefix_end - prefix_begin) * sizeof(char));
00240           prefix[prefix_end - prefix_begin] = '\0';
00241         }
00242       else
00243         {
00244           xfree(prefix);
00245         }
00246     }
00247   else
00248     {
00249       fstatus = -1;
00250     }
00251 
00252   /* get idlist */
00253   /* search for idlist begin */
00254   if(prefix != NULL)
00255     idlist_begin = prefix_end;
00256   else
00257     idlist_begin = list;
00258   while(*idlist_begin == '[' && idlist_begin < list_end)
00259     idlist_begin++;
00260   idlist_end = idlist_begin;
00261   if(idlist_begin < list_end)
00262     {
00263       /* search for idlist end */
00264       while((isdigit(*idlist_end) || *idlist_end == ',' || *idlist_end == '-')
00265             && idlist_end < list_end)
00266         {
00267           idlist_end++;
00268         }
00269       /* remove trailing dash, like in node%d-eth */
00270       if(*(idlist_end - 1) == '-')
00271         {
00272           idlist_end--;
00273           while(*(idlist_end - 1) == '-')
00274             idlist_end--;
00275         }
00276       /* dump idlist */
00277       idlist = (char *)malloc((idlist_end - idlist_begin + 1) * sizeof(char));
00278       if(idlist != NULL)
00279         {
00280           memcpy(idlist, idlist_begin, (idlist_end - idlist_begin) * sizeof(char));
00281           idlist[idlist_end - idlist_begin] = '\0';
00282         }
00283       else
00284         {
00285           fstatus = -1;
00286         }
00287     }
00288 
00289   /* get suffix */
00290   /* search for suffix begin */
00291   suffix_begin = idlist_end;
00292   while(*suffix_begin == ']' && suffix_begin < list_end)
00293     suffix_begin++;
00294   /* dump suffix */
00295   if(suffix_begin != list_end)
00296     {
00297       suffix = (char *)malloc((list_end - suffix_begin + 1) * sizeof(char));
00298       if(suffix != NULL)
00299         {
00300           memcpy(suffix, suffix_begin, (list_end - suffix_begin) * sizeof(char));
00301           suffix[list_end - suffix_begin] = '\0';
00302         }
00303       else
00304         {
00305           fstatus = -1;
00306         }
00307     }
00308 
00309   if(fstatus != 0)
00310     {
00311       xfree(prefix);
00312       xfree(idlist);
00313       xfree(suffix);
00314     }
00315 
00316   *p_prefix = prefix;
00317   *p_idlist = idlist;
00318   *p_suffix = suffix;
00319 
00320   return fstatus;
00321 }
00322 
00323 int nodelist_nodelist_init(nodelist_nodelist_t * nodelist, char **lists, int lists_nb)
00324 {
00325 
00326   int fstatus = 0;
00327   int i;
00328   char *list;
00329 
00330   int operation = 1;            /* 1=add 2=remove */
00331 
00332   nodelist->next = NULL;
00333   fstatus += nodelist_rangelist_init(&(nodelist->rangelist));
00334   fstatus += nodelist_nodepattern_init(&(nodelist->pattern));
00335 
00336   if(fstatus == 0)
00337     {
00338       for(i = 0; i < lists_nb; i++)
00339         {
00340           list = lists[i];
00341 
00342           /* set operation if required */
00343           if(strlen(list) == 1)
00344             {
00345               if(*list == '-')
00346                 {
00347                   operation = 2;
00348                   continue;
00349                 }
00350               if(*list == '+')
00351                 {
00352                   operation = 1;
00353                   continue;
00354                 }
00355               else
00356                 operation = 1;
00357             }
00358 
00359           /* do action */
00360           switch (operation)
00361             {
00362 
00363             case 1:
00364               fstatus += nodelist_nodelist_add_nodes(nodelist, list);
00365               break;
00366 
00367             case 2:
00368               nodelist_nodelist_remove_nodes(nodelist, list);
00369               break;
00370 
00371             }
00372 
00373           /* setting default operation */
00374           operation = 1;
00375         }
00376     }
00377 
00378   if(fstatus)
00379     return -1;
00380   else
00381     return fstatus;
00382 }
00383 
00384 int nodelist_nodelist_free_contents(nodelist_nodelist_t * nodelist)
00385 {
00386 
00387   int fstatus = -1;
00388 
00389   if(nodelist->next != NULL)
00390     nodelist_nodelist_free_contents(nodelist->next);
00391   nodelist->next = NULL;
00392   nodelist_nodepattern_free_contents(&(nodelist->pattern));
00393   nodelist_rangelist_free_contents(&(nodelist->rangelist));
00394 
00395   fstatus = 0;
00396 
00397   return fstatus;
00398 
00399 }
00400 
00411 int
00412 nodelist_nodelist_copy(nodelist_nodelist_t * dest_list, nodelist_nodelist_t * src_list)
00413 {
00414   int fstatus = -1;
00415 
00416   nodelist_nodelist_t **pwldest;
00417   nodelist_nodelist_t **pwlsrc;
00418 
00419   nodelist_nodelist_free_contents(dest_list);
00420 
00421   pwldest = &dest_list;
00422   if(nodelist_nodelist_init(*pwldest, NULL, 0) == 0)
00423     {
00424 
00425       if(src_list->pattern.prefix == NULL && src_list->pattern.suffix == NULL)
00426         {
00427           // second list is empty... so initialization will be sufficient
00428           fstatus = 0;
00429         }
00430       else
00431         {
00432 
00433           pwlsrc = &src_list;
00434           while(*pwlsrc != NULL)
00435             {
00436               fstatus = -1;
00437 
00438               if(nodelist_nodepattern_init_by_copy
00439                  (&((*pwldest)->pattern), &((*pwlsrc)->pattern)) != 0)
00440                 {
00441                   // unable to copy pattern, break
00442                   fstatus = -2;
00443                   break;
00444                 }
00445               else
00446                 {
00447                   if((*pwlsrc)->pattern.basic != 1)
00448                     {
00449                       // add ids
00450                       if(nodelist_rangelist_init_by_copy
00451                          (&((*pwldest)->rangelist), &((*pwlsrc)->rangelist)) != 0)
00452                         {
00453                           // unable to copy range list, break
00454                           fstatus = -3;
00455                           break;
00456                         }
00457                     }
00458                   pwldest = &((*pwldest)->next);
00459                   fstatus = 0;
00460                 }
00461 
00462               pwlsrc = &((*pwlsrc)->next);
00463             }
00464 
00465           if(fstatus != 0)
00466             nodelist_nodelist_free_contents(dest_list);
00467 
00468         }
00469 
00470     }
00471 
00472   return fstatus;
00473 }
00474 
00484 int nodelist_nodelist_is_empty(nodelist_nodelist_t * nodelist)
00485 {
00486 
00487   if(nodelist->pattern.prefix == NULL && nodelist->pattern.suffix == NULL)
00488     {
00489       return 1;
00490     }
00491   else
00492     {
00493       return 0;
00494     }
00495 
00496 }
00497 
00508 int
00509 nodelist_nodelist_add_nodelist(nodelist_nodelist_t * nodelist,
00510                                nodelist_nodelist_t * second_list)
00511 {
00512   int fstatus = -1;
00513 
00514   nodelist_nodelist_t **pwldest;
00515   nodelist_nodelist_t **pwlsrc;
00516 
00517   /* If second list is emty, nothing to add */
00518   if(nodelist_nodelist_is_empty(second_list))
00519     {
00520       return 0;
00521     }
00522 
00523   /* If nodelist is empty, duplicate second_list! */
00524   if(nodelist_nodelist_is_empty(nodelist))
00525     {
00526       fstatus = nodelist_nodelist_copy(nodelist, second_list);
00527     }
00528   /* we have to add each second list sublist to the first one */
00529   else
00530     {
00531 
00532       pwlsrc = &second_list;
00533       while(*pwlsrc != NULL)
00534         {
00535 
00536           /* try to add src sublist to an existant dest list sublist */
00537           pwldest = &nodelist;
00538           while(*pwldest != NULL)
00539             {
00540 
00541               /* if patterns equal, try to add ids and break */
00542               if(nodelist_nodepattern_equals
00543                  ((&(*pwldest)->pattern), &((*pwlsrc)->pattern)))
00544                 {
00545                   if((*pwldest)->pattern.padding < (*pwlsrc)->pattern.padding)
00546                     nodelist_nodepattern_set_padding(&((*pwldest)->pattern),
00547                                                      (*pwlsrc)->pattern.padding);
00548                   fstatus =
00549                       nodelist_rangelist_add_rangelist(&((*pwldest)->rangelist),
00550                                                        &((*pwlsrc)->rangelist));
00551                   break;
00552                 }
00553 
00554               pwldest = &((*pwldest)->next);    /* increment dst sublist */
00555             }
00556 
00557           /* add a new sublist to dest list if no equivalent pattern list was found */
00558           if(*pwldest == NULL)
00559             {
00560               *pwldest = (nodelist_nodelist_t *) malloc(sizeof(nodelist_nodelist_t));
00561               if(*pwldest != NULL)
00562                 {
00563                   fstatus = nodelist_nodelist_init(*pwldest, NULL, 0);
00564                   if(fstatus == 0)
00565                     {
00566                       fstatus =
00567                           nodelist_nodepattern_init_by_copy(&((*pwldest)->pattern),
00568                                                             &((*pwlsrc)->pattern));
00569                       if(fstatus == 0)
00570                         {
00571                           fstatus =
00572                               nodelist_rangelist_add_rangelist(&((*pwldest)->rangelist),
00573                                                                &((*pwlsrc)->rangelist));
00574                         }
00575                     }
00576                 }
00577             }
00578 
00579           /* fstatus != 0 means that an error occured, break */
00580           if(fstatus != 0)
00581             {
00582               break;
00583             }
00584 
00585           pwlsrc = &((*pwlsrc)->next);  /* increment src sublist */
00586         }
00587 
00588     }
00589 
00590   return fstatus;
00591 }
00592 
00603 int
00604 nodelist_nodelist_remove_nodelist(nodelist_nodelist_t * nodelist,
00605                                   nodelist_nodelist_t * second_list)
00606 {
00607   int fstatus = -1;
00608 
00609   int add_flag;
00610 
00611   nodelist_nodelist_t worklist;
00612   nodelist_nodelist_t **pwldest;
00613   nodelist_nodelist_t **pwlsrc;
00614 
00615   /* If second list is emty, nothing to remove */
00616   if(nodelist_nodelist_is_empty(second_list))
00617     {
00618       return 0;
00619     }
00620 
00621   /* If nodelist is empty, nothing to remove */
00622   if(nodelist_nodelist_is_empty(nodelist))
00623     {
00624       return 0;
00625     }
00626   /* we have to remove each second list sublist from the first one */
00627   else
00628     {
00629 
00630       /* initialize work list by copying the first nodelist */
00631       fstatus = nodelist_nodelist_init(&worklist, NULL, 0);
00632       if(fstatus == 0)
00633         {
00634 
00635           pwldest = &nodelist;
00636           while(*pwldest != NULL)
00637             {
00638 
00639               add_flag = 1;
00640               pwlsrc = &second_list;
00641               while(*pwlsrc != NULL)
00642                 {
00643 
00644                   /* if patterns equal, try to remove ids and break */
00645                   if(nodelist_nodepattern_equals
00646                      ((&(*pwldest)->pattern), &((*pwlsrc)->pattern)))
00647                     {
00648                       add_flag = 0;
00649                       if((*pwldest)->pattern.basic == 0)
00650                         {
00651                           fstatus +=
00652                               nodelist_rangelist_remove_rangelist(&
00653                                                                   ((*pwldest)->rangelist),
00654                                                                   &((*pwlsrc)->
00655                                                                     rangelist));
00656                         }
00657                       else
00658                         fstatus = 0;
00659                       fprintf(stdout, "fstatus %d\n", fstatus);
00660                       break;
00661                     }
00662 
00663                   pwlsrc = &((*pwlsrc)->next);  /* increment src sublist */
00664                 }
00665 
00666               if(fstatus)
00667                 break;
00668 
00669               if(add_flag == 1)
00670                 {
00671                   fstatus += nodelist_nodelist_add_nodelist(&worklist, *pwldest);
00672                 }
00673 
00674               if(fstatus)
00675                 break;
00676 
00677               pwldest = &((*pwldest)->next);    /* increment dest sublist */
00678             }
00679 
00680           if(fstatus == 0)
00681             {
00682               fstatus = nodelist_nodelist_copy(nodelist, &worklist);
00683             }
00684 
00685           nodelist_nodelist_free_contents(&worklist);
00686         }
00687 
00688     }
00689 
00690   return fstatus;
00691 }
00692 
00693 int nodelist_nodelist_add_nodes(nodelist_nodelist_t * nodelist, char *list)
00694 {
00695 
00696   int fstatus = -1;
00697   int status;
00698 
00699   char *prefix;
00700   char *idlist;
00701   char *suffix;
00702 
00703   int token_nb, i;
00704   char *token;
00705 
00706   nodelist_nodelist_t wlist;
00707 
00708   if(nodelist_common_string_get_tokens_quantity(list, ",", &token_nb) == 0)
00709     {
00710       token = NULL;
00711 
00712       for(i = 1; i <= token_nb; i++)
00713         {
00714           if(nodelist_common_string_get_token(list, ",", i, &token) == 0)
00715             {
00716 
00717               status =
00718                   nodelist_common_split_nodelist_entry(token, &prefix, &idlist, &suffix);
00719               if(status)
00720                 {
00721                   fstatus = -1;
00722                 }
00723               else
00724                 {
00725                   fstatus = nodelist_nodelist_init(&wlist, NULL, 0);
00726                   if(fstatus == 0)
00727                     {
00728                       nodelist_nodepattern_set_prefix(&(wlist.pattern), prefix);
00729                       nodelist_nodepattern_set_suffix(&(wlist.pattern), suffix);
00730                       if(idlist != NULL)
00731                         {
00732                           wlist.pattern.basic = 0;
00733                           fstatus = nodelist_nodelist_add_ids(&wlist, idlist);
00734                           nodelist_nodepattern_set_padding(&(wlist.pattern), fstatus);
00735                           fstatus = 0;
00736                         }
00737 
00738                       fstatus = nodelist_nodelist_add_nodelist(nodelist, &wlist);
00739 
00740                       nodelist_nodelist_free_contents(&wlist);
00741                     }
00742 
00743                   xfree(prefix);
00744                   xfree(suffix);
00745                   xfree(idlist);
00746                 }
00747 
00748               free(token);
00749             }
00750           token = NULL;
00751         }
00752 
00753     }
00754 
00755   return fstatus;
00756 
00757 }
00758 
00759 int nodelist_nodelist_remove_nodes(nodelist_nodelist_t * nodelist, char *list)
00760 {
00761 
00762   int fstatus = -1;
00763   int status;
00764 
00765   char *prefix;
00766   char *idlist;
00767   char *suffix;
00768 
00769   int token_nb, i;
00770   char *token;
00771 
00772   nodelist_nodelist_t wlist;
00773 
00774   if(nodelist_common_string_get_tokens_quantity(list, ",", &token_nb) == 0)
00775     {
00776       token = NULL;
00777       for(i = 1; i <= token_nb; i++)
00778         {
00779           if(nodelist_common_string_get_token(list, ",", i, &token) == 0)
00780             {
00781 
00782               status =
00783                   nodelist_common_split_nodelist_entry(token, &prefix, &idlist, &suffix);
00784               if(status)
00785                 {
00786                   fstatus = -1;
00787                 }
00788               else
00789                 {
00790                   fstatus = nodelist_nodelist_init(&wlist, NULL, 0);
00791                   if(fstatus == 0)
00792                     {
00793                       nodelist_nodepattern_set_prefix(&(wlist.pattern), prefix);
00794                       nodelist_nodepattern_set_suffix(&(wlist.pattern), suffix);
00795                       if(idlist != NULL)
00796                         {
00797                           wlist.pattern.basic = 0;
00798                           fstatus = nodelist_nodelist_add_ids(&wlist, idlist);
00799                           nodelist_nodepattern_set_padding(&(wlist.pattern), fstatus);
00800                           fstatus = 0;
00801                         }
00802 
00803                       fstatus = nodelist_nodelist_remove_nodelist(nodelist, &wlist);
00804 
00805                       nodelist_nodelist_free_contents(&wlist);
00806                     }
00807 
00808                   xfree(prefix);
00809                   xfree(suffix);
00810                   xfree(idlist);
00811                 }
00812 
00813               free(token);
00814             }
00815           token = NULL;
00816         }
00817 
00818     }
00819 
00820   return fstatus;
00821 
00822 }
00823 
00824 int nodelist_nodelist_add_nodes_range(nodelist_nodelist_t * nodelist, long int from_id,
00825                                       long int to_id)
00826 {
00827 
00828   int fstatus = -1;
00829 
00830   nodelist_range_t r;
00831 
00832   if(from_id <= to_id)
00833     {
00834       r.from = from_id;
00835       r.to = to_id;
00836     }
00837   else
00838     {
00839       r.from = to_id;
00840       r.to = from_id;
00841     }
00842 
00843   fstatus = nodelist_rangelist_add_range(&(nodelist->rangelist), &r);
00844 
00845   return fstatus;
00846 
00847 }
00848 
00849 long int nodelist_nodelist_non_recursive_nodes_quantity(nodelist_nodelist_t * nodelist)
00850 {
00851 
00852   long int quantity;
00853   long int i;
00854 
00855   quantity = 0;
00856   if(nodelist->pattern.basic == 1)
00857     {
00858       quantity++;
00859     }
00860   else
00861     {
00862       for(i = 0; i < nodelist->rangelist.ranges_nb; i++)
00863         {
00864           quantity +=
00865               (nodelist->rangelist.array[i].to - nodelist->rangelist.array[i].from + 1);
00866         }
00867     }
00868 
00869   return quantity;
00870 }
00871 
00872 long int nodelist_nodelist_nodes_quantity(nodelist_nodelist_t * nodelist)
00873 {
00874 
00875   long int quantity;
00876 
00877   nodelist_nodelist_t *nlist;
00878 
00879   quantity = 0;
00880   nlist = nodelist;
00881   while(nlist != NULL)
00882     {
00883       quantity += nodelist_nodelist_non_recursive_nodes_quantity(nlist);
00884       nlist = nlist->next;
00885     }
00886 
00887   return quantity;
00888 }
00889 
00890 int nodelist_nodelist_get_extended_string(nodelist_nodelist_t * nodelist, char **p_string)
00891 {
00892 
00893   int fstatus = 0;
00894 
00895   nodelist_nodelist_t *nlist;
00896 
00897   char *node_string;
00898   size_t node_string_size;
00899 
00900   char *output_string;
00901   size_t output_string_size = 1024;
00902 
00903   long int i, j;
00904 
00905   char id_print_format[128];
00906 
00907   char *prefix;
00908   char *suffix;
00909 
00910   output_string = (char *)malloc(output_string_size * sizeof(char));
00911   if(output_string)
00912     {
00913       output_string[0] = '\0';
00914 
00915       /* node list sublist loop */
00916       nlist = nodelist;
00917       while(nlist != NULL)
00918         {
00919 
00920           /* build sublist padded id format */
00921           prefix = nlist->pattern.prefix;
00922           suffix = nlist->pattern.suffix;
00923           snprintf(id_print_format, 128, "%%s%%0.%uu%%s", nlist->pattern.padding);
00924 
00925           node_string_size = 0;
00926           if(prefix != NULL)
00927             node_string_size += strlen(prefix);
00928           if(suffix != NULL)
00929             node_string_size += strlen(suffix);
00930           node_string_size += MAX_LONG_INT_STRING_SIZE;
00931           node_string = (char *)malloc(node_string_size * sizeof(char));
00932           if(node_string != NULL)
00933             {
00934 
00935               if(nlist->pattern.basic == 1)
00936                 {
00937                   /* add basic node */
00938                   snprintf(node_string, node_string_size, "%s%s",
00939                            (prefix == NULL) ? "" : prefix,
00940                            (suffix == NULL) ? "" : suffix);
00941                   if(nodelist_common_string_appends_and_extends
00942                      (&output_string, &output_string_size, node_string_size, node_string,
00943                       ","))
00944                     {
00945                       fstatus = -1;
00946                     }
00947                   else
00948                     {
00949                       fstatus = 0;
00950                     }
00951                 }
00952               else
00953                 {
00954                   /* add enumerated nodes */
00955                   for(i = 0; i < nlist->rangelist.ranges_nb; i++)
00956                     {
00957                       for(j = nlist->rangelist.array[i].from;
00958                           j <= nlist->rangelist.array[i].to; j++)
00959                         {
00960 
00961                           snprintf(node_string, node_string_size, id_print_format,
00962                                    (prefix == NULL) ? "" : prefix, j,
00963                                    (suffix == NULL) ? "" : suffix);
00964                           if(nodelist_common_string_appends_and_extends
00965                              (&output_string, &output_string_size, node_string_size,
00966                               node_string, ","))
00967                             {
00968                               fstatus = -1;
00969                             }
00970                           else
00971                             {
00972                               fstatus = 0;
00973                             }
00974                         }
00975                     }
00976                 }
00977 
00978               free(node_string);
00979             }
00980 
00981           nlist = nlist->next;
00982         }
00983 
00984       if(fstatus != 0)
00985         {
00986           free(output_string);
00987         }
00988       else
00989         {
00990           *p_string = output_string;
00991         }
00992     }
00993 
00994   return fstatus;
00995 }
00996 
00997 int nodelist_nodelist_get_compacted_string(nodelist_nodelist_t * nodelist,
00998                                            char **p_string)
00999 {
01000 
01001   int fstatus = -1;
01002 
01003   nodelist_nodelist_t *nlist;
01004 
01005   int brackets_flag;
01006 
01007   char *range_string;
01008   size_t range_string_size;
01009 
01010   char *ranges_string;
01011   size_t ranges_string_size;
01012 
01013   char *output_string;
01014   size_t output_string_size = 1024;
01015 
01016   long int nodes_nb;
01017   long int i;
01018 
01019   long int from, to;
01020 
01021   char id_print_format[128];
01022   char id_range_print_format[128];
01023 
01024   char *prefix;
01025   char *suffix;
01026 
01027   /* initialize output string */
01028   output_string = (char *)malloc(output_string_size * sizeof(char));
01029   if(output_string)
01030     {
01031       output_string[0] = '\0';
01032 
01033       /* node list sublist loop */
01034       nlist = nodelist;
01035       while(nlist != NULL)
01036         {
01037 
01038           prefix = nlist->pattern.prefix;
01039           suffix = nlist->pattern.suffix;
01040 
01041           nodes_nb = nodelist_nodelist_non_recursive_nodes_quantity(nlist);
01042           if(nodes_nb == 0)
01043             {
01044               free(output_string);
01045               return fstatus;
01046             }
01047           else if(nodes_nb == 1)
01048             brackets_flag = 0;
01049           else
01050             brackets_flag = 1;
01051 
01052           if(nlist->pattern.basic == 1)
01053             {
01054               /* in case of basic node, just add it */
01055               ranges_string_size = 1;   // \0
01056               if(prefix != NULL)
01057                 ranges_string_size += strlen(prefix);
01058               if(suffix != NULL)
01059                 ranges_string_size += strlen(suffix);
01060               ranges_string = (char *)malloc(ranges_string_size * sizeof(char));
01061               if(ranges_string != NULL)
01062                 {
01063                   snprintf(ranges_string, ranges_string_size, "%s%s",
01064                            (prefix == NULL) ? "" : prefix,
01065                            (suffix == NULL) ? "" : suffix);
01066                   fstatus = 0;
01067                 }
01068             }
01069           else
01070             {
01071               /* enumerated sublist */
01072               snprintf(id_print_format, 128, "%%0.%uu", nlist->pattern.padding);
01073               snprintf(id_range_print_format, 128, "%%0.%uu-%%0.%uu",
01074                        nlist->pattern.padding, nlist->pattern.padding);
01075 
01076               range_string_size = 0;
01077               range_string_size = 2 * MAX_LONG_INT_STRING_SIZE + 2;
01078 
01079               ranges_string_size = 1024;
01080               ranges_string = (char *)malloc(ranges_string_size * sizeof(char));
01081               if(ranges_string != NULL)
01082                 {
01083                   ranges_string[0] = '\0';
01084                   /* add prefix */
01085                   if(prefix != NULL)
01086                     nodelist_common_string_appends_and_extends(&ranges_string,
01087                                                                &ranges_string_size,
01088                                                                strlen(prefix), prefix,
01089                                                                "");
01090                   if(brackets_flag)
01091                     nodelist_common_string_appends_and_extends(&ranges_string,
01092                                                                &ranges_string_size, 1,
01093                                                                "[", "");
01094                   range_string = (char *)malloc(range_string_size * sizeof(char));
01095                   if(range_string != NULL)
01096                     {
01097                       range_string[0] = '\0';
01098                       for(i = 0; i < nlist->rangelist.ranges_nb; i++)
01099                         {
01100                           from = nlist->rangelist.array[i].from;
01101                           to = nlist->rangelist.array[i].to;
01102                           if(from == to)
01103                             snprintf(range_string, range_string_size, id_print_format,
01104                                      from);
01105                           else
01106                             snprintf(range_string, range_string_size,
01107                                      id_range_print_format, from, to);
01108                           if(i == 0)
01109                             fstatus =
01110                                 nodelist_common_string_appends_and_extends(&ranges_string,
01111                                                                            &ranges_string_size,
01112                                                                            range_string_size,
01113                                                                            range_string,
01114                                                                            "");
01115                           else
01116                             fstatus =
01117                                 nodelist_common_string_appends_and_extends(&ranges_string,
01118                                                                            &ranges_string_size,
01119                                                                            range_string_size,
01120                                                                            range_string,
01121                                                                            ",");
01122                           if(fstatus)
01123                             {
01124                               fstatus = -1;
01125                               break;
01126                             }
01127                           else
01128                             {
01129                               fstatus = 0;
01130                             }
01131                         }
01132                       free(range_string);
01133                     }
01134                   if(brackets_flag)
01135                     nodelist_common_string_appends_and_extends(&ranges_string,
01136                                                                &ranges_string_size, 1,
01137                                                                "]", "");
01138                   /* add suffix */
01139                   if(suffix != NULL)
01140                     nodelist_common_string_appends_and_extends(&ranges_string,
01141                                                                &ranges_string_size,
01142                                                                strlen(suffix), suffix,
01143                                                                "");
01144                 }
01145             }
01146 
01147           /* add current list to global list */
01148           if(ranges_string == NULL)
01149             {
01150               fstatus = -1;
01151               break;
01152             }
01153           if(nodelist_common_string_appends_and_extends
01154              (&output_string, &output_string_size, ranges_string_size, ranges_string,
01155               ","))
01156             {
01157               fstatus = -1;
01158               free(ranges_string);
01159               break;
01160             }
01161 
01162           /* go to next sublist */
01163           nlist = nlist->next;
01164         }
01165 
01166       if(fstatus != 0)
01167         {
01168           free(output_string);
01169         }
01170       else
01171         {
01172           *p_string = output_string;
01173         }
01174     }
01175 
01176   return fstatus;
01177 }
01178 
01193 int nodelist_nodepattern_init(nodelist_nodepattern_t * np)
01194 {
01195   np->padding = 0;
01196   np->prefix = NULL;
01197   np->suffix = NULL;
01198   np->basic = 1;
01199   return 0;
01200 }
01201 
01214 int
01215 nodelist_nodepattern_init_by_copy(nodelist_nodepattern_t * np,
01216                                   nodelist_nodepattern_t * npin)
01217 {
01218   int fstatus = -1;
01219   np->padding = npin->padding;
01220   np->basic = npin->basic;
01221   np->prefix = NULL;
01222   np->suffix = NULL;
01223   if(npin->prefix != NULL)
01224     {
01225       np->prefix = strdup(npin->prefix);
01226       if(np->prefix == NULL)
01227         {
01228           nodelist_nodepattern_free_contents(np);
01229           return fstatus;
01230         }
01231     }
01232   if(npin->suffix != NULL)
01233     {
01234       np->suffix = strdup(npin->suffix);
01235       if(np->suffix == NULL)
01236         {
01237           nodelist_nodepattern_free_contents(np);
01238           return fstatus;
01239         }
01240     }
01241   fstatus = 0;
01242   return fstatus;
01243 }
01244 
01253 int nodelist_nodepattern_free_contents(nodelist_nodepattern_t * np)
01254 {
01255   np->padding = 0;
01256   xfree(np->prefix);
01257   xfree(np->suffix);
01258   np->basic = 1;
01259   return 0;
01260 }
01261 
01271 int nodelist_nodepattern_set_padding(nodelist_nodepattern_t * np, int padding)
01272 {
01273   int fstatus = -1;
01274   if(np != NULL)
01275     {
01276       np->padding = padding;
01277       fstatus = 0;
01278     }
01279   return fstatus;
01280 }
01281 
01291 int nodelist_nodepattern_set_prefix(nodelist_nodepattern_t * np, char *prefix)
01292 {
01293   int fstatus = -1;
01294   if(np != NULL && prefix != NULL)
01295     {
01296       xfree(np->prefix);
01297       np->prefix = strdup(prefix);
01298       if(np->prefix != NULL)
01299         fstatus = 0;
01300     }
01301   return fstatus;
01302 }
01303 
01313 int nodelist_nodepattern_set_suffix(nodelist_nodepattern_t * np, char *suffix)
01314 {
01315   int fstatus = -1;
01316   if(np != NULL && suffix != NULL)
01317     {
01318       xfree(np->suffix);
01319       np->suffix = strdup(suffix);
01320       if(np->suffix != NULL)
01321         fstatus = 0;
01322     }
01323   return fstatus;
01324 }
01325 
01334 int nodelist_nodepattern_set_basic(nodelist_nodepattern_t * np)
01335 {
01336   int fstatus = -1;
01337   if(np != NULL)
01338     {
01339       np->basic = 1;
01340       fstatus = 0;
01341     }
01342   return fstatus;
01343 }
01344 
01353 int nodelist_nodepattern_unset_basic(nodelist_nodepattern_t * np)
01354 {
01355   int fstatus = -1;
01356   if(np != NULL)
01357     {
01358       np->basic = 0;
01359       fstatus = 0;
01360     }
01361   return fstatus;
01362 }
01363 
01374 int
01375 nodelist_nodepattern_equals(nodelist_nodepattern_t * np1, nodelist_nodepattern_t * np2)
01376 {
01377   int fstatus = -1;
01378   if(np1 != NULL && np2 != NULL)
01379     {
01380       fstatus = 0;
01381 /*       /\* same padding ? *\/ */
01382 /*       if(np1->padding!=np2->padding) */
01383 /*      return fstatus; */
01384       /* same basic flag ? */
01385       if(np1->basic != np2->basic)
01386         return fstatus;
01387       /* same prefix or lack of prefix ? */
01388       if(np1->prefix != NULL && np2->prefix != NULL)
01389         {
01390           if(strcmp(np1->prefix, np2->prefix) != 0)
01391             return fstatus;
01392         }
01393       else if(np1->prefix == NULL && np2->prefix != NULL)
01394         {
01395           return fstatus;
01396         }
01397       else if(np1->prefix != NULL && np2->prefix == NULL)
01398         {
01399           return fstatus;
01400         }
01401       /* same suffix or lack of suffix ? */
01402       if(np1->suffix != NULL && np2->suffix != NULL)
01403         {
01404           if(strcmp(np1->suffix, np2->suffix) != 0)
01405             return fstatus;
01406         }
01407       else if(np1->suffix == NULL && np2->suffix != NULL)
01408         {
01409           return fstatus;
01410         }
01411       else if(np1->suffix != NULL && np2->suffix == NULL)
01412         {
01413           return fstatus;
01414         }
01415       /* ok, they are the same pattern */
01416       fstatus = 1;
01417     }
01418   return fstatus;
01419 }
01420