00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <ctype.h>
00005
00006 #include "cmt_tag.h"
00007 #include "cmt_database.h"
00008
00009
00010
00011
00012
00013
00014
00015
00016 void Tag::unmark ()
00017 {
00018 if (!selected) return;
00019
00020 if ((priority == PriorityDefault) ||
00021 (priority == PrioritySite) ||
00022 (priority == PriorityUname)) return;
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 selected = false;
00033 def_use = 0;
00034 }
00035
00036
00037 void Tag::unmark_all ()
00038 {
00039 static TagPtrVector& Tags = tags ();
00040
00041 int tag_number;
00042
00043 for (tag_number = 0; tag_number < Tags.size (); tag_number++)
00044 {
00045 Tag* tag = Tags[tag_number];
00046
00047 if (tag->selected) tag->unmark ();
00048 }
00049 }
00050
00055 void Tag::restore_tree ()
00056 {
00057 static TagPtrVector& Tags = tags ();
00058
00059 int tag_number;
00060
00061 for (tag_number = 0; tag_number < Tags.size (); tag_number++)
00062 {
00063 Tag* tag = Tags[tag_number];
00064
00065 if (tag->selected)
00066 {
00067 if (tag->tag_refs.size () > 0)
00068 {
00069 int number;
00070
00071 for (number = 0; number < tag->tag_refs.size (); number++)
00072 {
00073 Tag* ref = tag->tag_refs[number];
00074
00075 ref->mark ();
00076 }
00077 }
00078 }
00079 }
00080 }
00081
00082
00083 void Tag::mark ()
00084 {
00085 if (selected) return;
00086
00087 if (tag_excludes.size () > 0)
00088 {
00089 int number;
00090
00091 for (number = 0; number < tag_excludes.size (); number++)
00092 {
00093 Tag* ref = tag_excludes[number];
00094 if (ref->selected)
00095 {
00096 if (priority > ref->priority)
00097 {
00098
00099
00100
00101
00102
00103
00104 ref->unmark ();
00105 }
00106 else
00107 {
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 return;
00118 }
00119 }
00120 }
00121 }
00122
00123 selected = true;
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 if (tag_refs.size () > 0)
00134 {
00135 int number;
00136
00137 for (number = 0; number < tag_refs.size (); number++)
00138 {
00139 Tag* ref = tag_refs[number];
00140
00141 ref->mark ();
00142 }
00143 }
00144 }
00145
00146
00147 void Tag::action (const CmtSystem::cmt_string_vector& words, Use* use)
00148 {
00149 cmt_string name;
00150 Tag* tag;
00151 Tag* ref;
00152
00153 name = words[1];
00154 if (name == "") return;
00155
00156 tag = add (name, PriorityUserTag, "use", use);
00157
00158 if (tag->tag_refs.size () == 0)
00159 {
00160 int priority = PriorityUserTag;
00161 if (tag->priority > priority)
00162 {
00163 priority = tag->priority;
00164 }
00165
00166 tag->set_use = use;
00167
00168 for (int i = 2; i < words.size (); i++)
00169 {
00170 name = words[i];
00171 if (name == "") break;
00172 ref = add (name, priority, "use", use);
00173 tag->add_tag_ref (ref);
00174 if (tag->selected)
00175 {
00176 ref->mark ();
00177 }
00178 }
00179 }
00180 }
00181
00182
00183 void Tag::action_exclude (const CmtSystem::cmt_string_vector& words, Use* use)
00184 {
00185 cmt_string name;
00186 Tag* tag;
00187 Tag* ref;
00188
00189 name = words[1];
00190 if (name == "") return;
00191
00192 tag = add (name, PriorityUserTag, "use", use);
00193
00194 if (tag->tag_excludes.size () == 0)
00195 {
00196 tag->set_use = use;
00197
00198 int i;
00199
00200 for (i = 2; i < words.size (); i++)
00201 {
00202 cmt_string n;
00203 n = words[i];
00204 if (n == "") break;
00205 ref = add (n, PriorityUserTag, "use", use);
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 tag->add_tag_exclude (ref);
00216 ref->add_tag_exclude (tag);
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 int count = 0;
00228 int winner_count = 0;
00229
00230 Tag* winner = 0;
00231
00232 if (tag->selected)
00233 {
00234 count++;
00235 winner = tag;
00236 winner_count = 1;
00237 }
00238
00239 for (i = 0; i < tag->tag_excludes.size (); i++)
00240 {
00241 Tag* ref = tag->tag_excludes[i];
00242
00243 if (ref == 0) continue;
00244
00245 if (ref->selected)
00246 {
00247 count++;
00248
00249 if ((winner == 0) ||
00250 (ref->priority > winner->priority))
00251 {
00252 winner = ref;
00253 winner_count = 1;
00254 }
00255 else if (ref->priority == winner->priority)
00256 {
00257 winner_count++;
00258 }
00259 }
00260 }
00261
00262 if (count > 1)
00263 {
00264 if (winner_count > 1)
00265 {
00266
00267
00268
00269 }
00270
00271
00272
00273
00274
00275
00276 if (tag != winner)
00277 {
00278 tag->unmark ();
00279 }
00280
00281 for (i = 0; i < tag->tag_excludes.size (); i++)
00282 {
00283 Tag* ref = tag->tag_excludes[i];
00284
00285 if (ref == 0) continue;
00286 if (ref == winner) continue;
00287
00288 ref->unmark ();
00289 }
00290 }
00291 }
00292 }
00293
00294
00295 Tag* Tag::find (const cmt_string& name)
00296 {
00297 static TagPtrVector& Tags = tags ();
00298
00299 int tag_index;
00300 Tag* tag;
00301
00302 if (Tags.size () == 0) return (0);
00303
00304 for (tag_index = 0; tag_index < Tags.size (); tag_index++)
00305 {
00306 tag = Tags[tag_index];
00307
00308 if ((tag != 0) && (tag->name == name))
00309 {
00310 return (tag);
00311 }
00312 }
00313
00314 return (0);
00315 }
00316
00317
00318 Tag* Tag::add (const cmt_string& name,
00319 int priority,
00320 const cmt_string& context,
00321 Use* use)
00322 {
00323 static TagPtrVector& Tags = tags ();
00324 static TagVector& AllTags = all_tags ();
00325
00326 Tag* tag;
00327
00328 if (name == "") return (0);
00329
00330 tag = find (name);
00331 if (tag != 0)
00332 {
00333 if (priority > tag->priority)
00334 {
00335 tag->priority = priority;
00336
00337
00338
00339
00340
00341
00342
00343 }
00344 else
00345 {
00346
00347
00348
00349
00350
00351
00352 }
00353
00354 return (tag);
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364 Tag& tag_object = AllTags.add ();
00365 tag = &tag_object;
00366 Tags.push_back (tag);
00367
00368 tag->clear ();
00369 tag->name = name;
00370
00371 tag->selected = false;
00372 tag->priority = priority;
00373 tag->def_use = use;
00374 tag->context = context;
00375
00376 return (tag);
00377 }
00378
00379
00380 int Tag::tag_number ()
00381 {
00382 static TagPtrVector& Tags = tags ();
00383
00384 return (Tags.size ());
00385 }
00386
00387
00388 Tag* Tag::tag (int index)
00389 {
00390 static TagPtrVector& Tags = tags ();
00391
00392 return (Tags[index]);
00393 }
00394
00395
00396 void Tag::clear_all ()
00397 {
00398 static TagPtrVector& Tags = tags ();
00399 static TagVector& AllTags = all_tags ();
00400
00401 int tag_index;
00402
00403 for (tag_index = 0; tag_index < AllTags.size (); tag_index++)
00404 {
00405 Tag& tag = AllTags[tag_index];
00406 tag.clear ();
00407 }
00408
00409 Tags.clear ();
00410 AllTags.clear ();
00411 }
00412
00413
00414 Tag::TagVector& Tag::all_tags ()
00415 {
00416 static Database& db = Database::instance ();
00417 static TagVector& AllTags = db.all_tags ();
00418
00419 return (AllTags);
00420 }
00421
00422
00423 Tag::TagPtrVector& Tag::tags ()
00424 {
00425 static Database& db = Database::instance ();
00426 static TagPtrVector& Tags = db.tags ();
00427
00428 return (Tags);
00429 }
00430
00431
00432 Tag* Tag::get_default ()
00433 {
00434 static Tag* default_tag = 0;
00435
00436 if (default_tag == 0)
00437 {
00438 default_tag = add ("Default", PriorityDefault, "Default", 0);
00439 default_tag->selected = true;
00440 }
00441
00442 return (default_tag);
00443 }
00444
00445
00446 Tag::Tag ()
00447 {
00448 }
00449
00450
00451 Tag::~Tag ()
00452 {
00453 }
00454
00455
00456 void Tag::clear ()
00457 {
00458 name = "";
00459 tag_refs.clear ();
00460 tag_excludes.clear ();
00461 priority = PriorityUserTag;
00462 selected = false;
00463 def_use = 0;
00464 set_use = 0;
00465 context = "";
00466 }
00467
00468
00469 void Tag::add_tag_ref (Tag* ref)
00470 {
00471 if (ref == 0) return;
00472
00473 if (tag_refs.size () > 0)
00474 {
00475 int number;
00476
00477 for (number = 0; number < tag_refs.size (); number++)
00478 {
00479 Tag* t = tag_refs[number];
00480 if (t == ref) return;
00481 }
00482 }
00483
00484 tag_refs.push_back (ref);
00485 }
00486
00487
00488 void Tag::add_tag_exclude (Tag* ref)
00489 {
00490 if (ref == 0) return;
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 if (tag_excludes.size () > 0)
00519 {
00520 int number;
00521
00522 for (number = 0; number < tag_excludes.size (); number++)
00523 {
00524 Tag* t = tag_excludes[number];
00525 if (t == ref) return;
00526 }
00527 }
00528
00529 tag_excludes.push_back (ref);
00530 }
00531
00532
00533 void Tag::show (bool quiet) const
00534 {
00535 static const cmt_string priority_text[] = {
00536 "Lowest",
00537 "Default",
00538 "Uname",
00539 "Config",
00540 "UserTag",
00541 "PrimaryUserTag",
00542 "Tag"
00543 };
00544
00545 if (selected)
00546 {
00547 cout << name;
00548
00549 if (!quiet)
00550 {
00551
00552
00553 if ((context == "use") || (def_use != 0))
00554 {
00555 if (def_use != 0)
00556 {
00557 cout << " (from ";
00558 if (context != "use") cout << context;
00559 cout << "package " << def_use->package << ")";
00560 }
00561 }
00562 else
00563 {
00564 cout << " (from " << context << ")";
00565 }
00566
00567
00568 if (tag_refs.size () > 0)
00569 {
00570 int number;
00571
00572 if (set_use != 0)
00573 {
00574 cout << " package " << set_use->package;
00575 }
00576
00577 cout << " implies [";
00578
00579 for (number = 0; number < tag_refs.size (); number++)
00580 {
00581 Tag* ref = tag_refs[number];
00582 if (number > 0) cout << " ";
00583 cout << ref->name;
00584 }
00585
00586 cout << "]";
00587 }
00588
00589 if (tag_excludes.size () > 0)
00590 {
00591 int number;
00592
00593 if (set_use != 0)
00594 {
00595 cout << " package " << set_use->package;
00596 }
00597
00598 cout << " excludes [";
00599
00600 for (number = 0; number < tag_excludes.size (); number++)
00601 {
00602 Tag* ref = tag_excludes[number];
00603 if (number > 0) cout << " ";
00604 cout << ref->name;
00605 }
00606
00607 cout << "]";
00608 }
00609 }
00610 cout << endl;
00611 }
00612 }
00613
00614
00615 bool Tag::is_selected () const
00616 {
00617 return (selected);
00618 }
00619
00620
00621