sxpptree.c

Go to the documentation of this file.
00001 /******************************************************************************
00002  *                                S Y N T A X
00003  *-----------------------------------------------------------------------------
00004  *   Copyright (C) 1972-2008 INRIA (Institut National de Recherche en
00005  *   Informatique et Automatique)
00006  *-----------------------------------------------------------------------------
00007  *   URL: http://syntax.gforge.inria.fr
00008  *-----------------------------------------------------------------------------
00009  *   The source code of SYNTAX is distributed with two different licenses,
00010  *   depending on the files:
00011  *   - The recursive content of src/ and incl/ and the non-recursive content
00012  *     of SYNTAX's root directory are distributed under the CeCILL-C license
00013  *   - The recursive content of all other repertories is distributed under
00014  *     the CeCILL license
00015  *   All code produced by SYNTAX must be considered as being under the
00016  *   CeCILL-C license. Information about the CeCILL and CeCILL-C licenses
00017  *   can be found at, e.g., http://www.cecill.fr
00018  *****************************************************************************/
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
00033 /*                                  */
00034 /*                                  */
00035 /* Mise en page et impression d'un arbre quelconque.            */
00036 /* -------------------------------------------------            */
00037 /*                                  */
00038 /* L'arbre est imprime sous forme de lés, chaque lé ayant pour largeur    */
00039 /* la valeur de la variable "page_width".  La distance minimale entre   */
00040 /* deux noeuds contigus sur une meme ligne est donnee par la valeur de  */
00041 /* "min_dist".  La distance minimale entre deux sous-arbres cousins est */
00042 /* donnee par la valeur de "min_dist_on_subtrees".  Les valeurs par */
00043 /* defaut de ces trois variables sont respectivement 132, 3 et min_dist.*/
00044 /*                                  */
00045 /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  * */
00046 
00047 
00048 
00049 
00050 
00051 
00052 #include        "sxversion.h"
00053 #include        "sxcommon.h"
00054 #include <stdio.h>
00055 #include <stdlib.h>
00056 
00057 char WHAT_SXPPTREE[] = "@(#)SYNTAX - $Id: sxpptree.c 1416 2008-06-25 14:42:55Z rlacroix $" WHAT_DEBUG;
00058 
00059 #define USER_PTR    SXINT*      /* Any pointer */
00060 
00061 #undef SXVOID
00062 #define SXVOID  void
00063 
00064 #undef SXBOOLEAN
00065 #define SXBOOLEAN   char
00066 #undef  SXTRUE
00067 #define SXTRUE  (SXBOOLEAN) 1
00068 #undef  SXFALSE
00069 #define SXFALSE (SXBOOLEAN) 0
00070 
00071 struct positions {
00072     long    left, middle, right;
00073     long    l_son_middle, r_son_middle;
00074 };
00075 struct informations_on_user_node {
00076     USER_PTR    user_node;
00077     SXINT       key_start;
00078     SXINT       key_length;
00079     SXINT       sons_number;
00080 };
00081 struct node {
00082     struct node     *next, *l_son_node;
00083     struct informations_on_user_node    info;
00084     struct positions    pos;
00085 };
00086 struct line {
00087     struct line     *next;
00088     struct node     *first, *last;
00089     long    h_bar_ovfl;
00090 };
00091 static SXINT    max_level;
00092 /* nb of levels in the tree when in
00093                        abbrev-mode */
00094 
00095 
00096 static SXINT    page_length;
00097 /* nb of lines in the page when in
00098                        abbrev-mode */
00099 
00100 
00101 static struct line  *lines = {NULL};
00102 static long minpos, maxpos;
00103 static struct {
00104        long     min_dist;
00105        long     min_dist_on_subtrees;
00106        long     page_width;
00107        long     (*get_key_length) (USER_PTR);
00108        USER_PTR (*get_left_son) (USER_PTR);
00109        USER_PTR (*get_right_brother) (USER_PTR);
00110        long     (*get_sons_number) (USER_PTR);
00111        SXVOID       (*print_from_arrows) (char *);
00112        SXVOID       (*print_horizontal_bar) (char *);
00113        SXVOID       (*print_key) (USER_PTR, SXINT, long);
00114        SXVOID       (*print_to_arrows) (char *);
00115        SXVOID       (*put_blanks) (long);
00116        SXVOID       (*put_page) (void);
00117        SXVOID       (*put_skip) (void);
00118        SXBOOLEAN    abbrev_mode /* on if the tree may be abbreviated */ ;
00119        }    args;
00120 
00121 
00122 
00123 static SXVOID   shift_subtree (struct node *node, long s)
00124 {
00125     struct node *son;
00126     SXINT   count;
00127 
00128     node->pos.left += s, node->pos.middle += s, node->pos.right += s;
00129     node->pos.l_son_middle += s, node->pos.r_son_middle += s;
00130     son = node->l_son_node;
00131 
00132     if (!args.abbrev_mode || son != NULL)
00133     for (count = node->info.sons_number; count-- > 0; ) {
00134         shift_subtree (son, s);
00135         son = son->next;
00136     }
00137 }
00138 
00139 
00140 
00141 static SXVOID   init_h_bar_ovfl (void)
00142 {
00143     struct line *line;
00144 
00145     for (line = lines; line != NULL; line = line->next) {
00146     line->h_bar_ovfl = 0;
00147     }
00148 }
00149 
00150 
00151 
00152 static SXVOID   min_max_pos (void)
00153 {
00154     struct line *line;
00155     long    min, max;
00156 
00157     line = lines;
00158     min = line->first->pos.left, max = line->last->pos.right;
00159     line->last = NULL;
00160 
00161     while ((line = line->next) != NULL) {
00162     long    val;
00163 
00164     if ((val = line->first->pos.left) < min)
00165         min = val;
00166 
00167     if ((val = line->last->pos.right) > max)
00168         max = val;
00169 
00170     line->last = NULL;
00171     }
00172 
00173     minpos = min, maxpos = max;
00174 }
00175 
00176 
00177 
00178 
00179 #include <setjmp.h>
00180 
00181 static jmp_buf  no_space;
00182 
00183 
00184 
00185 
00186 #ifdef  SIMPLE
00187 
00188 static void *allocate (size)
00189     SXINT       size;
00190 {
00191     void    *result;
00192 
00193     if ((result = malloc (size)) == NULL)
00194     longjmp (no_space, SXTRUE);
00195 
00196     return result;
00197 }
00198 
00199 
00200 
00201 
00202 #   define  node_dispose(node)  free (node)
00203 #   define  line_dispose(line)  free (line)
00204 
00205 static SXVOID   lines_destroy (first_line)
00206     struct line     *first_line;
00207 {
00208     struct node *node, *next_node;
00209     struct line *line, *next_line;
00210 
00211     for (line = first_line; line != NULL; line = next_line) {
00212     next_line = line->next;
00213 
00214     for (node = line->first; node != NULL; node = next_node) {
00215         next_node = node->next;
00216         node_dispose (node);
00217     }
00218 
00219     line_dispose (line);
00220     }
00221 }
00222 
00223 
00224 
00225 
00226 #   define  deallocate_areas()  0
00227 
00228 #else
00229 
00230 #   define  NBLINES 10      /* number of lines allocated together */
00231 #   define  NBNODES 100     /* number of nodes allocated together */
00232 
00233 static struct line_area {
00234        struct line_area *next;
00235        struct line  array [NBLINES];
00236        }    *first_line_area;
00237 static struct node_area {
00238        struct node_area *next;
00239        struct node  array [NBLINES];
00240        }    *first_node_area;
00241 
00242 
00243 
00244 static void *allocate (SXUINT size)
00245 {
00246     static struct line_area *line_area;
00247     static struct line  *last_line;
00248     static struct node_area *node_area;
00249     static struct node  *last_node;
00250 
00251     switch (size) {
00252     case sizeof (struct line):
00253     if (first_line_area == NULL || last_line == line_area->array) {
00254         struct line_area    *new;
00255 
00256         new = (struct line_area*) allocate (sizeof (struct line_area));
00257         new->next = NULL;
00258 
00259         if (first_line_area == NULL)
00260         first_line_area = new;
00261         else
00262         line_area->next = new;
00263 
00264         last_line = &((line_area = new)->array [NBLINES]);
00265     }
00266 
00267     return --last_line;
00268 
00269     case sizeof (struct node):
00270     if (first_node_area == NULL || last_node == node_area->array) {
00271         struct node_area    *new;
00272 
00273         new = (struct node_area*) allocate (sizeof (struct node_area));
00274         new->next = NULL;
00275 
00276         if (first_node_area == NULL)
00277         first_node_area = new;
00278         else
00279         node_area->next = new;
00280 
00281         last_node = &((node_area = new)->array [NBLINES]);
00282     }
00283 
00284     return --last_node;
00285 
00286     default:
00287     {
00288         void    *result;
00289 
00290         if ((result = malloc (size)) == NULL)
00291         longjmp (no_space, SXTRUE);
00292 
00293         return result;
00294     }
00295     }
00296 }
00297 
00298 
00299 
00300 
00301 #   define  node_dispose(node)  
00302 #   define  line_dispose(line)  
00303 #   define  lines_destroy(line) 
00304 
00305 
00306 static SXVOID   deallocate_areas (void)
00307 {
00308     struct line_area    *line_area;
00309     struct node_area    *node_area;
00310 
00311     for (line_area = first_line_area; line_area != NULL; line_area = line_area->next)
00312     free (line_area);
00313 
00314     first_line_area = NULL;
00315 
00316     for (node_area = first_node_area; node_area != NULL; node_area = node_area->next)
00317     free (node_area);
00318 
00319     first_node_area = NULL;
00320 }
00321 
00322 
00323 
00324 
00325 #endif  /* SIMPLE */
00326 
00327 
00328 
00329 static SXVOID   trim_nodes (struct node *node)
00330 {
00331     while (node != NULL) {
00332     node->l_son_node = NULL;
00333     node = node->next;
00334     }
00335 }
00336 
00337 
00338 
00339 static SXVOID   trim_lines (struct line *line, SXINT level)
00340 {
00341     while (level < max_level && line != NULL) {
00342     line = line->next;
00343     level++;
00344     }
00345 
00346     if (line != NULL) {
00347     trim_nodes (line->first);
00348     lines_destroy (line->next);
00349     line->next = NULL;
00350     }
00351 }
00352 
00353 
00354 
00355 static SXVOID   place (USER_PTR user_ptr, struct line **line_ptr, SXINT level, SXBOOLEAN is_left_son)
00356 {
00357     struct line *line;
00358     struct node *node;
00359     long    left_pos;
00360     SXINT       current_size, cursize, half_size;
00361     SXBOOLEAN   first_node_on_this_line_p;
00362 
00363     half_size = (cursize = (current_size = args.get_key_length (user_ptr)) - 1) >> 1;
00364 
00365 /* On cree un nouveau node vers user_ptr */
00366 
00367     node = (struct node*) allocate (sizeof (struct node));
00368     node->next = node->l_son_node = NULL;
00369     node->info.user_node = user_ptr;
00370     node->info.key_start = 1;
00371     node->info.key_length = current_size;
00372     node->info.sons_number = args.get_sons_number (user_ptr);
00373     first_node_on_this_line_p = (*line_ptr) == NULL;
00374 
00375     if (first_node_on_this_line_p) {
00376     (*line_ptr) = line = (struct line*) allocate (sizeof (struct line));
00377     line->next = NULL;
00378     line->first = node;
00379     line->h_bar_ovfl = 0;
00380     left_pos = 0;
00381     }
00382     else {
00383     line = *line_ptr;
00384     line->last->next = node;
00385     left_pos = line->last->pos.right + 1;
00386 
00387     {
00388         SXINT   val = is_left_son ? args.min_dist_on_subtrees : args.min_dist;
00389 
00390         line->h_bar_ovfl += val;
00391         left_pos += val;
00392     }
00393     }
00394 
00395     line->last = node;
00396     line->h_bar_ovfl += current_size;
00397 
00398     if (args.abbrev_mode && line->h_bar_ovfl > args.page_width)
00399     max_level = level;
00400 
00401 
00402 /* On ajuste la position en fonction des positions des fils eventuels */
00403 
00404     if (node->info.sons_number == 0 || (args.abbrev_mode && level >= max_level)) {
00405     node->pos.left = left_pos;
00406     node->pos.right = left_pos + cursize;
00407     node->pos.middle = node->pos.l_son_middle = node->pos.r_son_middle = left_pos + half_size;
00408     }
00409     else {
00410     SXBOOLEAN       left_son_first_on_his_line_p = line->next == NULL;
00411 
00412     level++;
00413 
00414     {
00415         USER_PTR    son;
00416         SXINT   count;
00417 
00418         place (son = args.get_left_son (user_ptr), &(line->next), level, SXTRUE);
00419         node->l_son_node = line->next->last;
00420 
00421         for (count = node->info.sons_number; --count > 0; )
00422         place (son = args.get_right_brother (son), &(line->next), level, SXFALSE);
00423     }
00424 
00425 
00426 /* On le place au milieu de ses fils, en les recadrant si necessaire */
00427 
00428     node->pos.l_son_middle = node->l_son_node->pos.middle;
00429     node->pos.r_son_middle = line->next->last->pos.middle;
00430     node->pos.middle = (node->pos.l_son_middle + node->pos.r_son_middle + 1) >> 1;
00431     node->pos.left = node->pos.middle - half_size;
00432     node->pos.right = node->pos.left + cursize;
00433 
00434     if (!first_node_on_this_line_p) {
00435         long    shift_q = left_pos - node->pos.left;
00436 
00437         if (shift_q != 0)
00438         if (shift_q > 0 || left_son_first_on_his_line_p)
00439             shift_subtree (node, shift_q);
00440     }
00441     }
00442 }
00443 
00444 
00445 
00446 static SXVOID   replace (struct line *line, SXINT level, SXBOOLEAN is_left_son, SXBOOLEAN first_time_on_this_level)
00447 {
00448     struct node     *node;
00449     long    left_pos;
00450     SXINT       sons_nb;
00451     SXINT       cursize, half_size;
00452     SXBOOLEAN   first_node_on_this_line_p;
00453 
00454     first_node_on_this_line_p = line->last == NULL;
00455 
00456     if (first_node_on_this_line_p) {
00457     node = line->first;
00458     left_pos = 0;
00459     }
00460     else {
00461     node = line->last->next;
00462     left_pos = line->last->pos.right + 1 + (is_left_son ? args.min_dist_on_subtrees : args.min_dist);
00463     }
00464 
00465     line->last = node;
00466 
00467 /* On ajuste la position en fonction des positions des fils eventuels */
00468 
00469     sons_nb = node->info.sons_number;
00470 
00471     if (sons_nb == 0 || level == max_level) {
00472     if (level == max_level)
00473         if ((first_time_on_this_level && sons_nb != 0) || (!first_time_on_this_level && sons_nb == 0)) {
00474         node->info.key_length = args.get_key_length (node->info.user_node);
00475         node->info.key_start = -1;
00476         }
00477 
00478     half_size = (cursize = node->info.key_length - 1) >> 1;
00479     node->pos.left = left_pos;
00480     node->pos.right = left_pos + cursize;
00481     node->pos.middle = node->pos.l_son_middle = node->pos.r_son_middle = left_pos + half_size;
00482     }
00483     else {
00484     SXBOOLEAN       left_son_first_on_his_line_p = line->next->last == NULL;
00485 
00486     level++;
00487 
00488     {
00489         SXINT   count;
00490 
00491         replace (line->next, level, SXTRUE, first_time_on_this_level);
00492 
00493         for (count = sons_nb; --count > 0; )
00494         replace (line->next, level, SXFALSE, first_time_on_this_level);
00495     }
00496 
00497 
00498 /* On le place au milieu de ses fils, en les recadrant si necessaire */
00499 
00500     node->pos.l_son_middle = node->l_son_node->pos.middle;
00501     node->pos.r_son_middle = line->next->last->pos.middle;
00502 
00503     {
00504         long    val = ((node->pos.l_son_middle + node->pos.r_son_middle + 1) >> 1) - node->pos.middle;
00505 
00506         node->pos.left += val, node->pos.middle += val, node->pos.right += val;
00507     }
00508 
00509     if (!first_node_on_this_line_p) {
00510         long    shift_q = left_pos - node->pos.left;
00511 
00512         if (shift_q != 0)
00513         if (shift_q > 0 || left_son_first_on_his_line_p)
00514             shift_subtree (node, shift_q);
00515     }
00516     }
00517 }
00518 
00519 
00520 
00521 static SXVOID   abbreviate_tree (void)
00522 {
00523     SXBOOLEAN   done;
00524     /* is the tree abbreviated enough */
00525     SXBOOLEAN   first_time_on_this_level;
00526 
00527     /* we recompute each level
00528                            twice if necessary */
00529 
00530     trim_lines (lines, (SXINT)1);
00531     /* as max_level may have been updated */
00532     min_max_pos ();
00533     args.put_page ();
00534     /* from now on, get abbreviations */
00535     first_time_on_this_level = SXTRUE;
00536     done = max_level <= 1 || maxpos - minpos < args.page_width;
00537 
00538     while (!done) {
00539     replace (lines, (SXINT)1, SXTRUE, first_time_on_this_level);
00540     trim_lines (lines, (SXINT)1);
00541     min_max_pos ();
00542 
00543     if (!(done = max_level <= 1 || maxpos - minpos < args.page_width)) {
00544         if ((first_time_on_this_level = !first_time_on_this_level))
00545         max_level--;
00546     }
00547     }
00548 
00549     maxpos = minpos + args.page_width - 1;
00550 }
00551 
00552 
00553 
00554 static long start_pos, next_stripe, current_pos;
00555 static SXINT    line_no;
00556 /* number of lines output when in
00557                        abbrev-mode */
00558 
00559 
00560 static struct line  *line;
00561 static struct string {
00562        char     *text;
00563        SXINT    length;
00564        }    from_arrows, to_arrows, horizontal_bar;
00565 
00566 
00567 
00568 static SXVOID   catenate_copy (struct string *string, char character, long number)
00569 {
00570     char    *str;
00571 
00572     str = &(string->text [string->length]);
00573     string->length += number;
00574 
00575     while (number-- > 0)
00576     *str++ = character;
00577 }
00578 
00579 
00580 
00581 static SXVOID   rateau (void)
00582 {
00583     long    pos;
00584     /* from_arrows.length =
00585                        to_arrows.length = pos - start_pos */
00586     struct node *node;
00587 
00588     horizontal_bar.length = to_arrows.length = from_arrows.length = 0;
00589 
00590     if (line->h_bar_ovfl > 0) {
00591     long    length;
00592 
00593     line->h_bar_ovfl -= length = line->h_bar_ovfl > args.page_width ? args.page_width : line->h_bar_ovfl;
00594     catenate_copy (&horizontal_bar, '-', length);
00595     }
00596 
00597     pos = start_pos;
00598 
00599     for (node = line->first; node != NULL && pos <= next_stripe; node = node->next) {
00600       if (node->info.sons_number > 0)
00601     if (node->pos.l_son_middle < next_stripe && node->pos.l_son_middle >= start_pos)
00602       /* pas encore traite */
00603       /* prepare_horizontal_bar:
00604         (pas de goto sur ce label, ce qui provoque un warning du compilo icc d'intel) */
00605       {
00606         catenate_copy (&horizontal_bar, ' ', node->pos.l_son_middle - start_pos - horizontal_bar.length);
00607 
00608         if (node->pos.r_son_middle >= next_stripe) {
00609           catenate_copy (&horizontal_bar, '-', args.page_width - horizontal_bar.length);
00610           line->h_bar_ovfl = node->pos.r_son_middle - next_stripe + 1;
00611         }
00612         else if (node->info.sons_number > 1)
00613           catenate_copy (&horizontal_bar, '-', node->pos.r_son_middle - node->pos.l_son_middle + 1);
00614         else
00615           horizontal_bar.text [horizontal_bar.length++] = '|';
00616       }
00617 
00618       if (node->pos.middle < next_stripe) {
00619     if (node->pos.middle >= start_pos) {
00620       /* pas encore traite */
00621       /* prepare_arrows: 
00622         (pas de goto sur ce label, ce qui provoque un warning du compilo icc d'intel) */
00623       {
00624         long    spaces_nb = node->pos.middle - pos;
00625 
00626         catenate_copy (&from_arrows, ' ', spaces_nb);
00627         from_arrows.text [from_arrows.length++] = '|';
00628         catenate_copy (&to_arrows, ' ', spaces_nb);
00629         to_arrows.text [to_arrows.length++] = node->info.sons_number != 0 ? '|' : ' ';
00630       }
00631 
00632       pos = node->pos.middle + 1;
00633     }
00634       }
00635       else if (node->info.sons_number > 0)
00636     /* sinon, on traite les freres */
00637     pos = node->pos.middle + 1;
00638     }
00639 }
00640 
00641 
00642 
00643 static SXVOID   print_one_node (struct node *node)
00644                       
00645 
00646 /* Si la cle tient sur la ligne, on l'imprime; */
00647 /* sinon on en imprime ce qu'on peut et on     */
00648 /* garde le reste pour le prochain le.         */
00649 
00650 {
00651     long    current_key_length, remaining_space;
00652 
00653     if (node->pos.left > current_pos)
00654     args.put_blanks (node->pos.left - current_pos);
00655 
00656     current_pos = node->pos.right + 1;
00657 
00658     if ((current_key_length = node->info.key_length) <= (remaining_space = next_stripe - node->pos.left)) {
00659     args.print_key (node->info.user_node, node->info.key_start, current_key_length);
00660     line->first = node->next;
00661     node_dispose (node);
00662     }
00663     else {
00664     args.print_key (node->info.user_node, node->info.key_start, remaining_space);
00665     node->info.key_start += remaining_space;
00666     node->info.key_length -= remaining_space;
00667     node->pos.left = next_stripe;
00668     }
00669 }
00670 
00671 
00672 
00673 static SXVOID   print_one_line (void)
00674 {
00675     struct node *node;
00676 
00677     rateau ();
00678 
00679     if (line != lines) {
00680     from_arrows.text [from_arrows.length] = '\0';
00681     args.print_from_arrows (from_arrows.text);
00682     line_no++;
00683     }
00684     else if (!args.abbrev_mode)
00685     args.print_from_arrows ("");
00686 
00687     current_pos = start_pos;
00688 
00689     while (current_pos < next_stripe && (node = line->first) != NULL) {
00690     if (node->pos.left < next_stripe)
00691         print_one_node (node);
00692     else
00693         current_pos = next_stripe;
00694     }
00695 
00696     args.put_skip ();
00697     line_no++;
00698 
00699     if (!args.abbrev_mode || line_no < page_length) {
00700     to_arrows.text [to_arrows.length] = '\0';
00701     args.print_to_arrows (to_arrows.text);
00702     line_no++;
00703     }
00704 
00705     if (!args.abbrev_mode || line_no < page_length) {
00706     horizontal_bar.text [horizontal_bar.length] = '\0';
00707     args.print_horizontal_bar (horizontal_bar.text);
00708     line_no++;
00709     }
00710 }
00711 
00712 
00713 
00714 static SXVOID   tree_print (void)
00715 {
00716     line_no = 0;
00717 
00718     for (start_pos = minpos; start_pos <= maxpos; start_pos = next_stripe) {
00719     next_stripe = start_pos + args.page_width;
00720 
00721     if (!args.abbrev_mode)
00722         args.put_page ();
00723 
00724     for (line = lines; line != NULL; line = line->next) {
00725         print_one_line ();
00726     }
00727     }
00728 
00729     if (!args.abbrev_mode)
00730     args.put_page ();
00731 }
00732 
00733 
00734 
00735 static char *strings = {NULL};
00736 
00737 
00738 
00739 SXVOID  sxpptree (USER_PTR tree,
00740           long min_dist,
00741           long min_dist_on_subtrees,
00742           long page_width,
00743           long (*get_key_length) (USER_PTR),
00744           USER_PTR (*get_left_son) (USER_PTR),
00745           USER_PTR (*get_right_brother) (USER_PTR),
00746           long (*get_sons_number) (USER_PTR),
00747           SXVOID (*print_from_arrows) (char *),
00748           SXVOID (*print_horizontal_bar) (char *),
00749           SXVOID (*print_key) (USER_PTR, SXINT, long),
00750           SXVOID (*print_to_arrows) (char *),
00751           SXVOID (*put_blanks) (long),
00752           SXVOID (*put_page) (void),
00753           SXVOID (*put_skip) (void),
00754           long switches)
00755 {
00756     args.min_dist = min_dist < 1 ? 3 : min_dist;
00757     args.min_dist_on_subtrees = min_dist_on_subtrees < args.min_dist ? args.min_dist : min_dist_on_subtrees;
00758     args.page_width = page_width < min_dist_on_subtrees ? (min_dist_on_subtrees < 132 ? 132 : min_dist_on_subtrees) :
00759      page_width;
00760     args.get_key_length = get_key_length;
00761     args.get_left_son = get_left_son;
00762     args.get_right_brother = get_right_brother;
00763     args.get_sons_number = get_sons_number;
00764     args.print_from_arrows = print_from_arrows;
00765     args.print_horizontal_bar = print_horizontal_bar;
00766     args.print_key = print_key;
00767     args.print_to_arrows = print_to_arrows;
00768     args.put_blanks = put_blanks;
00769     args.put_page = put_page;
00770     args.put_skip = put_skip;
00771     args.abbrev_mode = (switches & (long)0x8000) != 0;
00772 
00773     if (args.abbrev_mode) {
00774     page_length = args.get_key_length (NULL);
00775     max_level = (page_length + 2) / 4;
00776     }
00777 
00778     if (setjmp (no_space))
00779     fprintf (stderr, "\npp_trees: no more space available\n");
00780     else {
00781     {
00782         SXUINT strlength = args.page_width + 1;
00783 
00784         strings = (char*) allocate (3 * strlength * sizeof (char));
00785         to_arrows.text = (from_arrows.text = (horizontal_bar.text = strings) + strlength) + strlength;
00786     }
00787 
00788     place (tree, &lines, (SXINT)1, SXTRUE);
00789     init_h_bar_ovfl ();
00790 
00791     if (args.abbrev_mode)
00792         abbreviate_tree ();
00793     else
00794         min_max_pos ();
00795 
00796     tree_print ();
00797     }
00798 
00799     lines_destroy (lines);
00800     lines = NULL;
00801 
00802     if (strings != NULL)
00803     free (strings), strings = NULL;
00804 
00805     deallocate_areas ();
00806 }

Generated on Wed Apr 21 16:39:34 2010 for syntax-6.0b7 by  doxygen 1.6.1