source: CMT/v1r18p20050501/source/cmt_system.cxx @ 634

Last change on this file since 634 was 42, checked in by arnault, 19 years ago

Preparing support for projects in CVS - See CL 270

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