00001
00036 #include "util_hack.h"
00037 #include "mtrInt.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #ifndef lint
00056 static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $";
00057 #endif
00058
00059
00060
00061
00062
00065
00066
00067
00068
00069 static int mtrShiftHL ARGS((MtrNode *node, int shift));
00070
00073
00074
00075
00076
00077
00091 MtrNode *
00092 Mtr_InitGroupTree(
00093 int lower,
00094 int size)
00095 {
00096 MtrNode *root;
00097
00098 root = Mtr_InitTree();
00099 if (root == NULL) return(NULL);
00100 root->flags = MTR_DEFAULT;
00101 root->low = lower;
00102 root->size = size;
00103 return(root);
00104
00105 }
00106
00107
00128 MtrNode *
00129 Mtr_MakeGroup(
00130 MtrNode * root ,
00131 unsigned int low ,
00132 unsigned int size ,
00133 unsigned int flags )
00134 {
00135 MtrNode *node,
00136 *first,
00137 *last,
00138 *previous,
00139 *newn;
00140
00141
00142 if (size == 0)
00143 return(NULL);
00144
00145
00146
00147
00148 if (low < (unsigned int) root->low ||
00149 low + size > (unsigned int) (root->low + root->size))
00150 return(NULL);
00151
00152
00153
00154 if (root->size == size && root->low == low) {
00155 root->flags = flags;
00156 return(root);
00157 }
00158
00159
00160
00161
00162
00163
00164 if (root->child == NULL) {
00165 newn = Mtr_AllocNode();
00166 if (newn == NULL) return(NULL);
00167 newn->low = low;
00168 newn->size = size;
00169 newn->flags = flags;
00170 newn->parent = root;
00171 newn->elder = newn->younger = newn->child = NULL;
00172 root->child = newn;
00173 return(newn);
00174 }
00175
00176
00177
00178
00179 previous = NULL;
00180 first = root->child;
00181 while (first != NULL && low >= (unsigned int) (first->low + first->size)) {
00182 previous = first;
00183 first = first->younger;
00184 }
00185 if (first == NULL) {
00186
00187
00188
00189 newn = Mtr_AllocNode();
00190 if (newn == NULL) return(NULL);
00191 newn->low = low;
00192 newn->size = size;
00193 newn->flags = flags;
00194 newn->parent = root;
00195 newn->elder = previous;
00196 previous->younger = newn;
00197 newn->younger = newn->child = NULL;
00198 return(newn);
00199 }
00200
00201 if (low >= (unsigned int) first->low &&
00202 low + size <= (unsigned int) (first->low + first->size)) {
00203
00204 newn = Mtr_MakeGroup(first, low, size, flags);
00205 return(newn);
00206 } else if (low + size <= first->low) {
00207
00208
00209 newn = Mtr_AllocNode();
00210 if (newn == NULL) return(NULL);
00211 newn->low = low;
00212 newn->size = size;
00213 newn->flags = flags;
00214 newn->child = NULL;
00215 newn->parent = root;
00216 newn->elder = previous;
00217 newn->younger = first;
00218 first->elder = newn;
00219 if (previous != NULL) {
00220 previous->younger = newn;
00221 } else {
00222 root->child = newn;
00223 }
00224 return(newn);
00225 } else if (low < (unsigned int) first->low &&
00226 low + size < (unsigned int) (first->low + first->size)) {
00227
00228 return(NULL);
00229 } else if (low > first->low) {
00230
00231
00232
00233 return(NULL);
00234 }
00235
00236
00237
00238
00239 last = first->younger;
00240 while (last != NULL &&
00241 (unsigned int) (last->low + last->size) < low + size) {
00242 last = last->younger;
00243 }
00244 if (last == NULL) {
00245
00246
00247 newn = Mtr_AllocNode();
00248 if (newn == NULL) return(NULL);
00249 newn->low = low;
00250 newn->size = size;
00251 newn->flags = flags;
00252 newn->child = first;
00253 newn->parent = root;
00254 newn->elder = previous;
00255 newn->younger = NULL;
00256 first->elder = NULL;
00257 if (previous != NULL) {
00258 previous->younger = newn;
00259 } else {
00260 root->child = newn;
00261 }
00262 last = first;
00263 while (last != NULL) {
00264 last->parent = newn;
00265 last = last->younger;
00266 }
00267 return(newn);
00268 }
00269
00270
00271 if (low + size - 1 >= (unsigned int) last->low &&
00272 low + size < (unsigned int) (last->low + last->size)) {
00273
00274 return(NULL);
00275 }
00276
00277
00278
00279
00280
00281
00282
00283 newn = Mtr_AllocNode();
00284 if (newn == NULL) return(NULL);
00285 newn->low = low;
00286 newn->size = size;
00287 newn->flags = flags;
00288 newn->child = first;
00289 newn->parent = root;
00290 if (previous == NULL) {
00291 root->child = newn;
00292 } else {
00293 previous->younger = newn;
00294 }
00295 newn->elder = previous;
00296 newn->younger = last->younger;
00297 if (last->younger != NULL) {
00298 last->younger->elder = newn;
00299 }
00300 last->younger = NULL;
00301 first->elder = NULL;
00302 for (node = first; node != NULL; node = node->younger) {
00303 node->parent = newn;
00304 }
00305
00306 return(newn);
00307
00308 }
00309
00310
00327 MtrNode *
00328 Mtr_DissolveGroup(
00329 MtrNode * group )
00330 {
00331 MtrNode *parent;
00332 MtrNode *last;
00333
00334 parent = group->parent;
00335
00336 if (parent == NULL) return(NULL);
00337 if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL);
00338
00339
00340
00341 for (last = group->child; last->younger != NULL; last = last->younger) {
00342 last->parent = parent;
00343 }
00344 last->parent = parent;
00345
00346 last->younger = group->younger;
00347 if (group->younger != NULL) {
00348 group->younger->elder = last;
00349 }
00350
00351 group->child->elder = group->elder;
00352 if (group == parent->child) {
00353 parent->child = group->child;
00354 } else {
00355 group->elder->younger = group->child;
00356 }
00357
00358 Mtr_DeallocNode(group);
00359 return(parent);
00360
00361 }
00362
00363
00379 MtrNode *
00380 Mtr_FindGroup(
00381 MtrNode * root ,
00382 unsigned int low ,
00383 unsigned int size )
00384 {
00385 MtrNode *node;
00386
00387 #ifdef MTR_DEBUG
00388
00389 assert(!MTR_TEST(root,MTR_TERMINAL));
00390 #endif
00391
00392
00393 if (size < 1) return(NULL);
00394
00395
00396
00397
00398 if (low < (unsigned int) root->low ||
00399 low + size > (unsigned int) (root->low + root->size))
00400 return(NULL);
00401
00402 if (root->size == size && root->low == low)
00403 return(root);
00404
00405 if (root->child == NULL)
00406 return(NULL);
00407
00408
00409
00410
00411 node = root->child;
00412 while (low >= (unsigned int) (node->low + node->size)) {
00413 node = node->younger;
00414 }
00415 if (low + size <= (unsigned int) (node->low + node->size)) {
00416
00417 node = Mtr_FindGroup(node, low, size);
00418 return(node);
00419 } else {
00420 return(NULL);
00421 }
00422
00423 }
00424
00425
00440 int
00441 Mtr_SwapGroups(
00442 MtrNode * first ,
00443 MtrNode * second )
00444 {
00445 MtrNode *node;
00446 MtrNode *parent;
00447 int sizeFirst;
00448 int sizeSecond;
00449
00450 if (second->younger == first) {
00451 node = first;
00452 first = second;
00453 second = node;
00454 } else if (first->younger != second) {
00455 return(0);
00456 }
00457
00458 sizeFirst = first->size;
00459 sizeSecond = second->size;
00460
00461
00462 parent = first->parent;
00463 if (parent == NULL || second->parent != parent) return(0);
00464 if (parent->child == first) {
00465 parent->child = second;
00466 } else {
00467 first->elder->younger = second;
00468 }
00469 if (second->younger != NULL) {
00470 second->younger->elder = first;
00471 }
00472 first->younger = second->younger;
00473 second->elder = first->elder;
00474 first->elder = second;
00475 second->younger = first;
00476
00477
00478 if (!mtrShiftHL(first,sizeSecond)) return(0);
00479 if (!mtrShiftHL(second,-sizeFirst)) return(0);
00480
00481 return(1);
00482
00483 }
00484
00485
00507 void
00508 Mtr_PrintGroups(
00509 MtrNode * root ,
00510 int silent )
00511 {
00512 MtrNode *node;
00513
00514 assert(root != NULL);
00515 assert(root->younger == NULL || root->younger->elder == root);
00516 assert(root->elder == NULL || root->elder->younger == root);
00517 if (!silent) (void) printf("(%d",root->low);
00518 if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
00519 if (!silent) (void) printf(",");
00520 } else {
00521 node = root->child;
00522 while (node != NULL) {
00523 assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
00524 assert(node->parent == root);
00525 Mtr_PrintGroups(node,silent);
00526 node = node->younger;
00527 }
00528 }
00529 if (!silent) {
00530 (void) printf("%d", root->low + root->size - 1);
00531 if (root->flags != MTR_DEFAULT) {
00532 (void) printf("|");
00533 if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
00534 if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
00535 if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
00536 }
00537 (void) printf(")");
00538 if (root->parent == NULL) (void) printf("\n");
00539 }
00540 assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
00541 return;
00542
00543 }
00544
00545
00573 MtrNode *
00574 Mtr_ReadGroups(
00575 FILE * fp ,
00576 int nleaves )
00577 {
00578 int low;
00579 int size;
00580 int err;
00581 unsigned int flags;
00582 MtrNode *root;
00583 MtrNode *node;
00584 char attrib[8*sizeof(unsigned int)+1];
00585 char *c;
00586
00587 root = Mtr_InitGroupTree(0,nleaves);
00588 if (root == NULL) return NULL;
00589
00590 while (! feof(fp)) {
00591
00592 err = fscanf(fp, "%d %d %s", &low, &size, attrib);
00593 if (err == EOF) {
00594 break;
00595 } else if (err != 3) {
00596 return(NULL);
00597 } else if (low < 0 || low+size > nleaves || size < 1) {
00598 return(NULL);
00599 } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) {
00600
00601
00602 return(NULL);
00603 }
00604
00605
00606
00607
00608 flags = MTR_DEFAULT;
00609 for (c=attrib; *c != 0; c++) {
00610 switch (*c) {
00611 case 'D':
00612 break;
00613 case 'F':
00614 flags |= MTR_FIXED;
00615 break;
00616 case 'N':
00617 flags |= MTR_NEWNODE;
00618 break;
00619 case 'S':
00620 flags |= MTR_SOFT;
00621 break;
00622 case 'T':
00623 flags |= MTR_TERMINAL;
00624 break;
00625 default:
00626 return NULL;
00627 }
00628 }
00629 node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size,
00630 flags);
00631 if (node == NULL) return(NULL);
00632 }
00633
00634 return(root);
00635
00636 }
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00662 static int
00663 mtrShiftHL(
00664 MtrNode * node ,
00665 int shift )
00666 {
00667 MtrNode *auxnode;
00668 int low;
00669
00670 low = (int) node->low;
00671
00672
00673 low += shift;
00674
00675 if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0);
00676
00677 node->low = (MtrHalfWord) low;
00678
00679 if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) {
00680 auxnode = node->child;
00681 do {
00682 if (!mtrShiftHL(auxnode,shift)) return(0);
00683 auxnode = auxnode->younger;
00684 } while (auxnode != NULL);
00685 }
00686
00687 return(1);
00688
00689 }
00690