source: CMT/v1r20b1/source/cmt_system.cxx@ 327

Last change on this file since 327 was 205, checked in by garonne, 19 years ago

Correct touch function to conserve permission

  • Property svn:eol-style set to native
File size: 48.1 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 <errno.h>
11
12#ifdef WIN32
13#include <direct.h>
14#define chdir _chdir
15#define rmdir _rmdir
16//#define mkdir _mkdir
17#define getcwd _getcwd
18#define popen _popen
19#define pclose _pclose
20#define S_IFDIR _S_IFDIR
21#define USE_GETCWD 1
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <time.h>
26#include <io.h>
27#include <windows.h>
28
29#define stat _stat
30
31#else
32#include <unistd.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <time.h>
36#include <dirent.h>
37#endif
38
39#ifdef __hpux__
40#define USE_GETCWD 1
41#endif
42
43#ifdef __linux__
44#define USE_GETCWD 1
45#endif
46
47#ifdef USE_GETCWD
48char* getwd (const char* name)
49{
50 char dir[256];
51 getcwd (dir, sizeof (dir));
52 strcpy ((char*) name, dir);
53 return ((char*) name);
54}
55#endif
56
57#include "cmt_system.h"
58#include "cmt_error.h"
59#include "cmt_map.h"
60
61//--------------------------------------------------
62cmt_string CmtSystem::pwd ()
63{
64 char buffer[256] = "";
65 char* ptr = 0;
66 char* pwd_env = 0;
67
68#ifdef USE_PWD
69 pwd_env = ::getenv ("PWD");
70#endif
71
72 if (pwd_env != 0)
73 {
74 strcpy (buffer, pwd_env);
75 }
76 else
77 {
78 ptr = getcwd (buffer, sizeof (buffer));
79 }
80
81 const char* t = &buffer[0];
82 return ((cmt_string) t);
83}
84
85//--------------------------------------------------
86bool CmtSystem::cd (const cmt_string& dir)
87{
88 static cmt_string new_dir;
89
90 if ((dir.size () == 2) && (dir[1] == ':'))
91 {
92 new_dir = dir;
93 new_dir += file_separator ();
94 if (chdir (new_dir.c_str ()) == 0)
95 {
96#ifdef USE_PWD
97 new_dir = dir;
98 new_dir += file_separator ();
99 putenv ("PWD", new_dir);
100#endif
101
102 return (true);
103 }
104 return (false);
105 }
106 else
107 {
108 if (chdir (dir.c_str ()) == 0)
109 {
110#ifdef USE_PWD
111 putenv ("PWD", dir);
112#endif
113
114 return (true);
115 }
116 return (false);
117 }
118}
119
120//--------------------------------------------------
121void CmtSystem::basename (const cmt_string& file_name, cmt_string& result)
122{
123 int pos = file_name.find_last_of ('/');
124 if (pos == cmt_string::npos)
125 {
126 pos = file_name.find_last_of ('\\');
127 }
128
129 if (pos == cmt_string::npos)
130 {
131 result = file_name;
132 }
133 else
134 {
135 file_name.substr (pos + 1, result);
136 }
137}
138
139//--------------------------------------------------
140void CmtSystem::basename (const cmt_string& file_name,
141 const cmt_string& /*suffix*/,
142 cmt_string& result)
143{
144 basename (file_name, result);
145
146 int pos;
147
148 pos = result.find_last_of ('.');
149
150 if (pos != cmt_string::npos)
151 {
152 result.erase (pos);
153 }
154}
155
156//--------------------------------------------------
157void CmtSystem::dirname (const cmt_string& file_name, cmt_string& result)
158{
159 int pos = file_name.find_last_of ('/');
160 if (pos == cmt_string::npos)
161 {
162 pos = file_name.find_last_of ('\\');
163 }
164
165 if (pos == cmt_string::npos)
166 {
167 result = "";
168 }
169 else
170 {
171 result = file_name;
172 result.erase (pos);
173 }
174}
175
176//--------------------------------------------------
177void CmtSystem::name (const cmt_string& file_name, cmt_string& result)
178{
179 int pos;
180
181 result = file_name;
182
183 // remove the suffix
184
185 pos = result.find_last_of ('.');
186
187 if (pos != cmt_string::npos)
188 {
189 result.erase (pos);
190 }
191
192 // remove the directory name
193
194 pos = result.find_last_of ('/');
195 if (pos == cmt_string::npos)
196 {
197 pos = result.find_last_of ('\\');
198 }
199
200 if (pos != cmt_string::npos)
201 {
202 result.erase (0, pos + 1);
203 }
204}
205
206//-------------------------------------------------
207void CmtSystem::get_suffix (const cmt_string& file, cmt_string& result)
208{
209 int pos = file.find_last_of ('.');
210 int sep = file.find_last_of (file_separator ());
211
212 if ((pos == cmt_string::npos) || (pos < sep))
213 {
214 result = "";
215 }
216 else
217 {
218 file.substr (pos + 1, result);
219 }
220}
221
222//-------------------------------------------------
223void CmtSystem::get_dot_suffix (const cmt_string& file, cmt_string& result)
224{
225 int pos = file.find_last_of ('.');
226 int sep = file.find_last_of (file_separator ());
227
228 if ((pos == cmt_string::npos) || (pos < sep))
229 {
230 result = "";
231 }
232 else
233 {
234 file.substr (pos, result);
235 }
236}
237
238//--------------------------------------------------
239bool CmtSystem::has_prefix (const cmt_string& name)
240{
241 if ((name.find ('/') == cmt_string::npos) &&
242 (name.find ('\\') == cmt_string::npos))
243 {
244 return (false);
245 }
246
247 return (true);
248}
249
250//--------------------------------------------------
251bool CmtSystem::realpath (const cmt_string& path, cmt_string& result)
252{
253 cmt_string here = CmtSystem::pwd ();
254 if (test_directory(path))
255 {
256 CmtSystem::cd (path);
257 result = CmtSystem::pwd ();
258 CmtSystem::cd (here);
259 return true;
260 }
261 return false;
262}
263
264//--------------------------------------------------
265bool CmtSystem::absolute_path (const cmt_string& name)
266{
267 if (name.size () == 0) return (false);
268
269 if ((name[0] == '/') ||
270 (name[0] == '\\')) return (true);
271
272 if (name.size () >= 2)
273 {
274 if (name[1] == ':')
275 {
276 return (true);
277 }
278 }
279 return (false);
280}
281
282//--------------------------------------------------
283bool CmtSystem::has_device (const cmt_string& name)
284{
285#ifdef WIN32
286 if (name.size () == 0) return (false);
287
288 if (name.size () >= 2)
289 {
290 if (name[1] == ':')
291 {
292 return (true);
293 }
294 else if ((name[0] == '\\') && (name[1] == '\\'))
295 {
296 return (true);
297 }
298 }
299#endif
300
301 return (false);
302}
303
304//--------------------------------------------------
305cmt_string CmtSystem::current_branch ()
306{
307 cmt_string result;
308
309 basename (pwd (), result);
310
311 return (result);
312}
313
314//--------------------------------------------------
315bool CmtSystem::test_directory (const cmt_string& name)
316{
317 struct stat file_stat;
318 int status;
319
320 status = stat (name.c_str (), &file_stat);
321
322 //cerr << "status(stat) for " << name << " : " << status << " st_mode=" << file_stat.st_mode << endl;
323
324 if (status == 0)
325 {
326 if ((file_stat.st_mode & S_IFDIR) == 0)
327 {
328 return (false);
329 }
330 else
331 {
332 return (true);
333 }
334 }
335 else
336 {
337 return (false);
338 }
339}
340
341//--------------------------------------------------
342bool CmtSystem::test_file (const cmt_string& name)
343{
344 struct stat file_stat;
345 int status;
346
347 status = stat (name.c_str (), &file_stat);
348
349 if (status == 0)
350 {
351 if ((file_stat.st_mode & S_IFDIR) == 0)
352 {
353 return (true);
354 }
355 else
356 {
357 return (false);
358 }
359 }
360 else
361 {
362 return (false);
363 }
364}
365
366//--------------------------------------------------
367bool CmtSystem::compare_files (const cmt_string& name1,
368 const cmt_string& name2)
369{
370 struct stat file_stat1;
371 struct stat file_stat2;
372 int status;
373
374 status = stat (name1.c_str (), &file_stat1);
375
376 if (status == 0)
377 {
378 if ((file_stat1.st_mode & S_IFDIR) != 0)
379 {
380 return (false);
381 }
382 }
383 else
384 {
385 return (false);
386 }
387
388 status = stat (name2.c_str (), &file_stat2);
389
390 if (status == 0)
391 {
392 if ((file_stat2.st_mode & S_IFDIR) != 0)
393 {
394 return (false);
395 }
396 }
397 else
398 {
399 return (false);
400 }
401
402 if (((int) file_stat1.st_size) != ((int) file_stat2.st_size))
403 {
404 return (false);
405 }
406
407 static cmt_string s1;
408 static cmt_string s2;
409
410 s1.read (name1);
411 s2.read (name2);
412
413 return ((s1 == s2));
414}
415
416//--------------------------------------------------
417//
418// Function use to change file timestamps
419//
420//--------------------------------------------------
421bool CmtSystem::touch_file (const cmt_string& name)
422{
423 if (CmtSystem::test_file(name))
424 {
425 static cmt_string s;
426 s.read (name);
427 //unlink (name);
428 FILE* f = fopen (name, "wb");
429 if (f != NULL)
430 {
431 s.write (f);
432 fclose (f);
433 return (true);
434 }
435 chmod (name.c_str(), 0777);
436/* FILE* f = fopen (name, "a+");
437
438 if (f != NULL)
439 {
440 cmt_string empty = " ";
441 empty.write(f);
442
443 fclose (f);
444 return true;
445 }
446*/
447 }
448 return false;
449}
450
451
452//--------------------------------------------------
453//
454// Check if the file "name1" is identical to "name2"
455// if they are identical, "name1" will be simply deleted
456// otherwise "name1" will be copied to "name2" and deleted afterwards
457//
458//--------------------------------------------------
459bool CmtSystem::compare_and_update_files (const cmt_string& name1,
460 const cmt_string& name2)
461{
462 struct stat file_stat1;
463 struct stat file_stat2;
464 static cmt_string s1;
465 static cmt_string s2;
466 int status;
467
468 status = stat (name1.c_str (), &file_stat1);
469
470 if (status == 0)
471 {
472 if ((file_stat1.st_mode & S_IFDIR) != 0)
473 {
474 // name1 is a directory.
475 return (false);
476 }
477 }
478 else
479 {
480 // name1 does not exist
481 return (false);
482 }
483
484 s1.read (name1);
485
486 status = stat (name2.c_str (), &file_stat2);
487
488 if (status == 0)
489 {
490 if ((file_stat2.st_mode & S_IFDIR) != 0)
491 {
492 // name2 is a directory
493 return (false);
494 }
495
496 if (((int) file_stat1.st_size) == ((int) file_stat2.st_size))
497 {
498 s2.read (name2);
499 if (s1 == s2)
500 {
501 unlink (name1);
502 return (true);
503 }
504 }
505 }
506
507 FILE* f = fopen (name2, "wb");
508 if (f != NULL)
509 {
510 s1.write (f);
511 fclose (f);
512
513 unlink (name1);
514
515 return (true);
516 }
517 else
518 {
519 //
520 // keep the new file "name1" since it cannot be
521 // copied to "name2"
522 //
523 return (false);
524 }
525}
526
527//--------------------------------------------------
528int CmtSystem::file_size (const cmt_string& name)
529{
530 struct stat file_stat;
531 int status;
532
533 status = stat (name.c_str (), &file_stat);
534
535 if (status == 0)
536 {
537 return ((int) file_stat.st_size);
538 }
539 else
540 {
541 return (0);
542 }
543}
544
545//--------------------------------------------------
546char CmtSystem::file_separator ()
547{
548#ifdef WIN32
549 return ('\\');
550#else
551 return ('/');
552#endif
553}
554
555/**
556 * Transform all / or \ characters in the text into the current file_separator
557 * Reduce all multiple file_separator into single ones.
558 */
559void CmtSystem::reduce_file_separators (cmt_string& text)
560{
561 if (file_separator () == '/')
562 {
563 text.replace_all ("\\", "/");
564 while (text.find ("//") != cmt_string::npos)
565 {
566 text.replace_all ("//", "/");
567 }
568 }
569 else
570 {
571 text.replace_all ("/", "\\");
572 while (text.find ("\\\\") != cmt_string::npos)
573 {
574 text.replace_all ("\\\\", "\\");
575 }
576 }
577}
578
579//--------------------------------------------------
580char CmtSystem::path_separator ()
581{
582#ifdef WIN32
583 return (';');
584#else
585 return (':');
586#endif
587}
588
589//--------------------------------------------------
590char CmtSystem::command_separator ()
591{
592#ifdef WIN32
593 return ('&');
594#else
595 return (';');
596#endif
597}
598
599//--------------------------------------------------
600const cmt_string& CmtSystem::ev_open ()
601{
602#ifdef WIN32
603 static const cmt_string s = "%";
604#else
605 static const cmt_string s = "${";
606#endif
607
608 return (s);
609}
610
611//--------------------------------------------------
612const cmt_string& CmtSystem::ev_close ()
613{
614#ifdef WIN32
615 static const cmt_string s = "%";
616#else
617 static const cmt_string s = "}";
618#endif
619
620 return (s);
621}
622
623//-------------------------------------------------
624bool CmtSystem::create_symlink (const cmt_string& oldname,
625 const cmt_string& newname)
626{
627 ::unlink (newname.c_str ());
628
629#ifdef WIN32
630 int status = 1;
631#else
632 int status = ::symlink (oldname.c_str (), newname.c_str ());
633#endif
634
635 if (status == 0) return (true);
636 return (false);
637}
638
639//-------------------------------------------------
640bool CmtSystem::remove_file (const cmt_string& name)
641{
642 if (::unlink (name) != 0)
643 {
644 cerr << "#CMT> Cannot remove file " << name << endl;
645 return (false);
646 }
647
648 return (true);
649}
650
651//-------------------------------------------------
652bool CmtSystem::remove_directory (const cmt_string& name)
653{
654 //cerr << "Try to remove directory " << name << endl;
655
656 cmt_string_vector files;
657
658 scan_dir (name, files);
659
660 for (int i = 0; i < files.size (); i++)
661 {
662 cmt_string& file = files[i];
663
664 if (test_directory (file))
665 {
666 //cerr << "D=" << file << endl;
667 if (!remove_directory (file)) return (false);
668 }
669 else
670 {
671 //cerr << "F=" << file << endl;
672 if (!remove_file (file)) return (false);
673 }
674 }
675
676 int status = ::rmdir (name);
677 if (status != 0)
678 {
679 cerr << "#CMT> Cannot remove directory " << name << " errno=" << errno << endl;
680 return (false);
681 }
682
683 return (true);
684}
685
686//-------------------------------------------------
687bool CmtSystem::mkdir (const cmt_string& name)
688{
689 static cmt_string_vector path_vector;
690 int i;
691 static cmt_string full_path;
692 char double_fs[] = " ";
693
694 double_fs[0] = file_separator ();
695 double_fs[1] = file_separator ();
696
697 full_path = name;
698
699 if (file_separator () == '/')
700 {
701 full_path.replace_all ("\\", file_separator ());
702 }
703 else
704 {
705 full_path.replace_all ("/", file_separator ());
706 }
707
708 full_path.replace_all (double_fs, file_separator ());
709
710 split (full_path, file_separator (), path_vector);
711
712 full_path = "";
713
714 if (absolute_path (name))
715 {
716 if (!has_device (name))
717 {
718 full_path = file_separator ();
719 }
720 }
721
722 for (i = 0; i < path_vector.size (); i++)
723 {
724 const cmt_string& path = path_vector[i];
725
726 if (i > 0) full_path += file_separator ();
727 full_path += path;
728
729 if (has_device (path)) continue;
730
731 if (!test_directory (full_path))
732 {
733#ifdef WIN32
734 if (::_mkdir (full_path.c_str ()) != 0)
735 {
736 // cerr << "CMT> cannot create directory " << full_path << endl;
737 return (false);
738 }
739#else
740 if (::mkdir (full_path.c_str (), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) != 0)
741 {
742 // cerr << "CMT> cannot create directory " << full_path << endl;
743 return (false);
744 }
745#endif
746 }
747 }
748
749 return (true);
750}
751
752//----------------------------------------------------------
753void CmtSystem::scan_dir (const cmt_string& dir_name,
754 cmt_string_vector& list)
755{
756 static cmt_string dir_prefix;
757 static cmt_string name_prefix;
758
759 dir_prefix = dir_name;
760 if (dir_name == "") dir_prefix = ".";
761
762 if (!test_directory (dir_prefix))
763 {
764 dirname (dir_prefix, dir_prefix);
765 basename (dir_name, name_prefix);
766 }
767 else
768 {
769 name_prefix = "";
770 }
771
772 bool need_filter = false;
773
774 int wild_card;
775
776 wild_card = name_prefix.find ('*');
777 if (wild_card != cmt_string::npos)
778 {
779 name_prefix.erase (wild_card);
780 }
781
782 if (name_prefix.size () > 0)
783 {
784 need_filter = true;
785 }
786
787 list.clear ();
788
789#ifdef WIN32
790
791 long dir;
792 struct _finddata_t entry;
793
794 static cmt_string search;
795
796 search = dir_prefix;
797 search += file_separator ();
798 search += "*";
799
800 dir = _findfirst (search.c_str (), &entry);
801 if (dir > 0)
802 {
803 for (;;)
804 {
805 if ((strcmp ((char*) entry.name, ".") != 0) &&
806 (strcmp ((char*) entry.name, "..") != 0) &&
807 (strncmp ((char*) entry.name, ".nfs", 4) != 0))
808 {
809 const char* name = entry.name;
810
811 if (!need_filter ||
812 (strncmp (name, name_prefix.c_str (), name_prefix.size ()) == 0))
813 {
814 cmt_string& name_entry = list.add ();
815
816 name_entry = dir_prefix;
817 name_entry += file_separator ();
818 name_entry += name;
819 }
820 }
821
822 int status = _findnext (dir, &entry);
823 if (status != 0)
824 {
825 break;
826 }
827 }
828
829 _findclose (dir);
830 }
831#else
832
833 //cout << "scan_dir> dir=" << dir_name << endl;
834
835 DIR* dir = opendir (dir_prefix.c_str ());
836
837 struct dirent* entry;
838
839 if (dir != 0)
840 {
841 while ((entry = readdir (dir)) != 0)
842 {
843 //if (entry->d_name[0] == '.') continue;
844 if (!strcmp ((char*) entry->d_name, ".")) continue;
845 if (!strcmp ((char*) entry->d_name, "..")) continue;
846 if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
847
848 const char* name = entry->d_name;
849
850 if (need_filter &&
851 (strncmp (name, name_prefix.c_str (), name_prefix.size ()) != 0)) continue;
852
853 //cout << "scan_dir> name=" << name << endl;
854
855 cmt_string& name_entry = list.add ();
856
857 name_entry = dir_prefix;
858 name_entry += file_separator ();
859 name_entry += name;
860 }
861
862 closedir (dir);
863 }
864#endif
865
866}
867
868//----------------------------------------------------------
869void CmtSystem::scan_dir (const cmt_string& dir_name,
870 const cmt_regexp& expression,
871 cmt_string_vector& list)
872{
873 static cmt_string dir_prefix;
874
875 dir_prefix = dir_name;
876 if (dir_name == "") dir_prefix = ".";
877
878 if (!test_directory (dir_prefix))
879 {
880 dirname (dir_prefix, dir_prefix);
881 }
882
883 list.clear ();
884
885#ifdef WIN32
886
887 long dir;
888 struct _finddata_t entry;
889
890 static cmt_string search;
891
892 search = dir_prefix;
893 search += file_separator ();
894 search += "*";
895
896 dir = _findfirst (search.c_str (), &entry);
897 if (dir > 0)
898 {
899 for (;;)
900 {
901 if ((entry.name[0] != '.') &&
902 (strcmp ((char*) entry.name, ".") != 0) &&
903 (strcmp ((char*) entry.name, "..") != 0) &&
904 (strncmp ((char*) entry.name, ".nfs", 4) != 0))
905 {
906 const char* name = entry.name;
907
908 if (expression.match (name))
909 {
910 cmt_string& name_entry = list.add ();
911
912 name_entry = dir_prefix;
913 name_entry += file_separator ();
914 name_entry += name;
915 }
916 }
917
918 int status = _findnext (dir, &entry);
919 if (status != 0)
920 {
921 break;
922 }
923 }
924 _findclose (dir);
925 }
926#else
927
928 //cout << "scan_dir> dir=" << dir_name << endl;
929
930 DIR* dir = opendir (dir_prefix.c_str ());
931
932 struct dirent* entry;
933
934 if (dir != 0)
935 {
936 while ((entry = readdir (dir)) != 0)
937 {
938 //if (entry->d_name[0] == '.') continue;
939 if (!strcmp ((char*) entry->d_name, ".")) continue;
940 if (!strcmp ((char*) entry->d_name, "..")) continue;
941 if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
942
943 const char* name = entry->d_name;
944
945 if (!expression.match (name)) continue;
946
947 cmt_string& name_entry = list.add ();
948
949 name_entry = dir_prefix;
950 name_entry += file_separator ();
951 name_entry += name;
952 }
953
954 closedir (dir);
955 }
956#endif
957
958}
959
960//----------------------------------------------------------
961CmtSystem::cmt_string_vector& CmtSystem::scan_dir (const cmt_string& dir_name)
962{
963 static cmt_string_vector result;
964
965 scan_dir (dir_name, result);
966
967 return (result);
968}
969
970//----------------------------------------------------------
971const cmt_string& CmtSystem::get_cmt_root ()
972{
973 static cmt_string root;
974
975 root = "";
976
977 const char* env = ::getenv ("CMTROOT");
978 if (env != 0)
979 {
980 root = env;
981
982 dirname (root, root);
983 dirname (root, root);
984 root.replace_all ("\"", "");
985 return (root);
986 }
987
988#ifdef WIN32
989 LONG status;
990 HKEY key = 0;
991
992 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
993 0, KEY_READ, &key);
994 if (status == ERROR_SUCCESS)
995 {
996 char temp[256];
997 DWORD length = sizeof (temp) - 1;
998 DWORD type;
999
1000 status = RegQueryValueEx (key, "root", 0, &type, (LPBYTE) temp, &length);
1001 if (status == ERROR_SUCCESS)
1002 {
1003 root = temp;
1004 return (root);
1005 }
1006 }
1007#endif
1008
1009 return (root);
1010}
1011
1012//----------------------------------------------------------
1013void CmtSystem::get_cmt_version (cmt_string& version)
1014{
1015 version = "";
1016
1017 const char* env = ::getenv ("CMTROOT");
1018 if (env != 0)
1019 {
1020 cmt_string s = env;
1021 basename (s, version);
1022 version.replace_all ("\"", "");
1023 }
1024 else
1025 {
1026#ifdef WIN32
1027 LONG status;
1028 HKEY key = 0;
1029
1030 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
1031 0, KEY_READ, &key);
1032 if (status == ERROR_SUCCESS)
1033 {
1034 char temp[256];
1035 DWORD length = sizeof (temp) - 1;
1036 DWORD type;
1037
1038 status = RegQueryValueEx (key, "version", 0, &type,
1039 (LPBYTE) temp, &length);
1040 if (status == ERROR_SUCCESS)
1041 {
1042 version = temp;
1043 }
1044 }
1045#endif
1046 }
1047}
1048
1049//----------------------------------------------------------
1050cmt_string CmtSystem::get_cmt_config ()
1051{
1052 const char* env = ::getenv ("CMTCONFIG");
1053 if (env != 0)
1054 {
1055 return (cmt_string (env));
1056 }
1057
1058 env = ::getenv ("CMTBIN");
1059 if (env != 0)
1060 {
1061 return (cmt_string (env));
1062 }
1063
1064#ifdef WIN32
1065 LONG status;
1066 HKEY key = 0;
1067
1068 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
1069 0, KEY_READ, &key);
1070 if (status == ERROR_SUCCESS)
1071 {
1072 char temp[256];
1073 DWORD length = sizeof (temp) - 1;
1074 DWORD type;
1075
1076 status = RegQueryValueEx (key, "config", 0, &type,
1077 (LPBYTE) temp, &length);
1078 if (status == ERROR_SUCCESS)
1079 {
1080 cmt_string config (temp);
1081 return (config);
1082 }
1083 }
1084
1085 return ("VisualC");
1086#endif
1087
1088 return ("");
1089
1090}
1091
1092//----------------------------------------------------------
1093cmt_string CmtSystem::get_cmt_site ()
1094{
1095 const char* env = ::getenv ("CMTSITE");
1096 if (env != 0)
1097 {
1098 return (cmt_string (env));
1099 }
1100
1101#ifdef WIN32
1102 LONG status;
1103 HKEY key = 0;
1104
1105 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
1106 0, KEY_READ, &key);
1107 if (status == ERROR_SUCCESS)
1108 {
1109 char temp[256];
1110 DWORD length = sizeof (temp) - 1;
1111 DWORD type;
1112
1113 status = RegQueryValueEx (key, "site", 0, &type, (LPBYTE) temp, &length);
1114 if (status == ERROR_SUCCESS)
1115 {
1116 cmt_string site (temp);
1117 return (site);
1118 }
1119 }
1120#endif
1121
1122 return ("");
1123}
1124
1125//----------------------------------------------------------
1126void CmtSystem::get_uname (cmt_string& uname)
1127{
1128#ifdef WIN32
1129 uname = "WIN32";
1130#else
1131
1132 uname = "";
1133
1134 FILE* file;
1135
1136 file = popen ("uname", "r");
1137
1138 if (file != 0)
1139 {
1140 char line[1024];
1141 char* ptr;
1142 char* nl;
1143
1144 line[0] = 0;
1145 ptr = fgets (line, sizeof (line), file);
1146 if (ptr != 0)
1147 {
1148 nl = strrchr (ptr, '\n');
1149 if (nl != 0) *nl = 0;
1150
1151 uname = ptr;
1152 }
1153 pclose (file);
1154 }
1155#endif
1156}
1157
1158//----------------------------------------------------------
1159void CmtSystem::get_hosttype (cmt_string& hosttype)
1160{
1161 hosttype = "";
1162
1163 char* ptr;
1164
1165 ptr = ::getenv ("HOSTTYPE");
1166 if (ptr != 0)
1167 {
1168 hosttype = ptr;
1169 }
1170}
1171
1172//----------------------------------------------------------
1173cmt_string CmtSystem::get_temporary_name ()
1174{
1175 cmt_string name;
1176
1177 name = ::tmpnam (NULL);
1178
1179 return (name);
1180}
1181
1182//----------------------------------------------------------
1183cmt_string CmtSystem::get_home_package ()
1184{
1185 cmt_string name = "CMTHOME";
1186
1187 return (name);
1188}
1189
1190//----------------------------------------------------------
1191bool CmtSystem::is_home_package (const cmt_string& name,
1192 const cmt_string& version)
1193{
1194 if (name == "CMTHOME") return (true);
1195
1196 return (false);
1197}
1198
1199//----------------------------------------------------------
1200cmt_string CmtSystem::get_user_context_package ()
1201{
1202 cmt_string name = "CMTUSERCONTEXT";
1203
1204 return (name);
1205}
1206
1207//----------------------------------------------------------
1208bool CmtSystem::is_user_context_package (const cmt_string& name,
1209 const cmt_string& version)
1210{
1211 if (name == "CMTUSERCONTEXT") return (true);
1212
1213 return (false);
1214}
1215
1216//----------------------------------------------------------
1217cmt_string CmtSystem::get_project_package ()
1218{
1219 cmt_string name = "PROJECT";
1220
1221 return (name);
1222}
1223
1224//----------------------------------------------------------
1225bool CmtSystem::is_project_package (const cmt_string& name,
1226 const cmt_string& version)
1227{
1228 if (name == "PROJECT") return (true);
1229
1230 return (false);
1231}
1232
1233//----------------------------------------------------------
1234bool CmtSystem::testenv (const cmt_string& name)
1235{
1236 const char* env = ::getenv (name);
1237 if (env == 0) return (false);
1238 return (true);
1239}
1240
1241//----------------------------------------------------------
1242cmt_string CmtSystem::getenv (const cmt_string& name)
1243{
1244 cmt_string result;
1245
1246 const char* env = ::getenv (name);
1247 if (env != 0)
1248 {
1249 result = env;
1250 }
1251
1252 if (name == "CMTCONFIG")
1253 {
1254 return (get_cmt_config ());
1255 }
1256
1257 /*
1258 if (name == "CMTROOT")
1259 {
1260 return (get_cmt_root ());
1261 }
1262
1263 if (name == "CMTSITE")
1264 {
1265 return (get_cmt_site ());
1266 }
1267 */
1268
1269 return (result);
1270}
1271
1272/**
1273 Implementation based on a local static map of used environment
1274variables to ensure a stable character string. The OS requires
1275that the character string sent via a putenv is kept untouched forever
1276 */
1277bool CmtSystem::putenv (const cmt_string& name, const cmt_string& value)
1278{
1279 static cmt_map <cmt_string, cmt_string> envs;
1280
1281 if (!envs.has (name))
1282 {
1283 cmt_string& v = *(new cmt_string);
1284 v = name;
1285 v += "=";
1286 v += value;
1287 envs.add (name, v);
1288 }
1289 else
1290 {
1291 cmt_string& v = *(envs.find (name));
1292 v = name;
1293 v += "=";
1294 v += value;
1295 }
1296
1297 {
1298 const cmt_string& v = *envs.find (name);
1299 //cerr << "#CmtSystem::putenv> name=" << name << " &v=" << &v << endl;
1300
1301 int status = ::putenv ((char*) v.c_str ());
1302
1303 if (status == 0) return (true);
1304 else return (false);
1305 }
1306
1307}
1308
1309//----------------------------------------------------------
1310//
1311// This singleton interacts with the ProjectFactory to consistently create
1312// the project graph.
1313//
1314// In particular a single-depth stack of the top project is maintained.
1315//
1316//----------------------------------------------------------
1317class CMTPathManager
1318{
1319public:
1320 static CMTPathManager& instance ();
1321 static void reset ();
1322 static void add_cmt_path (const cmt_string& path,
1323 const cmt_string& path_source,
1324 IProjectFactory& factory);
1325
1326private:
1327 CMTPathManager () : m_project (0)
1328 {
1329 }
1330
1331 void do_reset ()
1332 {
1333 m_project = 0;
1334 }
1335
1336 void do_add_cmt_path (const cmt_string& path,
1337 const cmt_string& path_source,
1338 IProjectFactory& factory)
1339 {
1340 cmt_string npath = path;
1341
1342 if (npath == "") return;
1343
1344#ifdef WIN32
1345 if (npath.size () == 2)
1346 {
1347 if (npath[1] == ':')
1348 {
1349 npath += CmtSystem::file_separator ();
1350 }
1351 }
1352#endif
1353
1354 npath.replace_all ("\\", CmtSystem::file_separator ());
1355 npath.replace_all ("/", CmtSystem::file_separator ());
1356
1357 if (!CmtSystem::absolute_path (npath))
1358 {
1359 cmt_string h = CmtSystem::pwd ();
1360 h += CmtSystem::file_separator ();
1361 h += npath;
1362 npath = h;
1363 }
1364
1365 CmtSystem::compress_path (npath);
1366
1367 //cerr << "adding npath=" << npath << endl;
1368
1369 while (npath[npath.size ()-1] == CmtSystem::file_separator ())
1370 {
1371 npath.erase (npath.size ()-1);
1372 }
1373
1374 //cerr << "adding npath=[" << npath << "]" << endl;
1375
1376 if (npath != "")
1377 {
1378 cmt_string project_name;
1379
1380 if ((path_source == "CMTUSERCONTEXT") ||
1381 (path_source == "CMTHOME"))
1382 {
1383 project_name = path_source;
1384 }
1385
1386 m_project = factory.create_project (project_name, npath, path_source, m_project);
1387 }
1388 }
1389
1390 Project* m_project;
1391};
1392
1393CMTPathManager& CMTPathManager::instance ()
1394{
1395 static CMTPathManager me;
1396
1397 return (me);
1398}
1399
1400void CMTPathManager::reset ()
1401{
1402 static CMTPathManager& me = instance ();
1403 me.do_reset ();
1404}
1405
1406void CMTPathManager::add_cmt_path (const cmt_string& path,
1407 const cmt_string& path_source,
1408 IProjectFactory& factory)
1409{
1410 static CMTPathManager& me = instance ();
1411 me.do_add_cmt_path (path, path_source, factory);
1412}
1413
1414
1415
1416//----------------------------------------------------------
1417static void add_cmt_paths_from_text (const cmt_string& text,
1418 const cmt_string& context,
1419 IProjectFactory& factory)
1420{
1421 static CmtSystem::cmt_string_vector path_vector;
1422 int i;
1423
1424 CmtSystem::split (text, CmtSystem::path_separator (), path_vector);
1425
1426 for (i = 0; i < path_vector.size (); i++)
1427 {
1428 const cmt_string& path = path_vector[i];
1429
1430 CMTPathManager::add_cmt_path (path, context, factory);
1431 }
1432}
1433
1434//----------------------------------------------------------
1435static void add_cmt_paths_from_file (const cmt_string& file_name, IProjectFactory& factory)
1436{
1437 if (!CmtSystem::test_file (file_name)) return;
1438
1439 static cmt_string text;
1440
1441 text.read (file_name);
1442
1443 int pos = text.find ("CMTPATH");
1444 if (pos == cmt_string::npos) return;
1445 pos += strlen ("CMTPATH");
1446 pos = text.find (pos, "=");
1447 if (pos == cmt_string::npos) return;
1448 pos++;
1449
1450 text.erase (0, pos);
1451
1452 int nl = text.find (pos, "\n");
1453 if (nl != cmt_string::npos) text.erase (nl);
1454
1455 add_cmt_paths_from_text (text, file_name, factory);
1456}
1457
1458//----------------------------------------------------------
1459//
1460// With this function we analyse all possible ways of
1461// externally entering CMTPATH items
1462// + from the environment variable
1463// + from .cmtrc files
1464// + from registry on Windows
1465// + from EV settings for CMTUSERCONTEXT and CMTHOME
1466//
1467// Then projects are created from these settings.
1468//
1469// (The other way to enter project graph is through project files)
1470//----------------------------------------------------------
1471void CmtSystem::get_cmt_paths (IProjectFactory& factory,
1472 const cmt_string& init_text,
1473 const cmt_string& cmt_user_context,
1474 const cmt_string& cmt_home)
1475{
1476 CMTPathManager::reset ();
1477
1478 if (init_text != "")
1479 {
1480 add_cmt_paths_from_text (init_text, "initialization", factory);
1481 }
1482
1483#ifdef WIN32
1484 LONG status;
1485 HKEY key = 0;
1486
1487 status = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\CMT\\path",
1488 0, KEY_READ, &key);
1489 if (status == ERROR_SUCCESS)
1490 {
1491 DWORD index = 0;
1492 char name[256];
1493 char temp[256];
1494
1495 for (;;)
1496 {
1497 DWORD name_length = sizeof (name) - 1;
1498 DWORD length = sizeof (temp) - 1;
1499 DWORD type;
1500 status = RegEnumValue (key, index,
1501 name, &name_length, 0, &type,
1502 (LPBYTE) temp, &length);
1503 if ((status == ERROR_SUCCESS) ||
1504 (status == 234))
1505 {
1506 const cmt_string path = temp;
1507 CMTPathManager::add_cmt_path (path, "HKEY_CURRENT_USER", factory);
1508 }
1509
1510 if (status == 259)
1511 {
1512 break;
1513 }
1514
1515 index++;
1516 }
1517 }
1518
1519 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT\\path",
1520 0, KEY_READ, &key);
1521 if (status == ERROR_SUCCESS)
1522 {
1523 DWORD index = 0;
1524 char name[256];
1525 char temp[256];
1526
1527 for (;;)
1528 {
1529 DWORD type;
1530 DWORD name_length = sizeof (name) - 1;
1531 DWORD length = sizeof (temp) - 1;
1532
1533
1534 status = RegEnumValue (key, index,
1535 name, &name_length, 0, &type,
1536 (LPBYTE) temp, &length);
1537 if (status != ERROR_NO_MORE_ITEMS)
1538 {
1539 const cmt_string path = temp;
1540 CMTPathManager::add_cmt_path (path, "HKEY_LOCAL_MACHINE", factory);
1541 }
1542 else
1543 {
1544 break;
1545 }
1546 index++;
1547 }
1548 }
1549
1550#endif
1551
1552 //-----------------------------------------
1553 // look for .cmtrc files :
1554 // first look in ./
1555 // then in "~/"
1556 // then in ${CMTROOT}/mgr
1557 //-----------------------------------------
1558 cmt_string rc_name;
1559
1560 add_cmt_paths_from_file (".cmtrc", factory);
1561
1562 if (get_home_directory (rc_name))
1563 {
1564 rc_name += file_separator ();
1565 rc_name += ".cmtrc";
1566 add_cmt_paths_from_file (rc_name, factory);
1567 }
1568
1569 rc_name = get_cmt_root ();
1570 rc_name += file_separator ();
1571 rc_name += "CMT";
1572 rc_name += file_separator ();
1573 cmt_string version;
1574 get_cmt_version (version);
1575 rc_name += version;
1576 rc_name += file_separator ();
1577 rc_name += "mgr";
1578 rc_name += file_separator ();
1579 rc_name += ".cmtrc";
1580
1581 add_cmt_paths_from_file (rc_name, factory);
1582
1583 CMTPathManager::add_cmt_path (cmt_user_context, "CMTUSERCONTEXT", factory);
1584 CMTPathManager::add_cmt_path (cmt_home, "CMTHOME", factory);
1585}
1586
1587//----------------------------------------------------------
1588int CmtSystem::execute (const cmt_string& command)
1589{
1590 //cout << "CmtSystem::execute1> [" << command << "]" << endl;
1591
1592 return (system (command.c_str ()));
1593}
1594
1595//----------------------------------------------------------
1596int CmtSystem::execute (const cmt_string& command, cmt_string& output)
1597{
1598 output = "";
1599
1600 //cout << "CmtSystem::execute2> [" << command << "]" << endl;
1601
1602 FILE* f = popen (command.c_str (), "r");
1603
1604 if (f != 0)
1605 {
1606 char line[256];
1607 char* ptr;
1608
1609 while ((ptr = fgets (line, sizeof (line), f)) != NULL)
1610 {
1611 output += ptr;
1612 }
1613 pclose (f);
1614
1615 return (0);
1616 }
1617
1618 return (1);
1619}
1620
1621//----------------------------------------------------------
1622bool CmtSystem::is_package_directory (const cmt_string& name)
1623{
1624 cmt_string_vector dirs;
1625
1626 cmt_regexp exp ("^[a-zA-Z.][0-9]+([a-zA-Z.][0-9]+([a-zA-Z.][0-9]+)?)?");
1627
1628 scan_dir (name, exp, dirs);
1629
1630 cmt_string req;
1631
1632 req = name;
1633 req += file_separator ();
1634 req += "cmt";
1635 req += file_separator ();
1636 req += "requirements";
1637
1638 if (test_file (req)) return (true);
1639
1640 if (dirs.size () == 0)
1641 {
1642 return (false);
1643 }
1644
1645 for (int i = 0; i < dirs.size (); i++)
1646 {
1647 const cmt_string& d = dirs[i];
1648
1649 req = d;
1650 req += file_separator ();
1651 req += "mgr";
1652 req += file_separator ();
1653 req += "requirements";
1654
1655 if (test_file (req)) return (true);
1656
1657 req = d;
1658 req += file_separator ();
1659 req += "cmt";
1660 req += file_separator ();
1661 req += "requirements";
1662
1663 if (test_file (req)) return (true);
1664 }
1665
1666 return (false);
1667}
1668
1669//----------------------------------------------------------
1670bool CmtSystem::is_version_directory (const cmt_string& name)
1671{
1672 int v;
1673 int r;
1674 int p;
1675
1676 return (is_version_directory (name, v, r, p));
1677}
1678
1679//----------------------------------------------------------
1680bool CmtSystem::is_version_directory (const cmt_string& name,
1681 int& v,
1682 int& r,
1683 int& p)
1684{
1685 if ((name == "HEAD") || (name == "head"))
1686 {
1687 v = 0;
1688 r = 0;
1689 p = 0;
1690
1691 return (true);
1692 }
1693
1694 static const cmt_string numbers = "0123456789";
1695
1696 static const int id_version = 0;
1697 static const int id_release = 1;
1698 static const int id_patch = 2;
1699
1700 cmt_string buffer;
1701
1702 enum
1703 {
1704 starting,
1705 at_key,
1706 at_number
1707 } state;
1708
1709 int id;
1710 int pos;
1711 int value;
1712
1713 v = 0;
1714 r = 0;
1715 p = 0;
1716
1717 //
1718 // version : v-field
1719 // | v-field r-field
1720 // | v-field r-field p-field
1721 //
1722 // v-field : field
1723 // r-field : field
1724 // p-field : field
1725 //
1726 // field : key '*'
1727 // | key number
1728 //
1729 // key : letters
1730 //
1731
1732 state = starting;
1733 id = id_version;
1734
1735 for (pos = 0; pos < name.size (); pos++)
1736 {
1737 char c = name[pos];
1738
1739 if (c == '*')
1740 {
1741 // A wild card
1742 switch (state)
1743 {
1744 case starting:
1745 // cannot start with a wild card ??
1746 v = -1;
1747 r = -1;
1748 p = -1;
1749 return (false);
1750 case at_key:
1751 // the numeric field is valued with a wild card
1752 switch (id)
1753 {
1754 case id_version:
1755 v = -1;
1756 case id_release:
1757 r = -1;
1758 case id_patch:
1759 p = -1;
1760 break;
1761 }
1762 return (true);
1763 case at_number:
1764 // question:
1765 // a number followed by a wild-card is considered as:
1766 // 1) a wild card on the number itself (1* comp with 1, 10, 12, 120, etc)
1767 // 2) a wild card on the next fields (1* comp with 1r1, 1-12 etc)
1768 //
1769
1770 // Here we select option 1)
1771
1772 sscanf (buffer.c_str (), "%d", &value);
1773 switch (id)
1774 {
1775 case id_version:
1776 //
1777 // lazy option 1 implies v = -1;
1778 // strict option 1 would imply v = -value;
1779 // option 2 implies v = value;
1780 //
1781
1782 v = -1;
1783 r = -1;
1784 p = -1;
1785 break;
1786 case id_release:
1787 r = value;
1788 p = -1;
1789 break;
1790 case id_patch:
1791 p = value;
1792 break;
1793 }
1794
1795 return (true);
1796 }
1797 }
1798 else if (numbers.find (c) == cmt_string::npos)
1799 {
1800 // A letter
1801 switch (state)
1802 {
1803 case starting:
1804 state = at_key;
1805 break;
1806 case at_key:
1807 // Multiple letter key (is it permitted??)
1808 break;
1809 case at_number:
1810 sscanf (buffer.c_str (), "%d", &value);
1811 switch (id)
1812 {
1813 case id_version:
1814 v = value;
1815 break;
1816 case id_release:
1817 r = value;
1818 break;
1819 case id_patch:
1820 p = value;
1821 break;
1822 }
1823 buffer = "";
1824 id++;
1825 state = at_key;
1826 break;
1827 }
1828 }
1829 else
1830 {
1831 // a number
1832 switch (state)
1833 {
1834 case starting:
1835 // not starting by a letter (syntax error)
1836 //return (false);
1837 case at_key:
1838 // the numeric field for the current id is starting now
1839 buffer += c;
1840 state = at_number;
1841 break;
1842 case at_number:
1843 // continuing the current numeric field
1844 buffer += c;
1845 break;
1846 }
1847 }
1848 }
1849
1850 switch (state)
1851 {
1852 case starting:
1853 // Empty version string
1854 return (false);
1855 case at_key:
1856 // Syntax error (when only letters. Ending letters is not an error)
1857 if (id == id_version) return (false);
1858 else return (true);
1859 case at_number:
1860 sscanf (buffer.c_str (), "%d", &value);
1861 switch (id)
1862 {
1863 case id_version:
1864 v = value;
1865 break;
1866 case id_release:
1867 r = value;
1868 break;
1869 case id_patch:
1870 p = value;
1871 break;
1872 }
1873 id++;
1874 state = at_key;
1875 return (true);
1876 }
1877
1878 return (false);
1879}
1880
1881//----------------------------------------------------------
1882// Split a line into words. Separators are spaces and tabs
1883// Text enclosed in double quotes is one word.
1884//----------------------------------------------------------
1885void CmtSystem::split (const cmt_string& text,
1886 const cmt_string& separators,
1887 cmt_string_vector& strings)
1888{
1889 static char* buffer = 0;
1890 static int allocated = 0;
1891
1892 bool finished = false;
1893
1894 strings.clear ();
1895
1896 if (text.size () == 0) return;
1897
1898 /*
1899 We are going to work in a copy of the text, since
1900 \0 will be inserted right after each found word.
1901
1902 Then the vector of strings is iteratively filled by each found word.
1903 */
1904
1905 if (buffer == 0)
1906 {
1907 allocated = text.size ();
1908 buffer = (char*) malloc (allocated + 1);
1909 }
1910 else
1911 {
1912 if (text.size () > allocated)
1913 {
1914 allocated = text.size ();
1915 buffer = (char*) realloc (buffer, allocated + 1);
1916 }
1917 }
1918
1919 strcpy (buffer, text.c_str ());
1920
1921 /*
1922 Algorithm :
1923
1924 We look for words separated by <separators> which may be
1925 o spaces (' ' or '\t')
1926 o other characters such as ':'
1927
1928 A word is a character string not containing any separator. A substring in
1929 this word my be enclosed between quotes (" or ') which permits separator
1930 inclusion within words.
1931 */
1932
1933 char* current_word = buffer;
1934
1935 while (*current_word != 0)
1936 {
1937 size_t prefix_length;
1938 size_t word_length;
1939
1940 /*
1941 while ((*current_word == ' ') ||
1942 (*current_word == '\t'))
1943 {
1944 current_word++;
1945 }
1946 */
1947
1948 // first skip all starting separators.
1949
1950 prefix_length = strspn (current_word, separators.c_str ());
1951 if (prefix_length > 0)
1952 {
1953 // Move to the first non-separator character
1954
1955 current_word += prefix_length;
1956 }
1957
1958 /*
1959 Parse the next word.
1960
1961 It may contain enclosures in quote characters or not.
1962 Quotes must be identical on both sides of each enclosure.
1963 */
1964
1965 char* running_char = current_word;
1966
1967 word_length = 0;
1968
1969 for (;;)
1970 {
1971 size_t unquoted_length;
1972 size_t separator_offset;
1973
1974 for (int p = 0;;)
1975 {
1976 unquoted_length = strcspn (running_char + p, "\"\'") + p;
1977 if ((unquoted_length > 0) && (running_char[unquoted_length-1] == '\\'))
1978 {
1979 p = unquoted_length + 1;
1980 }
1981 else
1982 {
1983 break;
1984 }
1985 }
1986
1987 separator_offset = strcspn (running_char, separators.c_str ());
1988
1989 if (separator_offset <= unquoted_length)
1990 {
1991 // no quote in this word -> we are finished for this one.
1992 running_char += separator_offset;
1993 break;
1994 }
1995
1996 // We have found a quoted enclosure. Move to it.
1997
1998 running_char += unquoted_length;
1999
2000 char quote = running_char[0];
2001
2002 // Remove it.
2003 {
2004 char* p = running_char;
2005 while (p[1] != 0)
2006 {
2007 *p = p[1];
2008 p++;
2009 }
2010 *p = 0;
2011 }
2012
2013 // Look for the next occurence of this quote.
2014 {
2015 char* p = strchr (running_char, quote);
2016 if (p == 0)
2017 {
2018 // Unmatched quote : the rest of the line will be taken as a word...
2019 running_char += strlen (running_char);
2020 finished = true;
2021 break;
2022 }
2023 else
2024 {
2025 running_char = p;
2026 }
2027 }
2028
2029 // Now we remove the ending quote from the word
2030 // (by shifting all remaining characters by one place to the left)
2031
2032 {
2033 char* p = running_char;
2034 while (p[1] != 0)
2035 {
2036 *p = p[1];
2037 p++;
2038 }
2039 *p = 0;
2040 }
2041 }
2042
2043 word_length = running_char - current_word;
2044
2045 if (current_word[word_length] == 0)
2046 {
2047 finished = true;
2048 }
2049 else
2050 {
2051 current_word[word_length] = 0;
2052 }
2053
2054 /*
2055 if ((t[0] == '"') ||
2056 (t[0] == '\'') ||
2057 (t[0] == ':'))
2058 {
2059 char* quote;
2060
2061 t++;
2062 quote = strchr (t, sep);
2063 if (quote != 0) *quote = 0;
2064 else finished = true;
2065 }
2066 else
2067 {
2068 int offset;
2069
2070 offset = strcspn (t, " \t:");
2071 if ((offset < 0) || (t[offset] == 0)) finished = true;
2072 if (!finished)
2073 {
2074 space = t + offset;
2075 *space = 0;
2076 }
2077 }
2078 */
2079
2080 // Store the current word into the vector of strings
2081
2082 {
2083 cmt_string& s = strings.add ();
2084 s = current_word;
2085 }
2086
2087 if (finished) break;
2088
2089 // Move to the next possible word.
2090 current_word += word_length + 1;
2091 }
2092}
2093
2094//----------------------------------------------------------
2095void CmtSystem::compress_path (const cmt_string& dir, cmt_string& new_dir)
2096{
2097 new_dir = dir;
2098
2099 compress_path (new_dir);
2100}
2101
2102//----------------------------------------------------------
2103//
2104// We try to detect the aaaa/xxxx/../bbbb patterns which should be
2105// equivalent to aaaa/bbbb
2106// this therefore consists in removing all /xxxx/../ when
2107// xxxx is different from ".."
2108// xxxx is different from "."
2109// xxxx does not contain any macro reference
2110//
2111//----------------------------------------------------------
2112void CmtSystem::compress_path (cmt_string& dir)
2113{
2114#ifdef WIN32
2115 static const char pattern[] = "\\..";
2116 static const char fs[] = "\\\\";
2117#else
2118 static const char pattern[] = "/..";
2119 static const char fs[] = "//";
2120#endif
2121
2122 if (dir.size () == 0) return;
2123
2124 //
2125 // We first synchronize to using file_separator() in any case.
2126 //
2127
2128 if (file_separator () == '/')
2129 {
2130 dir.replace_all ("\\", file_separator ());
2131 }
2132 else
2133 {
2134 dir.replace_all ("/", file_separator ());
2135 }
2136
2137 // Suppress all duplicated file separators
2138 dir.replace_all (fs, file_separator ());
2139
2140 for (;;)
2141 {
2142 int pos1;
2143 int pos2;
2144 int pos3;
2145
2146 pos1 = dir.find (pattern);
2147 if (pos1 == cmt_string::npos) break;
2148
2149 //
2150 // extract "aaaa/xxxx" from "aaaa/xxxx/../bbbb"
2151 //
2152 cmt_string p = dir.substr (0, pos1);
2153
2154 cmt_string dn;
2155 basename (p, dn);
2156 if (dn == "..") break;
2157 if (dn == ".") break;
2158 if (dn == "") break;
2159
2160 //
2161 // Is "aaaa/xxxx" only made of "xxxx" ?
2162 //
2163 pos2 = p.find_last_of (file_separator ());
2164
2165 if (pos2 == cmt_string::npos)
2166 {
2167 // the pattern was xxxx/..
2168 //
2169 // so xxxx is [0:pos1-1]
2170 //
2171 pos3 = p.find ("$");
2172 if (pos3 == cmt_string::npos)
2173 {
2174 dir.erase (0, pos1 + 3);
2175 }
2176 else
2177 {
2178 break;
2179 }
2180 }
2181 else
2182 {
2183 // 01234567890123456
2184 // aaaa/xxxx/../bbbb
2185 // 2 1 3
2186 //
2187 // erase the "/xxxx/.." pattern
2188 // result will be "aaaa/bbbb"
2189 //
2190 // Here xxxx is [pos2+1:pos1-1]
2191 //
2192
2193 pos3 = p.find (pos2, "$");
2194 if (pos3 == cmt_string::npos)
2195 {
2196 dir.erase (pos2, pos1 + 3 - pos2);
2197 }
2198 else
2199 {
2200 break;
2201 }
2202 }
2203 }
2204
2205 //if (dir[dir.size () - 1] == file_separator ()) dir.erase (dir.size () - 1);
2206}
2207
2208//----------------------------------------------------------
2209cmt_string CmtSystem::now ()
2210{
2211 cmt_string result;
2212
2213 time_t ltime;
2214 time (&ltime);
2215 result = ctime (&ltime);
2216
2217 result.replace_all ("\n", "");
2218
2219 return (result);
2220}
2221
2222//----------------------------------------------------------
2223cmt_string CmtSystem::user ()
2224{
2225#ifdef _WIN32
2226 cmt_string result = getenv ("USERNAME");
2227#else
2228 cmt_string result = getenv ("USER");
2229#endif
2230
2231 return (result);
2232}
2233
2234//----------------------------------------------------------
2235void CmtSystem::get_cvsroot (cmt_string& cvsroot)
2236{
2237 cvsroot = "";
2238
2239 const char* env = ::getenv ("CVSROOT");
2240 if (env != 0)
2241 {
2242 cvsroot = env;
2243 return;
2244 }
2245
2246#ifdef WIN32
2247 LONG status;
2248 HKEY key = 0;
2249
2250 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
2251 0, KEY_READ, &key);
2252 if (status == ERROR_SUCCESS)
2253 {
2254 char temp[256];
2255 DWORD length = sizeof (temp) - 1;
2256 DWORD type;
2257
2258 status = RegQueryValueEx (key, "CVSROOT", 0, &type,
2259 (LPBYTE) temp, &length);
2260 if (status == ERROR_SUCCESS)
2261 {
2262 cvsroot = temp;
2263 return;
2264 }
2265 }
2266#endif
2267}
2268
2269//----------------------------------------------------------
2270bool CmtSystem::get_home_directory (cmt_string& dir)
2271{
2272 bool status = false;
2273
2274#ifdef WIN32
2275 const char* homedrive = ::getenv ("HOMEDRIVE");
2276 const char* homepath = ::getenv ("HOMEPATH");
2277
2278 if ((homedrive != 0) && (homepath != 0))
2279 {
2280 dir = homedrive;
2281 dir += homepath;
2282 status = true;
2283 }
2284
2285#else
2286 const char* home_env = ::getenv ("HOME");
2287 if (home_env != 0)
2288 {
2289 dir = home_env;
2290 status = true;
2291 }
2292#endif
2293
2294 return (status);
2295}
2296
2297//----------------------------------------------------------
2298cmt_string CmtSystem::get_makefile_suffix ()
2299{
2300#ifdef WIN32
2301 return "nmake";
2302#else
2303 return "make";
2304#endif
2305}
2306
Note: See TracBrowser for help on using the repository browser.