XxY_mngr.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 static char ME [] = "XxY_mngr";
00030 
00031 
00032 #include "sxversion.h"
00033 #include "sxcommon.h"
00034 #include "XxY.h"
00035 #include <memory.h>
00036 
00037 char WHAT_XXY_MNGR[] = "@(#)SYNTAX - $Id: XxY_mngr.c 1491 2008-07-23 16:13:15Z sagot $" WHAT_DEBUG;
00038 
00039 extern void sxtrap (char *caller, char *message);
00040 extern SXINT  sxlast_bit (SXINT nb);
00041 
00042 static SXINT        X_, Y_;
00043 static XxY_header   *HEADER_;
00044 static SXINT        KIND_;
00045 
00046 
00047 static void XxY_cpy (struct XxY_elem *old, struct XxY_elem *new, SXINT old_size)
00048 {
00049     struct XxY_elem *old_top = old + old_size;
00050 
00051     do {
00052     *new++ = *old++;
00053     } while (old <= old_top);
00054 }
00055 
00056 static void XxY_assoc_oflw (SXINT old_size, SXINT new_size)
00057 {
00058     /* La variable statique KIND_ est positionnee. */
00059     SXINT   *old = HEADER_->lnk_hd [KIND_];
00060 
00061     if (HEADER_->X_hd_is_static [KIND_]) {
00062     X_root_int_cpy (old,
00063             HEADER_->lnk_hd [KIND_] = (SXINT*) sxalloc (new_size + 1, sizeof (SXINT)),
00064             old_size);
00065     }
00066     else
00067     HEADER_->lnk_hd [KIND_] = (SXINT*) sxrealloc (old, new_size + 1, sizeof (SXINT));
00068 }
00069 
00070 
00071 
00072 static void XxY_system_oflw (SXINT old_top)
00073 {
00074     /* Appele depuis X_root sur debordement (ou lock) de "hash_lnk". */
00075     /* Suivant que la structure est statique ou non, On alloue ou realloue
00076        "display" et les "lnk" des "foreach" (s'il y en a) */
00077     SXINT kind, *old_lnk;
00078 
00079     if (HEADER_->is_static) {
00080     /* Premiere allocation dynamique */
00081     struct XxY_elem *old_display = HEADER_->display;
00082 
00083     XxY_cpy (old_display,
00084          HEADER_->display = (struct XxY_elem*) sxalloc (HEADER_->size + 1,
00085                                 sizeof (struct XxY_elem)),
00086          old_top);
00087     }
00088     else
00089     HEADER_->display = (struct XxY_elem*) sxrealloc (HEADER_->display,
00090                              HEADER_->size + 1,
00091                              sizeof (struct XxY_elem));
00092     
00093     if (HEADER_->suppress != NULL)
00094     for (kind = 0; kind < 2;kind++) {
00095         if ((old_lnk = HEADER_->lnk [kind]) != NULL) {
00096         if (HEADER_->is_static) {
00097             /* Premiere allocation dynamique */
00098             X_root_int_cpy (old_lnk,
00099                     HEADER_->lnk [kind] = (SXINT*) sxalloc (HEADER_->size + 1,
00100                                       sizeof (SXINT)),
00101                     old_top);
00102         }
00103         else
00104             HEADER_->lnk [kind] = (SXINT*) sxrealloc (old_lnk,
00105                                 HEADER_->size + 1,
00106                                 sizeof (SXINT));
00107         }
00108     }
00109 }
00110 
00111 
00112 static SXINT XxY_cmp (SXINT x)
00113 {
00114     /* Appele depuis X_root_is_set.
00115        "Compare" l'element courant se trouvant a l'indice x avec l'element que l'on
00116        recherche. Cette fonction retourne
00117           -1 si <
00118       0  si ==
00119       1  si >
00120     */
00121     SXINT       z;
00122     struct XxY_elem *aelem = HEADER_->display + x;
00123 
00124     if ((z = aelem->X) >= X_) {
00125     if (z == X_) {
00126         if ((z = aelem->Y) >= Y_)
00127         return z == Y_ ? 0 : 1;
00128 
00129         return -1;
00130     }
00131 
00132     return 1;
00133     }
00134 
00135     return -1;
00136 }
00137 
00138 
00139 static SXUINT XxY_scrmbl (SXINT x)
00140 {
00141     /* Retourne la valeur du "scramble" de l'element d'indice x. */
00142     /* Positionne X_ et Y_, ce qui permet d'appeler "cmp". */
00143     struct XxY_elem *aelem = HEADER_->display + x;
00144 
00145     X_ = aelem->X, Y_ = aelem->Y;
00146     return XxY_HASH_FUN (X_, Y_);
00147 }
00148 
00149 static SXINT XxY_assign (SXINT x)
00150 {
00151     /* Positionne le doublet courant a l'indice x et traite les "foreach". */
00152     struct XxY_elem *aelem = HEADER_->display + x;
00153     SXINT       kind;
00154     SXINT       *lnk;
00155     SXINT               head;
00156     
00157     aelem->X = X_;
00158     aelem->Y = Y_;
00159 
00160     if (HEADER_->suppress != NULL) {
00161     /* Il y a des "foreach". */
00162     for (kind = 0; kind < 2; kind++) {
00163         /* Traitement du cas "associatif" */
00164         if ((lnk = HEADER_->lnk [kind]) != NULL) {
00165         /* positionnement de la variable statique KIND_ si X_hd deborde */
00166         if (X_set (HEADER_->X_hd [KIND_ = kind], kind == XY_X ? X_ : Y_, &head))
00167             /* Ce n'est pas le premier X */
00168             lnk [x] = HEADER_->lnk_hd [kind][head];
00169         else
00170             lnk [x] = 0;
00171         
00172         HEADER_->lnk_hd [kind][head] = x;
00173         }
00174     }
00175     }
00176 
00177     return 0;
00178 }
00179 
00180 
00181 static SXINT XY_orig (SXINT x, SXINT kind)
00182 {
00183     struct XxY_elem *aelem = HEADER_->display + x;
00184     SXINT       indice;
00185 
00186     if ((indice = X_is_set (HEADER_->X_hd [kind], kind == XY_X ? aelem->X : aelem->Y)) == 0)
00187     sxtrap (ME, "XY_orig");
00188 
00189     return indice;
00190 }
00191 
00192 
00193 static SXINT  XxY_suppress (SXINT erased_lnk_hd)
00194 {
00195     /* Supprime, vis-a-vis des "foreach" les elements de la liste erased_lnk_hd. */
00196     SXINT       *low, *lnk;
00197     SXINT       x, y, orig;
00198     SXINT       *hash_lnk = HEADER_->hash_lnk;
00199 
00200     if ((lnk = HEADER_->lnk [XY_X]) != NULL) {
00201     x = erased_lnk_hd;
00202 
00203     do {
00204         low = HEADER_->lnk_hd [XY_X] + (orig = XY_orig (x, (SXINT)XY_X));
00205 
00206         while ((y = *low) != x)
00207         low = lnk + y;
00208 
00209         if ((*low = lnk [x]) == 0 && low == HEADER_->lnk_hd [XY_X] + orig)
00210         X_erase (*(HEADER_->X_hd [XY_X]), orig);
00211 
00212     } while ((x = (hash_lnk [x] & XxY_7F)) != 0);
00213     }
00214 
00215     if ((lnk = HEADER_->lnk [XY_Y]) != NULL) {
00216     x = erased_lnk_hd;
00217 
00218     do {
00219         low = HEADER_->lnk_hd [XY_Y] + (orig = XY_orig (x, (SXINT)XY_Y));
00220 
00221         while ((y = *low) != x)
00222         low = lnk + y;
00223 
00224         if ((*low = lnk [x]) == 0 && low == HEADER_->lnk_hd [XY_Y] + orig)
00225         X_erase (*(HEADER_->X_hd [XY_Y]), orig);
00226 
00227     } while ((x = (hash_lnk [x] & XxY_7F)) != 0);
00228     }
00229 
00230     return 0;
00231 }
00232 
00233 void    XxY_alloc (XxY_header *header, char *name, SXINT init_elem_nb, SXINT average_list_nb_per_bucket, SXINT average_X_assoc, SXINT average_Y_assoc, void (*user_oflw) (SXINT, SXINT), FILE *stat_file)
00234 {
00235     /* Cette fonction "cree" une matrice creuse extensible de dimension 2 */
00236     /* De header "header", de nom "name", dont la taille initiale de la table de hash_code
00237        est un nombre premier et la longueur moyenne des chaines de collision est
00238        "average_list_nb_per_bucket". La taille de la structure est doublee chaque fois
00239        que cette longueur moyenne depasse la taille fixee, de plus la fonction utilisateur
00240        "oflw" est appelee.
00241        Si "average_X_assoc" (resp. "average_y_assoc") est non nul, on veut pouvoir
00242        parcourir tous les couples (X, Y) ayant un X (resp. Y) donne, par l'intermediaire
00243        de la macro XxY_Xforeach (resp. XxY_Yforeach). Dans ce cas "average_X_assoc"
00244        (resp. "average_y_assoc") est la longueur moyenne de la liste de collision
00245        liant entre eux les ensembles de couples (X, Y) ayant meme valeur de hash_code
00246        sur X (resp. Y). Si cette valeur moyenne est depassee, la structure est doublee.
00247        Pour un X (resp. Y) donne, on obtient les Y (resp. X) correspondants par ordre
00248        croissant. */
00249     SXINT   lgth, has_foreach;
00250 
00251     sxinitialise(lgth); /* pour faire taire "gcc -Wuninitialized" */
00252     has_foreach = average_X_assoc + average_Y_assoc;
00253 
00254     X_root_alloc ((X_root_header*)header, name, init_elem_nb, average_list_nb_per_bucket, XxY_system_oflw,
00255           user_oflw, XxY_cmp, XxY_scrmbl, has_foreach ? XxY_suppress : NULL,
00256           XxY_assign, stat_file);
00257     header->display = (struct XxY_elem*) sxalloc (header->size + 1, sizeof (struct XxY_elem));
00258 
00259     if (has_foreach)
00260     /* On suppose que la relation est pleine a 1/16 (environ 7%), l'estimation du
00261        nombre de lignes (ou de colonnes) est donc de 4 fois la racine carree. */
00262     /* 4 fois la racine carree (gromo sodo) */
00263     lgth = 1 + (1 << ((sxlast_bit (header->size) + 1 + 4) / 2));
00264 
00265     if (average_X_assoc != 0) {
00266     header->X_hd [XY_X] = (X_header*) sxalloc (1, sizeof (X_header));
00267     X_alloc (header->X_hd [XY_X], name, lgth, average_X_assoc, XxY_assoc_oflw, stat_file);
00268     header->lnk_hd [XY_X] = (SXINT*) sxalloc (X_size (*(header->X_hd [XY_X])) + 1, sizeof (SXINT));
00269     header->lnk_hd [XY_X][0] = 0 /* Permet, si liste vide, de ne pas executer un "foreach". */;
00270     header->lnk [XY_X] = (SXINT*) sxalloc (header->size + 1, sizeof (SXINT));
00271     header->lnk [XY_X][0] = 0 /* Permet de quitter un "foreach" en positionnant la variable a 0 */;
00272     header->X_hd_is_static [XY_X] = SXFALSE;
00273     }
00274     else {
00275     header->X_hd [XY_X] = NULL;
00276     header->lnk_hd [XY_X] = header->lnk [XY_X] = NULL;
00277     header->X_hd_is_static [XY_X] = SXFALSE;
00278     }
00279 
00280     if (average_Y_assoc != 0) {
00281     header->X_hd [XY_Y] = (X_header*) sxalloc (1, sizeof (X_header));
00282     X_alloc (header->X_hd [XY_Y], name, lgth, average_Y_assoc, XxY_assoc_oflw, stat_file);
00283     header->lnk_hd [XY_Y] = (SXINT*) sxalloc (X_size (*(header->X_hd [XY_Y])) + 1, sizeof (SXINT));
00284     header->lnk_hd [XY_Y][0] = 0 /* Permet, si liste vide, de ne pas executer un "foreach". */;
00285     header->lnk [XY_Y] = (SXINT*) sxalloc (header->size + 1, sizeof (SXINT));
00286     header->lnk [XY_Y][0] = 0 /* Permet de quitter un "foreach" en positionnant la variable a 0 */;
00287     header->X_hd_is_static [XY_Y] = SXFALSE;
00288     }
00289     else {
00290     header->X_hd [XY_Y] = NULL;
00291     header->lnk_hd [XY_Y] = header->lnk [XY_Y] = NULL;
00292     header->X_hd_is_static [XY_Y] = SXFALSE;
00293     }
00294 }
00295 
00296 
00297 
00298 void    XxY_clear (XxY_header *header)
00299 {
00300     X_header    *Xhd;
00301     SXINT   kind;
00302 
00303     if (header->top != 0) {
00304     X_root_clear ((X_root_header*)header);
00305 
00306     for (kind = 0; kind < 2; kind++) {
00307         if ((Xhd = header->X_hd [kind]) != NULL)
00308         X_clear (Xhd);
00309     }
00310     }
00311 }
00312 
00313 
00314 
00315 void    XxY_stat (FILE *stat_file, XxY_header *header)
00316 {
00317     SXINT   x, i, l, n;
00318     X_header    *Xhd;
00319     SXINT   *lnk_hd, *lnk;
00320     SXINT           minl, maxl, meanl, kind;
00321 
00322     if (stat_file != NULL) {
00323     X_root_stat (stat_file, (X_root_header*)header);
00324 
00325     if (header->top != 0) {
00326         for (kind = 0; kind < 2; kind++) {
00327         if ((Xhd = header->X_hd [kind]) != NULL) {
00328             lnk_hd = header->lnk_hd [kind];
00329             lnk = header->lnk [kind];
00330             fprintf (stat_file, "X_statistics\n");
00331             X_stat (stat_file, Xhd);
00332             meanl = 0;
00333             maxl = 0;
00334             minl = XxY_7F;
00335             n = 0;
00336             
00337             for (x = X_top (*(Xhd)); x > 0;x--) {
00338             n++;
00339             l = 0;
00340             
00341             for (i = lnk_hd [x]; i != 0; i = lnk [i]) {
00342                 l++;
00343             }
00344             
00345             if (l < minl)
00346                 minl = l;
00347 
00348             if (l > maxl)
00349                 maxl = l;
00350 
00351             meanl += l;
00352             }
00353             
00354             meanl /= n;
00355             fprintf (stat_file, "X_minl = %ld, X_maxl = %ld, X_meanl = %ld\n", (long)minl, (long)maxl, (long)meanl);
00356         }
00357         }
00358     }
00359     }
00360 }
00361 
00362 
00363 
00364 
00365 void    XxY_free (XxY_header *header)
00366 {
00367     SXINT   kind;
00368     X_header    *Xhd;
00369 
00370     if (!header->is_static)
00371     {
00372     X_root_free ((X_root_header*)header);
00373     sxfree (header->display), header->display = NULL;
00374     }
00375 
00376     for (kind = 0; kind < 2; kind++) {
00377     if ((Xhd = header->X_hd [kind]) != NULL) {
00378         if (!Xhd->is_static)
00379         {
00380         X_free (Xhd);
00381         sxfree (header->lnk_hd [kind]), header->lnk_hd [kind] = NULL;
00382         
00383         if (!header->X_hd_is_static [kind])
00384             sxfree (Xhd), header->X_hd [kind] = NULL;
00385         }
00386 
00387         if (!header->is_static)
00388         sxfree (header->lnk [kind]), header->lnk [kind] = NULL;
00389     }
00390     }
00391 }
00392 
00393 
00394 
00395 SXINT   XxY_is_set (XxY_header *header, SXINT X, SXINT Y)
00396 {
00397     /* Si l'element X-Y de la matrice creuse header existe, cette fonction
00398        retourne l'identifiant de cet element, sinon elle retourne 0 */
00399 
00400     SXINT z;
00401 
00402     X_ = X, Y_ = Y;
00403 
00404     if ((z = X_root_is_set ((X_root_header*)(HEADER_ = header), XxY_HASH_FUN (X_, Y_))) <= 0)
00405     return 0;
00406     
00407     return header->hash_lnk [z] & XxY_80 ? 0 : z;
00408 }
00409 
00410 
00411 
00412 void    XxY_gc (XxY_header *header)
00413 {
00414     /* Cette procedure supprime physiquement les elements effaces
00415        par un "XxY_erase" et permet la reutilisation des indices
00416        ainsi recuperes. */
00417     SXINT       x, erased_lnk_hd;
00418     SXINT       *hash_lnk, *alnk;
00419 
00420     if (header->has_free_buckets != 0 && (erased_lnk_hd = X_root_gc ((X_root_header*)header)) > 0) {
00421     /* Traitement des "foreach" des elements supprimes. */
00422     if ((HEADER_ = header)->suppress != NULL) /* Il y a des foreach. */
00423         XxY_suppress (erased_lnk_hd);
00424 
00425     hash_lnk = HEADER_->hash_lnk;
00426     
00427     /* On concatene erased_lnh_hd a free_buckets. */
00428     for ((alnk = &(HEADER_->free_buckets)); (x = (*alnk & XxY_7F)) != 0; alnk = hash_lnk + x);
00429     
00430     *alnk = erased_lnk_hd | XxY_80;
00431     }
00432 }
00433 
00434 
00435 SXBOOLEAN   XxY_set (XxY_header *header, SXINT X, SXINT Y, SXINT *ref)
00436 {
00437     /* Si l'element X-Y de la matrice creuse header existe, cette fonction
00438        retourne SXTRUE et ref designe cet element, sinon elle cree un nouvel
00439        element, ref le designe et elle retourne SXFALSE */
00440 
00441     if (header->is_locked)
00442     sxtrap ("XxY_set", header->name);
00443 
00444     X_ = X, Y_ = Y;
00445 
00446     return X_root_set ((X_root_header*)(HEADER_ = header), XxY_HASH_FUN (X_, Y_), ref);
00447 }
00448 
00449 
00450 void    XxY_lock (XxY_header *header)
00451 {
00452     /* Cette procedure
00453           - Ajuste au minimum la taille de la structure XxY
00454       - Interdit l'utilisation ulterieure de XxY_set
00455       - Appelle (si non NULL) la procedure utilisateur oflw
00456        L'utisateur vient peut etre d'appeler XxY_gc. */
00457     SXINT kind;
00458 
00459     if (header->is_locked)
00460     return;
00461 
00462     HEADER_ = header;
00463 
00464     if (header->suppress != NULL)
00465     for (kind = 0; kind < 2;kind++) {
00466         if (header->lnk [kind] != NULL) {
00467         /* positionnement de la variable statique KIND_ pour
00468            la reallocation de lnk_hd */
00469         X_lock (header->X_hd [KIND_ = kind]);
00470         }
00471     }
00472 
00473     X_root_lock ((X_root_header*)header);
00474 }
00475 
00476 
00477 void    XxY_unlock (XxY_header *header)
00478 {
00479     /* Cette procedure
00480           - Ajuste au minimum la taille de la structure XxY
00481       - Interdit l'utilisation ulterieure de XxY_set
00482       - Appelle (si non NULL) la procedure utilisateur oflw
00483        L'utisateur vient peut etre d'appeler XxY_gc. */
00484     SXINT kind;
00485 
00486     if (!header->is_locked)
00487     return;
00488 
00489     if (header->suppress != NULL)
00490     for (kind = 0; kind < 2;kind++) {
00491         if (header->lnk [kind] != NULL) {
00492           X_unlock (*(header->X_hd [kind]));
00493         }
00494     }
00495 
00496     header->is_locked = SXFALSE;
00497 }
00498 
00499 
00500 SXBOOLEAN   XxY_set_and_close (XxY_header *header, SXINT X, SXINT Y, SXINT *ref)
00501 {
00502     /* Si R est une relation binaire, header contient la fermeture transitive
00503        R+ de R.
00504        Complete, si necessaire, R+ par ajout de l'element (X, Y).
00505        Ref designe ce (nouvel) element.
00506        Retourne SXTRUE si ref existait deja, SXFALSE sinon. */
00507     SXINT   x, y, X1;
00508 
00509     if ((*ref = XxY_is_set (header, X, Y)))
00510     return SXTRUE;
00511 
00512     if (X != Y) {
00513     XxY_Yforeach (*header, X, x) {
00514         X1 = XxY_X (*header, x);
00515 
00516         XxY_Xforeach (*header, Y, y) {
00517         XxY_set (header, X1, XxY_Y (*header, y), ref);
00518         }
00519 
00520         XxY_set (header, X1, Y, ref);
00521     }
00522 
00523     XxY_Xforeach (*header, Y, y) {
00524         XxY_set (header, X, XxY_Y (*header, y), ref);
00525     }
00526     }
00527 
00528     return XxY_set (header, X, Y, ref);
00529 }
00530 
00531 
00532 void    XxY_to_SXBM (XxY_header *header, SXBOOLEAN (*get_couple) (SXINT*, SXINT*, SXINT), SXINT couple_nb, X_header *index_hd, SXBA **M)
00533 {
00534     /* Si header est non NULL, il contient une relation binaire R.
00535        Sinon, on peut obtenir successivement les couples de cette relation
00536        par get_couple.
00537        couple_nb est le nombre de couples.
00538        Cette procedure stocke "au minimum" cette relation dans la matrice
00539        de bits carree M.
00540        index_hd est un X_header qui assure la correspondance entre
00541        les constituants des elements de R et les indices de M. */
00542     SXINT   x, n, old_n;
00543     SXINT           X, Y, ind1, ind2;
00544     SXBA    *bm;
00545     SXBOOLEAN       OK;
00546 
00547     n = 2 * couple_nb + 1;
00548 
00549     if (*M == NULL) {
00550     X_alloc (index_hd, "index_hd", n, 2, NULL, NULL);
00551     bm = *M = sxbm_calloc (n, n);
00552     }
00553     else {
00554     X_clear (index_hd);
00555     /* On suppose que M est une matrice carree */
00556     bm = *M;
00557     old_n = (SXINT) SXBASIZE (bm [0]);
00558     X = (n < old_n) ? n : old_n;
00559 
00560     for (x = 1; x < X; x++)
00561         sxba_empty (bm [x]);
00562     
00563     if (n > old_n)
00564         bm = *M = sxbm_resize (bm, old_n, n, n);
00565     }
00566 
00567     /* On initialise M avec R */
00568     /* On remplit index_hd */
00569 
00570     for (x = 1; x <= couple_nb; x++) {
00571     if (get_couple != NULL) {
00572         OK = SXTRUE;
00573         get_couple (&X, &Y, x);
00574     }
00575     else if ((OK = !XxY_is_erased (*header, x))) {
00576         X = XxY_X (*header, x);
00577         Y = XxY_Y (*header, x);
00578     }
00579 
00580     if (OK) {
00581         X_set (index_hd, X, &ind1);
00582         X_set (index_hd, Y, &ind2);
00583         SXBA_1_bit (bm [ind1], ind2);
00584     }
00585     }
00586 }
00587 
00588 
00589 SXBOOLEAN XxY_write (XxY_header *header, sxfiledesc_t F_XxY /* file descriptor */)
00590 {
00591     size_t      bytes;
00592     SXINT   kind;
00593     X_header    *X_hd;
00594     SXINT   *lnk_hd, *lnk;
00595     SXBOOLEAN   is_X_hd;
00596 
00597 #define WRITE(p,l)  if ((bytes = (l)) > 0 && ((size_t)write (F_XxY, p, bytes) != bytes)) return SXFALSE
00598 
00599     if (!X_root_write ((X_root_header*)header, F_XxY))
00600     return SXFALSE;
00601 
00602     WRITE (header->display, sizeof (struct XxY_elem) * (header->top + 1));
00603 
00604     for (kind = 0; kind < 2; kind++) {
00605     is_X_hd = (X_hd = header->X_hd [kind]) != NULL;
00606 
00607     WRITE (&(is_X_hd), sizeof (SXBOOLEAN));
00608 
00609     if (is_X_hd) {
00610         if (!X_write (X_hd, F_XxY))
00611         return SXFALSE;
00612 
00613         lnk_hd = header->lnk_hd [kind];
00614         lnk = header->lnk [kind];
00615 
00616         WRITE (lnk_hd, sizeof (SXINT) * (X_hd->top + 1));
00617         WRITE (lnk, sizeof (SXINT) * (header->top + 1));
00618     }
00619     }
00620 
00621     return SXTRUE;
00622 }
00623 
00624 
00625 SXBOOLEAN XxY_read (XxY_header *header, sxfiledesc_t F_XxY /* file descriptor */, char *name, void (*user_oflw) (SXINT, SXINT), FILE *stat_file)
00626 {
00627     size_t       bytes;
00628     SXINT        kind;
00629     X_header    *X_hd;
00630     SXINT       *lnk_hd, *lnk;
00631     SXBOOLEAN   is_X_hd ;
00632 
00633 #define READ(p,l)   if ((bytes=(l))>0&&(((size_t)read (F_XxY, p, bytes)) != bytes)) return SXFALSE
00634 
00635     if (X_root_read ((X_root_header*)header, F_XxY)) {
00636     header->display = (struct XxY_elem*) sxalloc (header->size + 1, sizeof (struct XxY_elem));
00637     READ (header->display, sizeof (struct XxY_elem) * (header->top + 1));
00638     header->name = name;
00639     header->system_oflw = XxY_system_oflw;
00640     header->user_oflw = user_oflw;
00641     header->cmp = XxY_cmp;
00642     header->scrmbl = XxY_scrmbl;
00643     header->suppress = XxY_suppress;
00644     header->assign = XxY_assign;
00645     header->stat_file = stat_file;
00646 
00647     for (kind = 0; kind < 2; kind++) {
00648         READ (&(is_X_hd), sizeof (SXBOOLEAN));
00649 
00650         if (is_X_hd) {
00651         X_hd = header->X_hd [kind] = (X_header*) sxalloc (1, sizeof (X_header));
00652 
00653         if (!X_read (X_hd, F_XxY, name, XxY_assoc_oflw, stat_file))
00654             return SXFALSE;
00655 
00656         lnk_hd = header->lnk_hd [kind] = (SXINT*) sxalloc (X_hd->size + 1, sizeof (SXINT));
00657         lnk = header->lnk [kind] = (SXINT*) sxalloc (header->size + 1, sizeof (SXINT));
00658 
00659         READ (lnk_hd, sizeof (SXINT) * (X_hd->top + 1));
00660         READ (lnk, sizeof (SXINT) * (header->top + 1));
00661         }
00662         else {
00663         header->X_hd [kind] = NULL;
00664         header->lnk_hd [kind] = NULL;
00665         header->lnk [kind] = NULL;
00666         }
00667 
00668         header->X_hd_is_static [kind] = SXFALSE;
00669     }
00670 
00671     return SXTRUE;
00672     }
00673 
00674     return SXFALSE;
00675 }
00676 
00677 
00678 void XxY_array_to_c (XxY_header *header, FILE *F_XxY /* named output stream */, char *name)
00679 {
00680     SXUINT  i;
00681     SXINT       i_counter, kind;
00682     char    sub_name [128];
00683     X_header    *X_hd;
00684 
00685     fprintf (F_XxY, "\n\nstatic struct XxY_elem %s_display [%ld] = {", name, (long)header->size + 1);
00686 
00687     for (i_counter = 0; i_counter <= header->top; i_counter++) {
00688     if ((i_counter & 3) == 0)
00689         fprintf (F_XxY, "\n/* %ld */ ", (long)i_counter);
00690 
00691     fprintf (F_XxY, "{%ld, %ld}, ", (long)header->display [i_counter].X, (long)header->display [i_counter].Y);
00692     } 
00693 
00694     fprintf (F_XxY, "\n};\n");
00695 
00696     for (kind = 0; kind < 2; kind++) {
00697     if ((X_hd = header->X_hd [kind]) != NULL) {
00698         if ((i = strlen (name)) > 120)
00699             i = 120;
00700 
00701         memcpy (sub_name, name, (size_t)i);
00702         sprintf (sub_name + i, "_X_hd_%ld", (long)kind);
00703         X_to_c (X_hd, F_XxY, sub_name, SXTRUE /* is_static */);
00704 
00705         /* lnk_hd [kind] */
00706         fprintf (F_XxY, "\n\nstatic SXINT %s_lnk_hd_%ld [%ld] = {", name, (long)kind, (long)X_hd->size + 1);
00707 
00708         for (i_counter = 0; i_counter <= X_hd->top; i_counter++) {
00709         if ((i_counter & 7) == 0)
00710             fprintf (F_XxY, "\n/* %ld */ ", (long)i_counter);
00711 
00712         fprintf (F_XxY, "%ld, ", (long)header->lnk_hd [kind] [i_counter]);
00713         } 
00714 
00715         fprintf (F_XxY, "\n};\n");
00716 
00717         /* lnk [kind] */
00718         fprintf (F_XxY, "\n\nstatic SXINT %s_lnk_%ld [%ld] = {", name, (long)kind, (long)header->size + 1);
00719 
00720         for (i_counter = 0; i_counter <= header->top; i_counter++) {
00721         if ((i_counter & 7) == 0)
00722             fprintf (F_XxY, "\n/* %ld */ ", (long)i_counter);
00723 
00724         fprintf (F_XxY, "%ld, ", (long)header->lnk [kind] [i_counter]);
00725         } 
00726 
00727         fprintf (F_XxY, "\n};\n");
00728     }
00729     }
00730 
00731     X_root_array_to_c ((X_root_header*)header, F_XxY, name); /* hash_display, hash_lnk */
00732 }
00733 
00734 void XxY_header_to_c (XxY_header *header, FILE *F_XxY /* named output stream */, char *name)
00735 {
00736     SXINT       kind;
00737     SXBOOLEAN   B [2];
00738 
00739     X_root_header_to_c ((X_root_header*)header, F_XxY, name);
00740 
00741     fprintf (F_XxY, "%s_display, /* display */\n", name);
00742 
00743     for (kind = 0; kind < 2; kind++)
00744     B [kind] = (header->lnk_hd [kind] != NULL);
00745 
00746     fprintf (F_XxY, "{%s%s%s, ", B [0] ? "&" : "NULL", B [0] ? name : "", B [0] ? "_X_hd_0" : "");
00747     fprintf (F_XxY, "%s%s%s}, /* X_hd [2] */\n", B [1] ? "&" : "NULL", B [1] ? name : "", B [1] ? "_X_hd_1" : "");
00748 
00749     fprintf (F_XxY, "{%s%s, ", B [0] ? name : "NULL", B [0] ? "_lnk_hd_0" : "");
00750     fprintf (F_XxY, "%s%s}, /* lnk_hd [2] */\n", B [1] ? name : "NULL", B [1] ? "_lnk_hd_1" : "");
00751 
00752     fprintf (F_XxY, "{%s%s, ", B [0] ? name : "NULL", B [0] ? "_lnk_0" : "");
00753     fprintf (F_XxY, "%s%s}, /* lnk [2] */\n", B [1] ? name : "NULL", B [1] ? "_lnk_1" : "");
00754 
00755     fprintf (F_XxY, "{SXTRUE, SXTRUE} /* X_hd_is_static [2] */\n");
00756 
00757     fprintf (F_XxY, "}");
00758 }
00759 
00760 void XxY_to_c (XxY_header *header, FILE *F_XxY /* named output stream */, char *name, SXBOOLEAN is_static)
00761 {
00762     XxY_array_to_c (header, F_XxY, name);
00763     fprintf (F_XxY, "\n\n%sXxY_header %s =\n", is_static ? "static " : "", name);
00764     XxY_header_to_c (header, F_XxY, name);
00765     fprintf (F_XxY, " /* End XxY_header %s */;\n", name);
00766 }
00767 
00768 
00769 
00770 void XxY_reuse (XxY_header *header, char *name, void (*user_oflw) (SXINT, SXINT), FILE *stat_file)
00771 {
00772     SXINT kind;
00773 
00774     X_root_reuse ((X_root_header*)header, name, XxY_system_oflw,
00775           user_oflw, XxY_cmp, XxY_scrmbl, XxY_suppress,
00776           XxY_assign, stat_file);
00777 
00778     for (kind = 0; kind < 2; kind++) {
00779         if (header->lnk [kind] != NULL)
00780         X_reuse (header->X_hd [kind], name, XxY_assoc_oflw, stat_file);
00781     }
00782 }
00783 

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