source: CMT/v1r16p20040901/src/cmt_symbol.cxx@ 1

Last change on this file since 1 was 1, checked in by arnault, 21 years ago

Import all tags

File size: 71.3 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// See the complete license in cmt_license.txt "http://www.cecill.info".
5//-----------------------------------------------------------
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <ctype.h>
11
12#include "cmt_use.h"
13#include "cmt_symbol.h"
14#include "cmt_system.h"
15#include "cmt_database.h"
16
17//-------------------------------------------------------------
18class SetBuilder : public ValueBuilder
19{
20public:
21 const cmt_string build (const Symbol& symbol,
22 const cmt_string& tag_name = "");
23 const cmt_string clean (const Symbol& symbol,
24 const cmt_string& tag_name = "")
25 {
26 static const cmt_string empty = "";
27 return (empty);
28 }
29};
30//-------------------------------------------------------------
31
32//-------------------------------------------------------------
33class PathBuilder : public ValueBuilder
34{
35public:
36 const cmt_string build (const Symbol& symbol,
37 const cmt_string& tag_name = "");
38 const cmt_string clean (const Symbol& symbol,
39 const cmt_string& tag_name = "");
40};
41//-------------------------------------------------------------
42
43//-------------------------------------------------------------
44class MacroBuilder : public ValueBuilder
45{
46public:
47 const cmt_string build (const Symbol& symbol,
48 const cmt_string& tag_name = "");
49 const cmt_string clean (const Symbol& symbol,
50 const cmt_string& tag_name = "")
51 {
52 static const cmt_string empty = "";
53 return (empty);
54 }
55};
56//-------------------------------------------------------------
57
58//-------------------------------------------------------------
59class ScriptBuilder : public ValueBuilder
60{
61public:
62 const cmt_string build (const Symbol& symbol,
63 const cmt_string& tag_name = "");
64 const cmt_string clean (const Symbol& symbol,
65 const cmt_string& tag_name = "")
66 {
67 static const cmt_string empty = "";
68 return (empty);
69 }
70};
71//-------------------------------------------------------------
72
73//-------------------------------------------------------------
74class ActionBuilder : public ValueBuilder
75{
76public:
77 const cmt_string build (const Symbol& symbol,
78 const cmt_string& tag_name = "");
79 const cmt_string clean (const Symbol& symbol,
80 const cmt_string& tag_name = "")
81 {
82 static const cmt_string empty = "";
83 return (empty);
84 }
85};
86//-------------------------------------------------------------
87
88//-------------------------------------------------------------
89class symbol_marker
90{
91public:
92 symbol_marker ()
93 {
94 ptr = cmt_string::npos;
95 pattern = 0;
96 intro = 0;
97 }
98
99 symbol_marker (int a_ptr, char a_pattern, int a_intro)
100 {
101 ptr = a_ptr;
102 pattern = a_pattern;
103 intro = a_intro;
104 }
105
106 symbol_marker (const symbol_marker& other)
107 {
108 ptr = other.ptr;
109 pattern = other.pattern;
110 intro = other.intro;
111 }
112
113 void set (int a_ptr, char a_pattern, int a_intro)
114 {
115 ptr = a_ptr;
116 pattern = a_pattern;
117 intro = a_intro;
118 }
119
120 static symbol_marker& get_lowest (symbol_marker markers[], int count)
121 {
122 static symbol_marker result;
123 int real_count = 0;
124 int i;
125
126 // Check that at least one marker has result
127
128 for (i = 0; i < count; i++)
129 {
130 if (markers[i].ptr != cmt_string::npos) real_count++;
131 }
132
133 if (real_count == 0) return (result);
134
135 // since we've passed the previous test,
136 // at least one entry is not npos.
137 // Now discards other npos by moving them to the end
138
139 for (i = 0; i < count;)
140 {
141 if (markers[i].ptr == cmt_string::npos)
142 {
143 markers[i] = markers[count-1];
144 count--;
145 if (count == 0) break;
146 }
147 else
148 {
149 i++;
150 }
151 }
152
153 if (count == 0) return (result);
154
155 // now all entries in [0, count-1] are not npos
156 // let's sort the lowest one in [0]
157
158 for (i = 1; i < count;)
159 {
160 if (markers[0].ptr > markers[i].ptr)
161 {
162 symbol_marker temp = markers[0];
163 markers[0] = markers[i];
164 markers[i] = temp;
165 i = 1;
166 }
167 else
168 {
169 i++;
170 }
171 }
172
173 return (markers[0]);
174 }
175
176 int ptr;
177 char pattern;
178 int intro;
179};
180//-------------------------------------------------------------
181
182/**
183
184 Attempt to substitute all occurrences of
185
186 ${<symbol_name>}
187 $(<symbol_name>)
188 %<symbol_name>% [on Windows only]
189
190 by the specified value in the given text.
191
192 This is for one symbol only
193
194 */
195static void resolve_value (cmt_string& text,
196 const cmt_string& symbol_name,
197 const cmt_string& value)
198{
199 static cmt_string pattern;
200
201 pattern = "${";
202 pattern += symbol_name;
203 pattern += "}";
204
205 text.replace_all (pattern, value);
206
207 pattern = "$(";
208 pattern += symbol_name;
209 pattern += ")";
210
211 text.replace_all (pattern, value);
212
213#ifdef WIN32
214 pattern = "%";
215 pattern += symbol_name;
216 pattern += "%";
217
218 text.replace_all (pattern, value);
219#endif
220}
221
222/**
223
224 Attempt to substitute into the specified text all occurrences of
225
226 ${xxx}
227 $(xxx)
228 `xxx`
229 %xxx% [on Windows only]
230
231 by the appropriate value:
232
233 for `xxx` :
234
235 xxx is considered as a shell command. Value is the result of its execution
236
237 for other patterns:
238
239 if xxx is a symbol name, its value is substituted to the pattern
240 otherwise, xxx is tried as an environment variable
241
242
243 ===> In all cases, the pattern is filtered away.
244
245
246 */
247static void resolve_value (cmt_string& text)
248{
249 //static cmt_regexp reg ("[$%`]");
250
251 //if (!reg.match (text)) return;
252
253 cmt_string pattern;
254 cmt_string symbol_name;
255 char end_pattern;
256
257 int start = 0;
258
259 for (;;)
260 {
261 int begin;
262 int end;
263
264 symbol_marker markers[4];
265 int num = 0;
266
267 markers[num].set (text.find (start, "$("), ')', 2); num++;
268 markers[num].set (text.find (start, "${"), '}', 2); num++;
269 markers[num].set (text.find (start, "`"), '`', 1); num++;
270
271#ifdef WIN32
272 markers[num].set (text.find (start, "%"), '%', 1); num++;
273#endif
274
275 // Find the first matching pattern
276
277 symbol_marker& marker = symbol_marker::get_lowest (markers, num);
278
279 begin = marker.ptr;
280
281 if (begin == cmt_string::npos) break;
282
283 end_pattern = marker.pattern;
284 start = begin + marker.intro;
285
286 end = text.find (start, end_pattern);
287 if (end == cmt_string::npos)
288 {
289 // The pattern is a fake one (no ending!)
290 start++;
291 continue;
292 }
293
294 // This should never happen...
295 if (end < begin) break;
296
297 // Extract the complete pattern
298 text.substr (begin, end - begin + 1, pattern);
299
300 // Then only the symbol name
301 text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
302
303 if (text[begin] == '`')
304 {
305 cmt_string command = symbol_name;
306 resolve_value (command);
307
308 // The value is a shell command that first needs
309 // to be applied. The output of the command is then substituted
310
311 cmt_string result;
312
313 Symbol::all_set ();
314 CmtSystem::execute (command, result);
315
316 int pos;
317 pos = result.find ('\n');
318 if (pos != cmt_string::npos) result.erase (pos);
319 pos = result.find ('\r');
320 if (pos != cmt_string::npos) result.erase (pos);
321
322 if (Cmt::get_debug ())
323 {
324 cout << " Executing [" << command << "] to expand a symbol value =>["
325 << result << "]" << endl;
326 }
327
328 text.replace_all (pattern, result);
329
330 // The substitution will restart from the same place
331 // allowing for recursive replacements
332 start = begin;
333 }
334 else
335 {
336 Symbol* symbol = Symbol::find (symbol_name);
337 if (symbol != 0)
338 {
339 // Symbol found
340 cmt_string value = symbol->resolve_macro_value ();
341 text.replace_all (pattern, value);
342
343 // The substitution will restart from the same place
344 // allowing for recursive replacements
345 start = begin;
346 }
347 else
348 {
349 // Symbol not found. Look for env. variable
350 cmt_string value = CmtSystem::getenv (symbol_name);
351
352 // When the env. variable is not defined, the replacement is empty
353 // thus all $(xxx) ${xxx} %xxx% patterns are always filtered away.
354 text.replace_all (pattern, value);
355
356 // The substitution will restart from the same place
357 // allowing for recursive replacements
358 start = begin;
359 }
360 }
361 }
362}
363
364/**
365
366 Attempt to substitute all occurrences of
367
368 ${xxx}
369 $(xxx)
370 `xxx`
371 %xxx% [on Windows only]
372
373 by the appropriate value:
374
375 for `xxx` :
376
377 xxx is considered as a shell command. Value is the result of its execution
378
379 for other patterns:
380
381 if xxx is a macro name, its value is substituted to the pattern
382
383 if xxx is a set or a path, it is kept in place (after fixing the pattern
384 according to the OS style)
385
386 otherwise it is simply kept in place
387
388 */
389static void resolve_value_for_macros (cmt_string& text)
390{
391 cmt_string pattern;
392 cmt_string symbol_name;
393 char end_pattern;
394
395 int start = 0;
396
397 for (;;)
398 {
399 //
400 // Try and substitute all ${xxx} $(xxx) or %xxx% patterns
401 // using symbol values, only when the symbol is a macro.
402 //
403
404 int begin;
405 int end;
406
407 symbol_marker markers[4];
408 int num = 0;
409
410 markers[num].set (text.find (start, "$("), ')', 2); num++;
411 markers[num].set (text.find (start, "${"), '}', 2); num++;
412
413#ifdef WIN32
414 markers[num].set (text.find (start, "%"), '%', 1); num++;
415#endif
416
417 markers[num].set (text.find (start, "`"), '`', 1); num++;
418
419 // Find the first of three patterns
420
421 symbol_marker& marker = symbol_marker::get_lowest (markers, num);
422
423 begin = marker.ptr;
424
425 if (begin == cmt_string::npos) break;
426
427 end_pattern = marker.pattern;
428 start = begin + marker.intro;
429
430 end = text.find (start, end_pattern);
431 if (end == cmt_string::npos)
432 {
433 // The pattern is a fake one (no ending!)
434 start++;
435 continue;
436 }
437
438 // This should never happen...
439 if (end < begin) break;
440
441 // Extract the complete pattern
442 text.substr (begin, end - begin + 1, pattern);
443
444 // Then only the macro name
445 text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
446
447 if (text[begin] == '`')
448 {
449 cmt_string command = symbol_name;
450 resolve_value (command);
451
452 // The macro value is a shell command that first needs
453 // to be applied. The output of the command is substituted
454
455 cmt_string result;
456
457 Symbol::all_set ();
458 CmtSystem::execute (command, result);
459
460 int pos;
461 pos = result.find ('\n');
462 if (pos != cmt_string::npos) result.erase (pos);
463 pos = result.find ('\r');
464 if (pos != cmt_string::npos) result.erase (pos);
465
466 if (Cmt::get_debug ())
467 {
468 cout << " Executing [" << command << "] to expand a macro value =>["
469 << result << "]" << endl;
470 }
471
472 text.replace_all (pattern, result);
473
474 // The substitution will restart from the same place
475 // allowing for recursive replacements
476 start = begin;
477 }
478 else
479 {
480 Symbol* macro = Symbol::find (symbol_name);
481 if ((macro != 0) &&
482 (macro->type == Symbol::SymbolMacro))
483 {
484 // Macro found
485 cmt_string value = macro->resolve_macro_value ();
486 text.replace_all (pattern, value);
487
488 // The substitution will restart from the same place
489 // allowing for recursive replacements
490 start = begin;
491 }
492 else if ((macro == 0) ||
493 ((macro->type == Symbol::SymbolSet) || (macro->type == Symbol::SymbolPath)))
494 {
495 // Set found
496 // ensure that the delimiters will match the OS dependent
497 // delimiters.
498
499 cmt_string pattern_close = marker.pattern;
500
501 if (pattern_close != CmtSystem::ev_close ())
502 {
503 cmt_string new_pattern;
504
505 new_pattern = CmtSystem::ev_open ();
506 new_pattern += symbol_name;
507 new_pattern += CmtSystem::ev_close ();
508
509 text.replace (pattern, new_pattern);
510 }
511
512 start = end + 1;
513 }
514 else
515 {
516 start = end + 1;
517 }
518 }
519 }
520}
521
522/**
523
524 This function suppress all OS delimiters ie ${ } or % % and replaces them
525 by the pure macro delimiters $( )
526
527 `xxx` pattern is replaced by the result of the execution of the command
528
529 */
530static void suppress_OS_delimiters (cmt_string& text)
531{
532 cmt_string pattern;
533 cmt_string symbol_name;
534 char end_pattern;
535
536 int start = 0;
537
538 for (;;)
539 {
540 int begin;
541 int end;
542
543 symbol_marker markers[3];
544 int num = 0;
545
546 markers[num].set (text.find (start, "${"), '}', 2); num++;
547 markers[num].set (text.find (start, "`"), '`', 1); num++;
548
549#ifdef WIN32
550 markers[num].set (text.find (start, "%"), '%', 1); num++;
551#endif
552
553 // Find the first of three patterns
554
555 symbol_marker& marker = symbol_marker::get_lowest (markers, num);
556
557 begin = marker.ptr;
558
559 if (begin == cmt_string::npos) break;
560
561 end_pattern = marker.pattern;
562 start = begin + marker.intro;
563
564 end = text.find (start, end_pattern);
565 if (end == cmt_string::npos)
566 {
567 // The pattern is a fake one (no ending!)
568 start++;
569 continue;
570 }
571
572 // This should never happen...
573 if (end < begin) break;
574
575 // Extract the complete pattern
576 text.substr (begin, end - begin + 1, pattern);
577
578 // Then only the macro name
579 text.substr (begin + marker.intro, end - begin - marker.intro, symbol_name);
580
581 if (text[begin] == '`')
582 {
583 cmt_string command = symbol_name;
584 resolve_value (command);
585
586 // The macro value is a shell command that first needs
587 // to be applied. The output of the command is substituted
588
589 cmt_string result;
590
591 Symbol::all_set ();
592 CmtSystem::execute (command, result);
593
594 int pos;
595 pos = result.find ('\n');
596 if (pos != cmt_string::npos) result.erase (pos);
597 pos = result.find ('\r');
598 if (pos != cmt_string::npos) result.erase (pos);
599
600 if (Cmt::get_debug ())
601 {
602 cout << " Executing [" << command << "] to expand a macro value =>["
603 << result << "]" << endl;
604 }
605
606 text.replace_all (pattern, result);
607
608 // The substitution will restart from the same place
609 // allowing for recursive replacements
610 start = begin;
611 }
612 else
613 {
614 cmt_string new_pattern;
615
616 new_pattern = "$(";
617 new_pattern += symbol_name;
618 new_pattern += ")";
619
620 text.replace (pattern, new_pattern);
621
622 start = begin;
623 }
624 }
625}
626
627//-------------------------------------------------------------
628/* */
629/* Operations on SymbolValues */
630/* */
631//-------------------------------------------------------------
632
633//-------------------------------------------------------------
634SymbolValue::SymbolValue ()
635{
636 tag = 0;
637}
638
639//-------------------------------------------------------------
640SymbolValue::~SymbolValue ()
641{
642 tag = 0;
643}
644
645//-------------------------------------------------------------
646/* */
647/* Operations on Symbols */
648/* */
649//-------------------------------------------------------------
650
651//-------------------------------------------------------------
652Symbol* Symbol::create (const cmt_string& name,
653 CommandType command,
654 Use* use)
655{
656 static SetBuilder Set;
657 static PathBuilder Path;
658 static MacroBuilder Macro;
659 static ScriptBuilder Script;
660 static ActionBuilder Action;
661
662 static SymbolVector& Symbols = symbols ();
663 static SymbolMap& SymbolMap = symbol_map ();
664
665 SymbolType type = SymbolUndefined;
666
667 switch (command)
668 {
669 case CommandSet:
670 case CommandSetAppend:
671 case CommandSetPrepend:
672 case CommandSetRemove:
673 case CommandSetRemoveRegexp:
674 type = SymbolSet;
675 break;
676 case CommandPath:
677 case CommandPathAppend:
678 case CommandPathPrepend:
679 case CommandPathRemove:
680 case CommandPathRemoveRegexp:
681 type = SymbolPath;
682 break;
683 case CommandMacro:
684 case CommandMacroAppend:
685 case CommandMacroPrepend:
686 case CommandMacroRemove:
687 case CommandMacroRemoveRegexp:
688 case CommandMacroRemoveAll:
689 case CommandMacroRemoveAllRegexp:
690 type = SymbolMacro;
691 break;
692 case CommandAction:
693 type = SymbolAction;
694 break;
695 case CommandAlias:
696 type = SymbolAlias;
697 break;
698 case CommandSetupScript:
699 type = SymbolSetupScript;
700 break;
701 case CommandCleanupScript:
702 type = SymbolCleanupScript;
703 break;
704 }
705
706 {
707 Symbol* symbol;
708
709 symbol = find (name);
710 if (symbol != 0)
711 {
712 if (symbol->type != type)
713 {
714 ActionType action = Cmt::get_action ();
715
716 if ((!Cmt::get_quiet ()) &&
717 (action != action_build_tag_makefile))
718 {
719 cmt_string s1;
720 cmt_string s2;
721
722 switch (symbol->type)
723 {
724 case SymbolSet:
725 s1 = "set";
726 break;
727 case SymbolPath:
728 s1 = "path";
729 break;
730 case SymbolMacro:
731 s1 = "macro";
732 break;
733 case SymbolSetupScript:
734 s1 = "setup_script";
735 break;
736 case SymbolCleanupScript:
737 s1 = "cleanup_script";
738 break;
739 case SymbolAction:
740 s1 = "action";
741 break;
742 case SymbolAlias:
743 s1 = "alias";
744 break;
745 }
746
747 switch (type)
748 {
749 case SymbolSet:
750 s2 = "set";
751 break;
752 case SymbolPath:
753 s2 = "path";
754 break;
755 case SymbolMacro:
756 s2 = "macro";
757 break;
758 case SymbolSetupScript:
759 s2 = "setup_script";
760 break;
761 case SymbolCleanupScript:
762 s2 = "cleanup_script";
763 break;
764 case SymbolAction:
765 s2 = "action";
766 break;
767 case SymbolAlias:
768 s2 = "alias";
769 break;
770 }
771
772 cerr << "#CMT> Warning: Symbol " << name
773 << " inconsistently redeclared from " << s1 << " to " << s2;
774 if (use != 0) cerr << " in package " << use->get_package_name ();
775 cerr << endl;
776 }
777 }
778
779 return (symbol);
780 }
781 }
782
783 Symbol& symbol = Symbols.add ();
784 SymbolMap.add (name, symbol);
785
786 symbol.name = name;
787 symbol.scope = use->get_current_scope ();
788 symbol.type = type;
789
790 symbol.value_lists.clear ();
791
792 switch (type)
793 {
794 case SymbolSet:
795 symbol.builder = &Set;
796 break;
797 case SymbolPath:
798 symbol.builder = &Path;
799 break;
800 case SymbolAlias:
801 symbol.builder = &Set;
802 break;
803 case SymbolMacro:
804 symbol.builder = &Macro;
805 break;
806 case SymbolSetupScript:
807 case SymbolCleanupScript:
808 symbol.builder = &Script;
809 break;
810 case SymbolAction:
811 symbol.builder = &Action;
812 break;
813 }
814
815 symbol.selected_value = -1;
816
817 return (&symbol);
818}
819
820//-------------------------------------------------------------
821Symbol* Symbol::find (const cmt_string& name)
822{
823 static SymbolMap& SymbolMap = symbol_map ();
824
825 Symbol* result = 0;
826
827 result = SymbolMap.find (name);
828
829 return (result);
830}
831
832//-------------------------------------------------------------
833int Symbol::symbol_number ()
834{
835 static SymbolVector& Symbols = symbols ();
836
837 return (Symbols.size ());
838}
839
840//-------------------------------------------------------------
841Symbol::SymbolVector& Symbol::symbols ()
842{
843 static Database& db = Database::instance ();
844 static SymbolVector& Symbols = db.symbols ();
845
846 return (Symbols);
847}
848
849//-------------------------------------------------------------
850Symbol::SymbolMap& Symbol::symbol_map ()
851{
852 static Database& db = Database::instance ();
853 static SymbolMap& SymbolMap = db.symbol_map ();
854
855 return (SymbolMap);
856}
857
858//-------------------------------------------------------------
859Symbol& Symbol::symbol (int index)
860{
861 static SymbolVector& Symbols = symbols ();
862
863 return (Symbols[index]);
864}
865
866//-------------------------------------------------------------
867void Symbol::action (const CmtSystem::cmt_string_vector& words,
868 CommandType command_type,
869 Use* use)
870{
871 int number;
872 Symbol* symbol;
873 Tag* tag;
874
875 if (words.size () < 1) return;
876 cmt_string name = words[1];
877
878 if ((command_type == CommandSetupScript) ||
879 (command_type == CommandCleanupScript))
880 {
881 cmt_string full_name;
882
883 Symbol::expand (name);
884
885 if (name != "")
886 {
887 if (CmtSystem::absolute_path (name))
888 {
889 full_name = name;
890 }
891 else
892 {
893#ifdef WIN32
894 full_name = "%";
895#else
896 full_name = "${";
897#endif
898 full_name += use->prefix;
899 full_name += "ROOT";
900#ifdef WIN32
901 full_name += "%";
902#else
903 full_name += "}";
904#endif
905 full_name += CmtSystem::file_separator ();
906 if (use->style == cmt_style) full_name += "cmt";
907 else if (use->style == no_version_style) full_name += "cmt";
908 else full_name += "mgr";
909 full_name += CmtSystem::file_separator ();
910 full_name += name;
911 }
912
913 symbol = create (full_name, command_type, use);
914 symbol->add_value_to_list (command_type, use,
915 Tag::get_default (), full_name);
916 }
917 }
918 else
919 {
920 if (words.size () < 2) return;
921 const cmt_string& default_value = words[2];
922
923 if (Cmt::get_debug ())
924 {
925 cout << "Symbol::action> name:" << name
926 << " access:" << Cmt::get_current_access ()
927 << " scope:" << use->get_current_scope () << endl;
928 }
929
930 if (Cmt::get_current_access () == UserMode)
931 {
932 if (name == "constituents") return;
933 if (name == "constituentscclean") return;
934
935 if (use->get_current_scope () == ScopePrivate) return;
936 }
937
938 symbol = create (name, command_type, use);
939
940 /*
941 Parse the default value.
942 */
943
944 symbol->add_value_to_list (command_type, use,
945 Tag::get_default (), default_value);
946
947 /*
948 Then parse all specific values
949
950 <tag> <value>
951 ...
952 */
953
954 number = 3;
955 while (number < (words.size () - 1))
956 {
957 cmt_string tag_name = words[number];
958 const cmt_string& value = words[number + 1];
959
960 expand (tag_name);
961
962 if (Cmt::get_debug ())
963 {
964 cout << "Symbol::action> tag_name=" << tag_name << endl;
965 }
966
967 tag = Tag::find (tag_name);
968 if (tag == 0)
969 {
970 tag = Tag::add (tag_name, PriorityUserTag, "use", use);
971 }
972
973 symbol->add_value_to_list (command_type, use, tag, value);
974
975 number += 2;
976 }
977
978 if (name == "CMTPATH")
979 {
980 Cmt::configure_cmt_path (use);
981 }
982 else if (name == "CMTSITE")
983 {
984 Cmt::configure_site_tag (use);
985 }
986 else if (name == "CMTCONFIG")
987 {
988 //cerr << "redefining CMTCONFIG" << endl;
989 Cmt::configure_tags (use);
990 }
991 else if (name == "CMTHOME")
992 {
993 Cmt::configure_home (use);
994 }
995 else if (name == "CMTUSERCONTEXT")
996 {
997 Cmt::configure_user_context (use);
998 }
999 else if (name.find ("_native_version") != cmt_string::npos)
1000 {
1001 cmt_string n = use->get_package_name ();
1002 n += "_native_version";
1003
1004 if (name == n)
1005 {
1006 use->set_native_version (true);
1007 }
1008 }
1009 }
1010}
1011
1012//-------------------------------------------------------------
1013int Symbol::is_selected (const cmt_string& name)
1014{
1015 Symbol* symbol;
1016 int number;
1017 int value_number;
1018
1019 symbol = find (name);
1020 if (symbol == 0) return (0);
1021
1022 if (symbol->value_lists.size () == 0) return (0);
1023
1024 for (number = 0;
1025 number < symbol->value_lists.size ();
1026 number++)
1027 {
1028 const SymbolValueList& value_list = symbol->value_lists[number];
1029
1030 if (value_list.discarded) continue;
1031
1032 if ((value_list.command_type == CommandMacro) ||
1033 (value_list.command_type == CommandSet) ||
1034 (value_list.command_type == CommandSetAppend) ||
1035 (value_list.command_type == CommandSetPrepend) ||
1036 (value_list.command_type == CommandSetRemove) ||
1037 (value_list.command_type == CommandSetRemoveRegexp) ||
1038 (value_list.command_type == CommandAlias) ||
1039 (value_list.command_type == CommandAction))
1040 {
1041 for (value_number = 0;
1042 value_number < value_list.values.size ();
1043 value_number++)
1044 {
1045 Tag* tag;
1046
1047 SymbolValue& value = value_list.values[value_number];
1048
1049 tag = value.tag;
1050 if ((tag == 0) ||
1051 (tag == Tag::get_default ()) ||
1052 (tag->is_selected () != 0))
1053 {
1054 return (1);
1055 }
1056 }
1057 }
1058 }
1059
1060 return (0);
1061}
1062
1063//-------------------------------------------------------------
1064Symbol::Symbol ()
1065{
1066 name = "";
1067}
1068
1069//-------------------------------------------------------------
1070Symbol::~Symbol ()
1071{
1072}
1073
1074/**
1075 * Characterizes if a value is provided as the reference to itself.
1076 */
1077bool Symbol::value_is_reflexive (const cmt_string& text) const
1078{
1079 bool result = false;
1080 int text_length = text.size ();
1081
1082 if (text_length == (name.size () + 3))
1083 {
1084 static cmt_string temp;
1085
1086 if (text[0] == '$')
1087 {
1088 if (text[1] == '(')
1089 {
1090 temp = "$(";
1091 temp += name;
1092 temp += ")";
1093
1094 if (text == temp)
1095 {
1096 result = true;
1097 }
1098 }
1099 else if (text[1] == '{')
1100 {
1101 temp = "${";
1102 temp += name;
1103 temp += "}";
1104
1105 if (text == temp)
1106 {
1107 result = true;
1108 }
1109 }
1110 }
1111 }
1112 else if (text_length == (name.size () + 2))
1113 {
1114 static cmt_string temp;
1115
1116 temp = "%";
1117 temp += name;
1118 temp += "%";
1119
1120 if (text == temp)
1121 {
1122 result = true;
1123 }
1124 }
1125
1126 return (result);
1127}
1128
1129//-------------------------------------------------------------
1130void Symbol::add_value_to_list (CommandType command_type,
1131 Use* use,
1132 Tag* tag,
1133 const cmt_string& text)
1134{
1135 SymbolValueList* value_list = 0;
1136 bool is_reflexive = false;
1137
1138 //
1139 // First pickup the most recent value_list
1140 //
1141 if (value_lists.size () > 0) value_list = &(value_lists.back ());
1142
1143 //
1144 // Create a new value list is we switch to another use or
1145 // if we switch to a new command_type (eg. switching from
1146 // macro to macro_append).
1147 //
1148 if ((value_list == 0) ||
1149 (use != value_list->use) ||
1150 (command_type != value_list->command_type) ||
1151 (tag == Tag::get_default ()))
1152 {
1153 value_list = &(value_lists.add ());
1154 value_list->use = use;
1155 value_list->command_type = command_type;
1156 value_list->values.clear ();
1157 value_list->discarded = false;
1158 value_list->is_reflexive = false;
1159 }
1160
1161/*
1162 else
1163 {
1164 value_list = &(value_lists[value_lists.size () - 1]);
1165 }
1166*/
1167
1168 is_reflexive = value_list->is_reflexive;
1169
1170 //
1171 // If the command_type is command_macro or command_set,
1172 // this is considered as a full re-set of this symbol
1173 // In this case, we have to discard all previous values
1174 //
1175 // However, we'd like to exclude from this logic the cases where
1176 // the value is **exactly*
1177 //
1178 // $(<symbol>)
1179 // ${<symbol>}
1180 // %<symbol>%
1181 //
1182 // which would then mean that we do not reset the value but rather
1183 // override it.
1184 //
1185
1186 //
1187 // Inside this value_list, we add this new tag-value pair.
1188 //
1189
1190 if ((command_type == CommandMacro) ||
1191 (command_type == CommandSet) ||
1192 (command_type == CommandPath) ||
1193 (command_type == CommandAction))
1194 {
1195 //
1196 // Check whether we have to hide previous settings by this new definition
1197 // (of course this is only useful if there WERE previous settings)
1198 //
1199 if ((value_lists.size () >= 1) && (!is_reflexive))
1200 {
1201 if (value_is_reflexive (text))
1202 {
1203 value_list->is_reflexive = true;
1204 is_reflexive = true;
1205 }
1206 else
1207 {
1208 //cout << "...discarding old values for symbol " << name << " text=[" << text << "]" << endl;
1209
1210 for (int i = 0; i < (value_lists.size () - 1); i++)
1211 {
1212 SymbolValueList& vl = value_lists[i];
1213
1214 if ((vl.use != 0) &&
1215 (vl.use->discarded))
1216 {
1217 //vl.discarded = true;
1218 }
1219 }
1220 }
1221 }
1222 }
1223
1224 SymbolValue& value = value_list->values.add ();
1225
1226 value.tag = tag;
1227 value.text = text;
1228 value.selected = 0;
1229}
1230
1231/**
1232 Compute the current value of all environment variables and set them to the
1233 shell
1234 */
1235void Symbol::all_set ()
1236{
1237 static bool done = false;
1238
1239 if (Cmt::get_debug ())
1240 {
1241 cout << "Symbol::all_set> done" << done << endl;
1242 }
1243
1244 if (done) return;
1245
1246 done = true;
1247
1248 static SymbolVector& Symbols = symbols ();
1249
1250 static CmtSystem::cmt_string_vector envs;
1251
1252 envs.clear ();
1253
1254 int number;
1255
1256 if (Symbols.size () == 0)
1257 {
1258 //running = false;
1259 return;
1260 }
1261
1262 cmt_string value;
1263
1264 for (number = 0; number < Symbol::symbol_number (); number++)
1265 {
1266 Symbol& symbol = Symbol::symbol (number);
1267
1268 if (symbol.type != SymbolSet) continue;
1269
1270 value = symbol.build_macro_value ();
1271 if (value != "")
1272 {
1273 cmt_string& temp = envs.add ();
1274
1275 temp = symbol.name;
1276 temp += '=';
1277 temp += value;
1278 }
1279 }
1280
1281 for (number = 0; number < Symbol::symbol_number (); number++)
1282 {
1283 Symbol& symbol = Symbol::symbol (number);
1284
1285 if ((symbol.type != SymbolPath)) continue;
1286
1287 value = symbol.build_macro_value ();
1288 if (value != "")
1289 {
1290 cmt_string& temp = envs.add ();
1291
1292 temp = symbol.name;
1293 temp += '=';
1294 temp += value;
1295 }
1296 }
1297
1298 for (number = 0; number < envs.size (); number++)
1299 {
1300 cmt_string& env = envs[number];
1301 Symbol::expand (env);
1302
1303#ifdef WIN32
1304 env.replace_all ("/", "\\");
1305#endif
1306
1307 if (Cmt::get_debug ())
1308 {
1309 cout << "Symbol::all_set> " << env << endl;
1310 }
1311 CmtSystem::putenv (env);
1312 }
1313
1314 //running = false;
1315}
1316
1317//-------------------------------------------------------------
1318void Symbol::all_print (PrintMode mode)
1319{
1320 static SymbolVector& Symbols = symbols ();
1321
1322 int number;
1323
1324 if (Symbols.size () == 0) return;
1325
1326 for (number = 0; number < Symbol::symbol_number (); number++)
1327 {
1328 Symbol& symbol = Symbol::symbol (number);
1329
1330 if ((symbol.type == SymbolSet) ||
1331 (symbol.type == SymbolAlias) ||
1332 (symbol.type == SymbolSetupScript))
1333 {
1334 if (symbol.print (mode))
1335 {
1336 if (mode == Bat)
1337 {
1338 cout << endl;
1339 }
1340 else
1341 {
1342 //cout << "; ";
1343 cout << endl;
1344 }
1345 }
1346 }
1347 }
1348
1349 for (number = 0; number < Symbol::symbol_number (); number++)
1350 {
1351 Symbol& symbol = Symbol::symbol (number);
1352
1353 if ((symbol.type != SymbolPath)) continue;
1354
1355 if (symbol.print (mode))
1356 {
1357 if (mode == Bat)
1358 {
1359 cout << endl;
1360 }
1361 else
1362 {
1363 //cout << "; ";
1364 cout << endl;
1365 }
1366 }
1367 }
1368}
1369
1370//-------------------------------------------------------------
1371void Symbol::all_print_clean (PrintMode mode)
1372{
1373 static SymbolVector& Symbols = symbols ();
1374
1375 int number;
1376
1377 if (Symbols.size () == 0) return;
1378
1379 for (number = Symbols.size () - 1; number >= 0; number--)
1380 {
1381 Symbol& symbol = Symbols[number];
1382
1383 if ((symbol.type == SymbolSet) ||
1384 (symbol.type == SymbolAlias) ||
1385 (symbol.type == SymbolCleanupScript))
1386 {
1387 if (symbol.print_clean (mode))
1388 {
1389 cout << endl;
1390 }
1391 }
1392 }
1393
1394 for (number = Symbols.size () - 1; number >= 0; number--)
1395 {
1396 Symbol& symbol = Symbols[number];
1397
1398 if ((symbol.type != SymbolPath)) continue;
1399
1400 if (symbol.print_clean (mode))
1401 {
1402 cout << endl;
1403 }
1404 }
1405}
1406
1407//-------------------------------------------------------------
1408int Symbol::print_clean (PrintMode mode)
1409{
1410 int result = 0;
1411 static cmt_string temp;
1412
1413 if (name == "CMTCONFIG") return (0);
1414
1415 switch (type)
1416 {
1417 case SymbolSet :
1418 switch (mode)
1419 {
1420 case Csh :
1421 cout << "unsetenv " << name;
1422 result = 1;
1423 break;
1424 case Sh :
1425 cout << "unset " << name;
1426 result = 1;
1427 break;
1428 case Bat :
1429 cout << "set " << name << "=";
1430 result = 1;
1431 break;
1432 }
1433 break;
1434 case SymbolAlias :
1435 switch (mode)
1436 {
1437 case Csh :
1438 cout << "unalias " << name;
1439 result = 1;
1440 break;
1441 case Sh :
1442 cout << "unset " << name;
1443 result = 1;
1444 break;
1445 }
1446 break;
1447 case SymbolPath :
1448 temp = clean_macro_value ();
1449 switch (mode)
1450 {
1451 case Csh :
1452 if (temp == "")
1453 {
1454 cout << "unsetenv " << name;
1455 }
1456 else
1457 {
1458 cout << "setenv " << name << " " << temp;
1459 }
1460 result = 1;
1461 break;
1462 case Sh :
1463 cout << name << "=" << temp << "; export " << name;
1464 result = 1;
1465 break;
1466 case Bat :
1467 cout << "set " << name << "=" << temp;
1468 result = 1;
1469 break;
1470 }
1471 break;
1472 case SymbolCleanupScript :
1473 switch (mode)
1474 {
1475 case Csh :
1476 cout << "if ( -f " << name << ".csh ) then" << endl;
1477 cout << " source " << name << ".csh" << endl;
1478 cout << "endif" << endl;
1479 result = 1;
1480 break;
1481 case Sh :
1482 cout << "if test -f " << name << ".sh; then" << endl;
1483 cout << " . " << name << ".sh" << endl;
1484 cout << "fi" << endl;
1485 result = 1;
1486 break;
1487 case Bat :
1488 cout << "call " << name;
1489 result = 1;
1490 break;
1491 }
1492 break;
1493 }
1494
1495 return (result);
1496}
1497
1498//-------------------------------------------------------------
1499int Symbol::print (PrintMode mode)
1500{
1501 int result = 0;
1502 cmt_string temp;
1503
1504 temp = build_macro_value ();
1505
1506 bool empty = (temp.size () == 0) ? true : false;
1507
1508 switch (type)
1509 {
1510 case SymbolSet :
1511 case SymbolPath :
1512 switch (mode)
1513 {
1514 case Csh :
1515 if (empty) cout << "unsetenv " << name;
1516 else cout << "setenv " << name << " \"" << temp << "\"";
1517
1518 result = 1;
1519 break;
1520 case Sh :
1521 if (empty) cout << "unset " << name;
1522 else cout << name << "=\"" << temp << "\"; export " << name;
1523
1524 result = 1;
1525 break;
1526 case Bat :
1527 temp.replace_all ("/", "\\");
1528 cout << "set " << name << "=" << temp;
1529 result = 1;
1530 break;
1531 }
1532 break;
1533 case SymbolAlias :
1534 switch (mode)
1535 {
1536 case Csh :
1537 cout << "alias " << name <<
1538 " \"" << temp << "\"";
1539 result = 1;
1540 break;
1541 case Sh :
1542 cout << "alias " << name <<
1543 "=\"" << temp <<
1544 "\"; export " << name;
1545 result = 1;
1546 break;
1547 case Bat :
1548 cout << "set " << name <<
1549 "=" << temp;
1550 result = 1;
1551 break;
1552 }
1553 break;
1554 default :
1555 break;
1556 }
1557
1558 if (temp != "")
1559 {
1560 switch (type)
1561 {
1562 case SymbolSetupScript :
1563 switch (mode)
1564 {
1565 case Csh :
1566 cout << "if ( -f " << name << ".csh ) then" << endl;
1567 cout << " source " << name << ".csh" << endl;
1568 cout << "endif" << endl;
1569 result = 1;
1570 break;
1571 case Sh :
1572 cout << "if test -f " << name << ".sh; then" << endl;
1573 cout << " . " << name << ".sh" << endl;
1574 cout << "fi" << endl;
1575 result = 1;
1576 break;
1577 case Bat :
1578 cout << "call " << name;
1579 result = 1;
1580 break;
1581 }
1582 break;
1583 default:
1584 break;
1585 }
1586 }
1587
1588 return (result);
1589}
1590
1591//-------------------------------------------------------------
1592cmt_string Symbol::build_macro_value () const
1593{
1594 cmt_string temp;
1595
1596 temp = builder->build (*this);
1597
1598 return (temp);
1599}
1600
1601//-------------------------------------------------------------
1602cmt_string Symbol::clean_macro_value () const
1603{
1604 cmt_string temp;
1605
1606 temp = builder->clean (*this);
1607
1608 return (temp);
1609}
1610
1611/**
1612
1613 Attempt to substitute into the symbol value all occurrences of
1614
1615 ${xxx}
1616 $(xxx)
1617 `xxx`
1618 %xxx% [on Windows only]
1619
1620 by the appropriate value:
1621
1622 for `xxx` :
1623
1624 xxx is considered as a shell command. Value is the result of its execution
1625
1626 for other patterns:
1627
1628 if xxx is a symbol name, its value is substituted to the pattern
1629 otherwise, xxx is tried as an environment variable
1630
1631
1632 ===> In all cases, the pattern is filtered away.
1633
1634 */
1635cmt_string Symbol::resolve_macro_value (const cmt_string& tag_name)
1636{
1637 cmt_string temp = builder->build (*this, tag_name);
1638
1639 resolve_value (temp);
1640
1641 return (temp);
1642}
1643
1644//-------------------------------------------------------------
1645void Symbol::show_macro (PrintMode mode)
1646{
1647 if (Cmt::get_debug ())
1648 {
1649 cout << "Symbol::show_macro> " << name << endl;
1650 }
1651
1652 ActionType action = Cmt::get_action ();
1653
1654 cmt_string value = build_macro_value ();
1655
1656 if ((!Cmt::get_quiet ()) &&
1657 (action != action_build_tag_makefile) &&
1658 (action != action_show_macros) &&
1659 (action != action_show_actions) &&
1660 (action != action_show_sets))
1661 {
1662 cout << "#" << endl;
1663 cout << "# Selection : " << endl;
1664 }
1665
1666 if (value.size () > 0)
1667 {
1668 if ((action == action_show_macro) ||
1669 (action == action_show_macros) ||
1670 (action == action_show_sets) ||
1671 (action == action_show_set) ||
1672 (action == action_show_actions) ||
1673 (action == action_show_action) ||
1674 (action == action_build_tag_makefile) ||
1675 (action == action_load) ||
1676 (!Cmt::get_quiet ()))
1677 {
1678 if (mode == Make)
1679 {
1680 cout << name << "=";
1681 }
1682 else
1683 {
1684 cout << name << "='";
1685 }
1686 }
1687
1688 if ((action == action_show_macro_value) ||
1689 (action == action_show_set_value) ||
1690 (action == action_show_action_value))
1691 {
1692 expand (value);
1693 }
1694 else if (action == action_build_tag_makefile)
1695 {
1696 /*
1697 Unfortunately, the %xxx% pattern has to be kept on Unix. Therefore
1698 we cannot force all patterns to become $(xxx)
1699
1700 This was useful on Windows so as to only keep $(xxx)
1701 */
1702#ifdef WIN32
1703 suppress_OS_delimiters (value);
1704#endif
1705 }
1706
1707 cout << value;
1708
1709 if ((action == action_show_macro) ||
1710 (action == action_show_macros) ||
1711 (action == action_show_sets) ||
1712 (action == action_show_set) ||
1713 (action == action_show_actions) ||
1714 (action == action_show_action) ||
1715 (action == action_build_tag_makefile) ||
1716 (action == action_load) ||
1717 (!Cmt::get_quiet ()))
1718 {
1719 if (mode != Make)
1720 {
1721 cout << "'";
1722 }
1723#ifdef WIN32
1724 else
1725 {
1726 cout << " ";
1727 }
1728#endif
1729 }
1730
1731 cout << endl;
1732 }
1733}
1734
1735//-------------------------------------------------------------
1736void Symbol::clear_all ()
1737{
1738 static SymbolVector& Symbols = symbols ();
1739 static SymbolMap& SymbolMap = symbol_map ();
1740
1741 SymbolMap.clear ();
1742 Symbols.clear ();
1743}
1744
1745//-------------------------------------------------------------
1746void Symbol::expand (cmt_string& text)
1747{
1748 static cmt_regexp reg ("[$%`]");
1749
1750 if (!reg.match (text)) return;
1751
1752 resolve_value (text);
1753}
1754
1755//-------------------------------------------------------------
1756const cmt_string SetBuilder::build (const Symbol& symbol,
1757 const cmt_string& /*tag_name*/)
1758{
1759 // Control of recursivity
1760 static int level = 0;
1761
1762 int show_it = 0;
1763
1764 cmt_string temp;
1765 cmt_string previous_temp;
1766 cmt_string new_value;
1767 static const cmt_string empty;
1768
1769 ActionType action = Cmt::get_action ();
1770
1771 if (action == action_show_set)
1772 {
1773 if (symbol.name == Cmt::get_current_target ())
1774 {
1775 // Should not display on recursive calls
1776 if (level == 0) show_it = 1;
1777 }
1778 }
1779
1780 level++;
1781
1782 temp = "";
1783
1784 bool first_definition = true;
1785 bool defined = false;
1786
1787 for (int i = 0; i < symbol.value_lists.size (); i++)
1788 {
1789 const SymbolValueList& value_list = symbol.value_lists[i];
1790
1791 if ((value_list.use != 0) &&
1792 (value_list.use->discarded)) continue;
1793
1794 const int selected = value_list.select_first ();
1795
1796 if (selected < 0) continue;
1797
1798 SymbolValue& value = value_list.values[selected];
1799
1800 if (show_it)
1801 {
1802 value_list.show (symbol, value, first_definition);
1803 }
1804
1805 if (value_list.discarded) continue;
1806
1807 //
1808 // One should accumulate values if it refers to
1809 // itself.
1810 //
1811
1812 new_value = value.text;
1813
1814 resolve_value_for_macros (new_value);
1815
1816 switch (value_list.command_type)
1817 {
1818 case CommandSet :
1819
1820 if (!value_list.is_reflexive ||
1821 !symbol.value_is_reflexive (value.text))
1822 {
1823 resolve_value (new_value, symbol.name, temp);
1824 temp = new_value;
1825 }
1826 else if (temp == "")
1827 {
1828 temp = CmtSystem::getenv (symbol.name);
1829 }
1830
1831 if (!defined)
1832 {
1833 defined = true;
1834 }
1835 else
1836 {
1837 if ((!Cmt::get_quiet ()) &&
1838 ((action == action_show_macro) ||
1839 (action == action_show_set) ||
1840 (action == action_show_action) ||
1841 (action == action_show_macros) ||
1842 (action == action_show_sets) ||
1843 (action == action_show_actions)))
1844 {
1845 cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
1846
1847 if (value_list.use != 0)
1848 {
1849 cerr << " in package " << value_list.use->get_package_name ();
1850 }
1851
1852 cerr << endl;
1853 }
1854 }
1855
1856 break;
1857 case CommandSetAppend :
1858
1859 if (new_value != "")
1860 {
1861 temp += new_value;
1862 }
1863
1864 break;
1865 case CommandSetPrepend :
1866
1867 if (new_value != "")
1868 {
1869 previous_temp = temp;
1870 temp = new_value;
1871 temp += previous_temp;
1872 }
1873
1874 break;
1875 case CommandSetRemove :
1876
1877 if (new_value != "")
1878 {
1879 temp.replace_all (new_value, empty);
1880 }
1881
1882 break;
1883 case CommandSetRemoveRegexp :
1884
1885 if (new_value != "")
1886 {
1887 cmt_regexp e (new_value);
1888 cmt_regexp::iterator it;
1889
1890 for (;;)
1891 {
1892 it = e.begin (temp);
1893 if (it == e.end ()) break;
1894
1895 temp.erase (it._pos, it._length);
1896 }
1897 }
1898
1899 break;
1900 case CommandAlias :
1901
1902 resolve_value (new_value, symbol.name, temp);
1903 temp = new_value;
1904
1905 break;
1906 }
1907 }
1908
1909 level--;
1910
1911 return (temp);
1912}
1913
1914static bool find_path_entry (const cmt_string& paths, const cmt_string& value)
1915{
1916 static const cmt_string path_separator = CmtSystem::path_separator ();
1917 static const cmt_string double_path_separator = path_separator + path_separator;
1918
1919 cmt_string complete_paths;
1920
1921 complete_paths = path_separator;
1922 complete_paths += paths;
1923 complete_paths += path_separator;
1924
1925 complete_paths.replace_all (double_path_separator, path_separator);
1926
1927 cmt_string complete_value;
1928 complete_value = path_separator;
1929 complete_value += value;
1930 complete_value += path_separator;
1931
1932 if (complete_paths.find (complete_value) == cmt_string::npos) return (false);
1933 else return (true);
1934}
1935
1936//-------------------------------------------------------------
1937const cmt_string PathBuilder::build (const Symbol& symbol,
1938 const cmt_string& /*tag_name*/)
1939{
1940 // Control of recursivity
1941 static int level = 0;
1942
1943 int show_it = 0;
1944
1945 cmt_string temp;
1946 cmt_string previous_temp;
1947 cmt_string new_value;
1948 static const cmt_string empty;
1949
1950 static cmt_string path_separator = CmtSystem::path_separator ();
1951
1952 ActionType action = Cmt::get_action ();
1953
1954 if (action == action_show_set)
1955 {
1956 if (symbol.name == Cmt::get_current_target ())
1957 {
1958 // Should not display on recursive calls
1959 if (level == 0) show_it = 1;
1960 }
1961 }
1962
1963 level++;
1964
1965 temp = CmtSystem::getenv (symbol.name);
1966
1967 bool first_definition = true;
1968 bool defined = false;
1969
1970 for (int i = 0; i < symbol.value_lists.size (); i++)
1971 {
1972 const SymbolValueList& value_list = symbol.value_lists[i];
1973
1974 if ((value_list.use != 0) &&
1975 (value_list.use->discarded)) continue;
1976
1977 const int selected = value_list.select_first ();
1978
1979 if (selected < 0) continue;
1980
1981 SymbolValue& value = value_list.values[selected];
1982
1983 if (show_it)
1984 {
1985 value_list.show (symbol, value, first_definition);
1986 }
1987
1988 if (value_list.discarded) continue;
1989
1990 new_value = value.text;
1991
1992 //resolve_value (new_value);
1993 resolve_value_for_macros (new_value);
1994
1995 switch (value_list.command_type)
1996 {
1997 case CommandPath :
1998
1999 if (!value_list.is_reflexive ||
2000 !symbol.value_is_reflexive (value.text))
2001 {
2002 resolve_value (new_value, symbol.name, temp);
2003 temp = new_value;
2004
2005 if (!defined)
2006 {
2007 defined = true;
2008 }
2009 else
2010 {
2011 if ((!Cmt::get_quiet ()) &&
2012 ((action == action_show_macro) ||
2013 (action == action_show_set) ||
2014 (action == action_show_action) ||
2015 (action == action_show_macros) ||
2016 (action == action_show_sets) ||
2017 (action == action_show_actions)))
2018 {
2019 cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
2020
2021 if (value_list.use != 0)
2022 {
2023 cerr << " in package " << value_list.use->get_package_name ();
2024 }
2025
2026 cerr << endl;
2027 }
2028 }
2029 }
2030
2031 break;
2032 case CommandPathAppend :
2033
2034 if (new_value != "")
2035 {
2036 if (!find_path_entry (temp, new_value))
2037 {
2038 if (temp != "") temp += path_separator;
2039
2040 temp += new_value;
2041 }
2042 }
2043
2044 break;
2045 case CommandPathPrepend :
2046
2047 if (new_value != "")
2048 {
2049 if (!find_path_entry (temp, new_value))
2050 {
2051 previous_temp = temp;
2052 temp = new_value;
2053 if (previous_temp != "") temp += path_separator;
2054 temp += previous_temp;
2055 }
2056 }
2057
2058 break;
2059 case CommandPathRemove :
2060
2061 if (new_value != "")
2062 {
2063 CmtSystem::cmt_string_vector paths;
2064
2065 CmtSystem::split (temp, path_separator, paths);
2066
2067 for (int j = 0; j < paths.size (); ++j)
2068 {
2069 cmt_string& s = paths[j];
2070
2071 if (s.find (new_value) != cmt_string::npos)
2072 {
2073 s = "";
2074 }
2075 }
2076
2077 Cmt::vector_to_string (paths, path_separator, temp);
2078 temp.replace_all ("::", ":");
2079 temp.replace_all (";;", ";");
2080 }
2081
2082 break;
2083 case CommandPathRemoveRegexp :
2084
2085 if (new_value != "")
2086 {
2087 cmt_regexp e (new_value);
2088
2089 CmtSystem::cmt_string_vector paths;
2090
2091 CmtSystem::split (temp, path_separator, paths);
2092
2093 for (int j = 0; j < paths.size (); ++j)
2094 {
2095 cmt_string& s = paths[j];
2096
2097 if (CmtSystem::getenv ("TESTPRR") != "")
2098 {
2099 cout << "PRR> s=[" << s << "]";
2100 }
2101
2102 if (e.match (s))
2103 {
2104 s = "";
2105
2106 if (CmtSystem::getenv ("TESTPRR") != "")
2107 {
2108 cout << " match ";
2109 }
2110 }
2111 else
2112 {
2113 if (CmtSystem::getenv ("TESTPRR") != "")
2114 {
2115 cout << " no match ";
2116 }
2117 }
2118
2119 if (CmtSystem::getenv ("TESTPRR") != "")
2120 {
2121 cout << endl;
2122 }
2123 }
2124
2125 Cmt::vector_to_string (paths, path_separator, temp);
2126 temp.replace_all ("::", ":");
2127 temp.replace_all (";;", ";");
2128 }
2129
2130 break;
2131 }
2132
2133 }
2134
2135 level--;
2136
2137 return (temp);
2138}
2139
2140//-------------------------------------------------------------
2141const cmt_string PathBuilder::clean (const Symbol& symbol,
2142 const cmt_string& /*tag_name*/)
2143{
2144 // Control of recursivity
2145 static int level = 0;
2146
2147 cmt_string temp;
2148 cmt_string new_value;
2149 static const cmt_string empty;
2150
2151 static cmt_string path_separator = CmtSystem::path_separator ();
2152
2153 temp = CmtSystem::getenv (symbol.name);
2154
2155 //cerr << "#####1 temp=" << temp << endl;
2156
2157 for (int i = 0; i < symbol.value_lists.size (); i++)
2158 {
2159 const SymbolValueList& value_list = symbol.value_lists[i];
2160
2161 if (value_list.discarded) continue;
2162
2163 if ((value_list.use != 0) &&
2164 (value_list.use->discarded)) continue;
2165
2166 const int selected = value_list.select_first ();
2167
2168 if (selected < 0) continue;
2169
2170 SymbolValue& value = value_list.values[selected];
2171
2172 new_value = value.text;
2173
2174 //resolve_value (new_value);
2175
2176 //cerr << "#####1 new_value=" << new_value << endl;
2177
2178 resolve_value_for_macros (new_value);
2179 resolve_value (new_value);
2180
2181 //cerr << "#####2 new_value=" << new_value << endl;
2182
2183 switch (value_list.command_type)
2184 {
2185 case CommandPath :
2186
2187 temp = "";
2188
2189 break;
2190 case CommandPathAppend :
2191 case CommandPathPrepend :
2192 case CommandPathRemove :
2193
2194 if (new_value != "")
2195 {
2196 CmtSystem::cmt_string_vector paths;
2197
2198 CmtSystem::split (temp, path_separator, paths);
2199
2200 for (int j = 0; j < paths.size (); ++j)
2201 {
2202 cmt_string& s = paths[j];
2203
2204 if (s.find (new_value) != cmt_string::npos)
2205 {
2206 s = "";
2207 }
2208
2209 if (j > 0)
2210 {
2211 cmt_string& s2 = paths[j-1];
2212 if (s2 == s)
2213 {
2214 s2 = "";
2215 }
2216 }
2217 }
2218
2219 Cmt::vector_to_string (paths, path_separator, temp);
2220 temp.replace_all ("::", ":");
2221 temp.replace_all (";;", ";");
2222 }
2223
2224 break;
2225 case CommandPathRemoveRegexp :
2226
2227 if (new_value != "")
2228 {
2229 cmt_regexp e (new_value);
2230
2231 CmtSystem::cmt_string_vector paths;
2232
2233 CmtSystem::split (temp, path_separator, paths);
2234
2235 for (int j = 0; j < paths.size (); ++j)
2236 {
2237 cmt_string& s = paths[j];
2238
2239 if (e.match (s))
2240 {
2241 s = "";
2242 }
2243
2244 if (j > 0)
2245 {
2246 cmt_string& s2 = paths[j-1];
2247 if (s2 == s)
2248 {
2249 s2 = "";
2250 }
2251 }
2252 }
2253
2254 Cmt::vector_to_string (paths, path_separator, temp);
2255 temp.replace_all ("::", ":");
2256 temp.replace_all (";;", ";");
2257 }
2258
2259 break;
2260 }
2261 }
2262
2263 //cerr << "#####2 temp=" << temp << endl;
2264
2265 return (temp);
2266}
2267
2268//-------------------------------------------------------------
2269const cmt_string MacroBuilder::build (const Symbol& symbol,
2270 const cmt_string& tag_name)
2271{
2272 // Control of recursivity
2273 static int level = 0;
2274
2275 cmt_string temp;
2276 cmt_string previous_temp;
2277 static const cmt_string empty;
2278 int show_it = 0;
2279
2280 ActionType action = Cmt::get_action ();
2281
2282 if (action == action_show_macro)
2283 {
2284 if (symbol.name == Cmt::get_current_target ())
2285 {
2286 // Should not display on recursive calls
2287 if (level == 0) show_it = 1;
2288 }
2289 }
2290
2291 level++;
2292
2293 temp = "";
2294
2295 int i;
2296
2297 bool first_definition = true;
2298 bool defined = false;
2299
2300 for (i = 0; i < symbol.value_lists.size (); i++)
2301 {
2302 const SymbolValueList& value_list = symbol.value_lists[i];
2303
2304 if ((value_list.use != 0) &&
2305 (value_list.use->discarded)) continue;
2306
2307 if (value_list.command_type != CommandMacroPrepend) continue;
2308
2309 const int selected = value_list.select_first (tag_name);
2310
2311 if (selected < 0) continue;
2312
2313 SymbolValue& value = value_list.values[selected];
2314
2315 if (show_it)
2316 {
2317 value_list.show (symbol, value, first_definition);
2318 }
2319
2320 if (value_list.discarded) continue;
2321
2322 previous_temp = temp;
2323 temp = value.text;
2324 temp += previous_temp;
2325 }
2326
2327 previous_temp = temp;
2328 temp = "";
2329
2330 first_definition = true;
2331
2332 for (i = 0; i < symbol.value_lists.size (); i++)
2333 {
2334 const SymbolValueList& value_list = symbol.value_lists[i];
2335
2336 if ((value_list.use != 0) &&
2337 (value_list.use->discarded)) continue;
2338
2339 if (value_list.command_type != CommandMacro) continue;
2340
2341 const int selected = value_list.select_first (tag_name);
2342
2343 if (selected < 0) continue;
2344
2345 SymbolValue& value = value_list.values[selected];
2346
2347 if (show_it)
2348 {
2349 value_list.show (symbol, value, first_definition);
2350 }
2351
2352 // WARNING:
2353 // Commented just for a test : should be uncommented after the test
2354 if (value_list.discarded) continue;
2355
2356 if (!value_list.is_reflexive ||
2357 !symbol.value_is_reflexive (value.text))
2358 {
2359 temp = value.text;
2360
2361 if (!defined)
2362 {
2363 defined = true;
2364 }
2365 else
2366 {
2367 /*
2368 if ((!Cmt::get_quiet ()) &&
2369 ((action == action_show_macro) ||
2370 (action == action_show_set) ||
2371 (action == action_show_action) ||
2372 (action == action_show_macros) ||
2373 (action == action_show_sets) ||
2374 (action == action_show_actions)))
2375 {
2376 cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
2377
2378 if (value_list.use != 0)
2379 {
2380 cerr << " in package " << value_list.use->get_package_name ();
2381 }
2382
2383 cerr << endl;
2384 }
2385 */
2386 }
2387 }
2388 }
2389
2390 previous_temp += temp;
2391 temp = previous_temp;
2392
2393 for (i = 0; i < symbol.value_lists.size (); i++)
2394 {
2395 const SymbolValueList& value_list = symbol.value_lists[i];
2396
2397 if ((value_list.use != 0) &&
2398 (value_list.use->discarded)) continue;
2399
2400 if (value_list.command_type != CommandMacroAppend) continue;
2401
2402 const int selected = value_list.select_first (tag_name);
2403
2404 if (selected < 0) continue;
2405
2406 SymbolValue& value = value_list.values[selected];
2407
2408 if (show_it)
2409 {
2410 value_list.show (symbol, value, first_definition);
2411 }
2412
2413 if (value_list.discarded) continue;
2414
2415 temp += value.text;
2416 }
2417
2418 for (i = 0; i < symbol.value_lists.size (); i++)
2419 {
2420 const SymbolValueList& value_list = symbol.value_lists[i];
2421
2422 if ((value_list.use != 0) &&
2423 (value_list.use->discarded)) continue;
2424
2425 if ((value_list.command_type != CommandMacroRemove) &&
2426 (value_list.command_type != CommandMacroRemoveRegexp) &&
2427 (value_list.command_type != CommandMacroRemoveAll) &&
2428 (value_list.command_type != CommandMacroRemoveAllRegexp)) continue;
2429
2430 const int selected = value_list.select_first (tag_name);
2431
2432 if (selected < 0) continue;
2433
2434 SymbolValue& value = value_list.values[selected];
2435
2436 if (show_it)
2437 {
2438 value_list.show (symbol, value, first_definition);
2439 }
2440
2441 if (value_list.discarded) continue;
2442
2443 switch (value_list.command_type)
2444 {
2445 case CommandMacroRemove :
2446 temp.replace (value.text, empty);
2447 break;
2448 case CommandMacroRemoveRegexp :
2449 if (value.text != "")
2450 {
2451 cmt_regexp e (value.text);
2452 cmt_regexp::iterator it;
2453
2454 it = e.begin (temp);
2455 if (it != e.end ())
2456 {
2457 temp.erase (it._pos, it._length);
2458 }
2459 }
2460 break;
2461 case CommandMacroRemoveAll :
2462 temp.replace_all (value.text, empty);
2463 break;
2464 case CommandMacroRemoveAllRegexp :
2465 if (value.text != "")
2466 {
2467 cmt_regexp e (value.text);
2468 cmt_regexp::iterator it;
2469
2470 for (;;)
2471 {
2472 it = e.begin (temp);
2473 if (it != e.end ())
2474 {
2475 temp.erase (it._pos, it._length);
2476 }
2477 else
2478 {
2479 break;
2480 }
2481 }
2482 }
2483 break;
2484 }
2485 }
2486
2487 level--;
2488
2489 return (temp);
2490}
2491
2492//-------------------------------------------------------------
2493const cmt_string ScriptBuilder::build (const Symbol& symbol,
2494 const cmt_string& tag_name)
2495{
2496 // Control of recursivity
2497 static int level = 0;
2498
2499 static const cmt_string empty = "";
2500
2501 if (symbol.value_lists.size () > 0)
2502 {
2503 const SymbolValueList& value_list = symbol.value_lists[0];
2504
2505 if (value_list.discarded) return (empty);
2506
2507 if ((value_list.use != 0) &&
2508 (value_list.use->discarded)) return (empty);
2509 }
2510
2511 return (symbol.name);
2512}
2513
2514//-------------------------------------------------------------
2515const cmt_string ActionBuilder::build (const Symbol& symbol,
2516 const cmt_string& tag_name)
2517{
2518 // Control of recursivity
2519 static int level = 0;
2520
2521 cmt_string temp;
2522 cmt_string previous_temp;
2523 static const cmt_string empty;
2524 int show_it = 0;
2525
2526 ActionType action = Cmt::get_action ();
2527
2528 if (action == action_show_action)
2529 {
2530 if (symbol.name == Cmt::get_current_target ())
2531 {
2532 // Should not display on recursive calls
2533 if (level == 0) show_it = 1;
2534 }
2535 }
2536
2537 level++;
2538
2539 int i;
2540
2541 bool first_definition = true;
2542 bool defined = false;
2543
2544 temp = "";
2545
2546 for (i = 0; i < symbol.value_lists.size (); i++)
2547 {
2548 const SymbolValueList& value_list = symbol.value_lists[i];
2549
2550 if ((value_list.use != 0) &&
2551 (value_list.use->discarded)) continue;
2552
2553 if (value_list.command_type != CommandAction) continue;
2554
2555 const int selected = value_list.select_first (tag_name);
2556
2557 if (selected < 0) continue;
2558
2559 SymbolValue& value = value_list.values[selected];
2560
2561 if (show_it)
2562 {
2563 value_list.show (symbol, value, first_definition);
2564 }
2565
2566 // WARNING:
2567 // Commented just for a test : should be uncommented after the test
2568 if (value_list.discarded) continue;
2569
2570 if (!value_list.is_reflexive ||
2571 !symbol.value_is_reflexive (value.text))
2572 {
2573 temp = value.text;
2574
2575 if (!defined)
2576 {
2577 defined = true;
2578 }
2579 else
2580 {
2581 if ((!Cmt::get_quiet ()) &&
2582 ((action == action_show_macro) ||
2583 (action == action_show_set) ||
2584 (action == action_show_action) ||
2585 (action == action_show_macros) ||
2586 (action == action_show_sets) ||
2587 (action == action_show_actions)))
2588 {
2589 cerr << "#CMT> Warning: Symbol " << symbol.name << " overridden";
2590
2591 if (value_list.use != 0)
2592 {
2593 cerr << " in package " << value_list.use->get_package_name ();
2594 }
2595
2596 cerr << endl;
2597 }
2598 }
2599 }
2600 }
2601
2602 level--;
2603
2604 return (temp);
2605}
2606
2607//-------------------------------------------------------------
2608int SymbolValueList::select_first (const cmt_string& tag_name) const
2609{
2610 int priority = 0;
2611 int value_number;
2612 int selected = -1;
2613
2614 Tag* the_tag = 0;
2615
2616 if (tag_name != "") the_tag = Tag::find (tag_name);
2617
2618 for (value_number = 0;
2619 value_number < values.size ();
2620 value_number++)
2621 {
2622 const SymbolValue& value = values[value_number];
2623
2624 const Tag* tag = value.tag;
2625
2626 if (the_tag == 0)
2627 {
2628 if (!tag->is_selected ()) continue;
2629 }
2630 else
2631 {
2632 if (tag != the_tag) continue;
2633 selected = value_number;
2634 }
2635
2636 //
2637 // Only the first value at a given priority is
2638 // selected (which implies the '>' test instead
2639 // of '>=')
2640 //
2641
2642 if (tag->get_priority () > priority)
2643 {
2644 priority = tag->get_priority ();
2645 selected = value_number;
2646 }
2647 }
2648
2649 return (selected);
2650}
2651
2652//-------------------------------------------------------------
2653int SymbolValueList::select_last () const
2654{
2655 int priority = 0;
2656 int value_number;
2657 int selected = -1;
2658
2659 for (value_number = 0;
2660 value_number < values.size ();
2661 value_number++)
2662 {
2663 SymbolValue& value = values[value_number];
2664
2665 const Tag* tag = value.tag;
2666
2667 if (tag->is_selected ())
2668 {
2669 //
2670 // The last value at a given priority is
2671 // selected (which implies the '>=' test instead
2672 // of '>')
2673 //
2674
2675 if (tag->get_priority () >= priority)
2676 {
2677 priority = tag->get_priority ();
2678 selected = value_number;
2679 }
2680 }
2681 }
2682
2683 return (selected);
2684}
2685
2686//-------------------------------------------------------------
2687void SymbolValueList::show (const Symbol& symbol,
2688 const SymbolValue& value,
2689 bool& first_definition) const
2690{
2691 cmt_string discarded_text;
2692 cmt_string define_text;
2693 ActionType action = Cmt::get_action ();
2694
2695 if (value.text == "") return;
2696
2697 if (discarded) discarded_text = " (discarded by override)";
2698 else discarded_text = "";
2699
2700 if (first_definition) define_text = "defines";
2701 else define_text = "overrides";
2702
2703 cout << "# Package ";
2704 if (use != 0)
2705 {
2706 cout << use->get_package_name () << " " << use->version;
2707 }
2708
2709 switch (command_type)
2710 {
2711 case CommandSet :
2712 cout << " " << define_text << " set " << symbol.name << " as ";
2713 first_definition = false;
2714 break;
2715 case CommandSetAppend :
2716 cout << " appends to set " << symbol.name << " : ";
2717 break;
2718 case CommandSetPrepend :
2719 cout << " prepends to set " << symbol.name << " : ";
2720 break;
2721 case CommandSetRemove :
2722 cout << " removes from set " << symbol.name << " : ";
2723 break;
2724 case CommandSetRemoveRegexp :
2725 cout << " removes RE from set " << symbol.name << " : ";
2726 break;
2727 case CommandAlias :
2728 cout << " " << define_text << " alias " << symbol.name << " as ";
2729 first_definition = false;
2730 break;
2731 case CommandPath :
2732 cout << " " << define_text << " path " << symbol.name << " as ";
2733 first_definition = false;
2734 break;
2735 case CommandPathAppend :
2736 cout << " appends to path " << symbol.name << " : ";
2737 break;
2738 case CommandPathPrepend :
2739 cout << " prepends to path " << symbol.name << " : ";
2740 break;
2741 case CommandPathRemove :
2742 cout << " removes from path " << symbol.name << " : ";
2743 break;
2744 case CommandPathRemoveRegexp :
2745 cout << " removes RE from path " << symbol.name << " : ";
2746 break;
2747 case CommandMacroPrepend :
2748 cout << " prepends to macro " << symbol.name << " : ";
2749 break;
2750 case CommandMacro :
2751 cout << " " << define_text << " macro " << symbol.name << " as ";
2752 break;
2753 case CommandMacroAppend :
2754 cout << " appends to macro " << symbol.name << " : ";
2755 break;
2756 case CommandMacroRemove :
2757 cout << " remove from macro " << symbol.name << " : ";
2758 break;
2759 case CommandMacroRemoveRegexp :
2760 cout << " remove RE from macro " << symbol.name << " : ";
2761 break;
2762 case CommandMacroRemoveAll :
2763 cout << " remove all from macro " << symbol.name << " : ";
2764 break;
2765 case CommandMacroRemoveAllRegexp :
2766 cout << " remove all RE from macro " << symbol.name << " : ";
2767 break;
2768 case CommandAction :
2769 cout << " " << define_text << " action " << symbol.name << " as ";
2770 first_definition = false;
2771 break;
2772 }
2773
2774 cout << "'" << value.text << "'";
2775
2776 Tag* selected_tag = value.tag;
2777
2778 if ((selected_tag == 0) ||
2779 (selected_tag == Tag::get_default ()))
2780 {
2781 cout << " for default tag";
2782 }
2783 else
2784 {
2785 cout << " for tag '" << selected_tag->get_name () << "'";
2786 }
2787
2788 cout << discarded_text << endl;
2789}
2790
Note: See TracBrowser for help on using the repository browser.