source: CMT/v1r18p20050401/source/cmt_system.cxx @ 597

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

Accept HEAD as a valid version directory - CL261

  • Property svn:eol-style set to native
File size: 46.0 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  //cout << "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          if (!remove_directory (file)) return (false);
619        }
620      else
621        {
622          if (!remove_file (file)) return (false);
623        }
624    }
625 
626  int status = ::rmdir (name);
627  if (status != 0)
628    {
629      cerr << "#CMT> Cannot remove directory " << name << " errno=" << errno << endl;
630      return (false);
631    }
632
633  return (true);
634}
635
636//-------------------------------------------------
637bool CmtSystem::mkdir (const cmt_string& name)
638{
639  static cmt_string_vector path_vector;
640  int i;
641  static cmt_string full_path;
642  char double_fs[] = "  ";
643
644  double_fs[0] = file_separator ();
645  double_fs[1] = file_separator ();
646
647  full_path = name;
648
649  if (file_separator () == '/')
650    {
651      full_path.replace_all ("\\", file_separator ());
652    }
653  else
654    {
655      full_path.replace_all ("/", file_separator ());
656    }
657
658  full_path.replace_all (double_fs, file_separator ());
659
660  split (full_path, file_separator (), path_vector);
661
662  full_path = "";
663
664  if (absolute_path (name))
665    {
666      if (!has_device (name))
667        {
668          full_path = file_separator ();
669        }
670    }
671
672  for (i = 0; i < path_vector.size (); i++)
673    {
674      const cmt_string& path = path_vector[i];
675
676      if (i > 0) full_path += file_separator ();
677      full_path += path;
678
679      if (has_device (path)) continue;
680
681      if (!test_directory (full_path))
682        {
683#ifdef WIN32
684          if (::_mkdir (full_path.c_str ()) != 0)
685            {
686                // cerr << "CMT> cannot create directory " << full_path << endl;
687              return (false);
688            }
689#else
690          if (::mkdir (full_path.c_str (), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) != 0)
691            {
692                // cerr << "CMT> cannot create directory " << full_path << endl;
693              return (false);
694            }
695#endif
696        }
697    }
698
699  return (true);
700}
701
702//----------------------------------------------------------
703void CmtSystem::scan_dir (const cmt_string& dir_name,
704                          cmt_string_vector& list)
705{
706  static cmt_string dir_prefix;
707  static cmt_string name_prefix;
708
709  dir_prefix = dir_name;
710  if (dir_name == "") dir_prefix = ".";
711
712  if (!test_directory (dir_prefix))
713    {
714      dirname (dir_prefix, dir_prefix);
715      basename (dir_name, name_prefix);
716    }
717  else
718    {
719    }
720
721  bool need_filter = false;
722
723  int wild_card;
724
725  wild_card = name_prefix.find ('*');
726  if (wild_card != cmt_string::npos)
727    {
728      name_prefix.erase (wild_card);
729    }
730
731  if (name_prefix.size () > 0)
732    {
733      need_filter = true;
734    }
735
736  list.clear ();
737
738#ifdef WIN32
739
740  long dir;
741  struct _finddata_t entry;
742
743  static cmt_string search;
744
745  search = dir_prefix;
746  search += file_separator ();
747  search += "*";
748
749  dir = _findfirst (search.c_str (), &entry);
750  if (dir > 0)
751    {
752      for (;;)
753        {
754          if ((strcmp ((char*) entry.name, ".") != 0) &&
755              (strcmp ((char*) entry.name, "..") != 0) &&
756              (strncmp ((char*) entry.name, ".nfs", 4) != 0))
757            {
758              const char* name = entry.name;
759
760              if (!need_filter ||
761                  (strncmp (name, name_prefix.c_str (), name_prefix.size ()) == 0))
762                {
763                  cmt_string& name_entry = list.add ();
764
765                  name_entry = dir_prefix;
766                  name_entry += file_separator ();
767                  name_entry += name;
768                }
769            }
770
771          int status = _findnext (dir, &entry);
772          if (status != 0)
773            {
774              break;
775            }
776        }
777
778      _findclose (dir);
779    }
780#else
781
782  //cout << "scan_dir> dir=" << dir_name << endl;
783
784  DIR* dir = opendir (dir_prefix.c_str ());
785
786  struct dirent* entry;
787
788  if (dir != 0)
789    {
790      while ((entry = readdir (dir)) != 0)
791        {
792          //if (entry->d_name[0] == '.') continue;
793          if (!strcmp ((char*) entry->d_name, ".")) continue;
794          if (!strcmp ((char*) entry->d_name, "..")) continue;
795          if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
796
797          const char* name = entry->d_name;
798
799          if (need_filter &&
800              (strncmp (name, name_prefix.c_str (), name_prefix.size ()) != 0)) continue;
801
802          //cout << "scan_dir> name=" << name << endl;
803
804          cmt_string& name_entry = list.add ();
805
806          name_entry = dir_prefix;
807          name_entry += file_separator ();
808          name_entry += name;
809        }
810
811      closedir (dir);
812    }
813#endif
814
815}
816
817//----------------------------------------------------------
818void CmtSystem::scan_dir (const cmt_string& dir_name,
819                          const cmt_regexp& expression,
820                          cmt_string_vector& list)
821{
822  static cmt_string dir_prefix;
823
824  dir_prefix = dir_name;
825  if (dir_name == "") dir_prefix = ".";
826
827  if (!test_directory (dir_prefix))
828    {
829      dirname (dir_prefix, dir_prefix);
830    }
831
832  list.clear ();
833
834#ifdef WIN32
835
836  long dir;
837  struct _finddata_t entry;
838
839  static cmt_string search;
840
841  search = dir_prefix;
842  search += file_separator ();
843  search += "*";
844
845  dir = _findfirst (search.c_str (), &entry);
846  if (dir > 0)
847    {
848      for (;;)
849        {
850          if ((entry.name[0] != '.') &&
851              (strcmp ((char*) entry.name, ".") != 0) &&
852              (strcmp ((char*) entry.name, "..") != 0) &&
853              (strncmp ((char*) entry.name, ".nfs", 4) != 0))
854            {
855              const char* name = entry.name;
856             
857              if (expression.match (name))
858                {
859                  cmt_string& name_entry = list.add ();
860
861                  name_entry = dir_prefix;
862                  name_entry += file_separator ();
863                  name_entry += name;
864                }
865            }
866
867          int status = _findnext (dir, &entry);
868          if (status != 0)
869            {
870              break;
871            }
872        }
873      _findclose (dir);
874    }
875#else
876
877  //cout << "scan_dir> dir=" << dir_name << endl;
878
879  DIR* dir = opendir (dir_prefix.c_str ());
880
881  struct dirent* entry;
882
883  if (dir != 0)
884    {
885      while ((entry = readdir (dir)) != 0)
886        {
887          //if (entry->d_name[0] == '.') continue;
888          if (!strcmp ((char*) entry->d_name, ".")) continue;
889          if (!strcmp ((char*) entry->d_name, "..")) continue;
890          if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
891
892          const char* name = entry->d_name;
893
894          if (!expression.match (name)) continue;
895
896          cmt_string& name_entry = list.add ();
897
898          name_entry = dir_prefix;
899          name_entry += file_separator ();
900          name_entry += name;
901        }
902
903      closedir (dir);
904    }
905#endif
906
907}
908
909//----------------------------------------------------------
910CmtSystem::cmt_string_vector& CmtSystem::scan_dir (const cmt_string& dir_name)
911{
912  static cmt_string_vector result;
913
914  scan_dir (dir_name, result);
915
916  return (result);
917}
918
919//----------------------------------------------------------
920const cmt_string& CmtSystem::get_cmt_root ()
921{
922  static cmt_string root;
923
924  root = "";
925
926  const char* env = ::getenv ("CMTROOT");
927  if (env != 0)
928    {
929      root = env;
930
931      dirname (root, root);
932      dirname (root, root);
933      root.replace_all ("\"", "");
934      return (root);
935    }
936
937#ifdef WIN32
938  LONG status;
939  HKEY key = 0;
940
941  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
942                         0, KEY_READ, &key);
943  if (status == ERROR_SUCCESS)
944    {
945      char temp[256];
946      DWORD length = sizeof (temp) - 1;
947      DWORD type;
948
949      status = RegQueryValueEx (key, "root", 0, &type, (LPBYTE) temp, &length);
950      if (status == ERROR_SUCCESS)
951        {
952          root = temp;
953          return (root);
954        }
955    }
956#endif
957
958  return (root);
959}
960
961//----------------------------------------------------------
962void CmtSystem::get_cmt_version (cmt_string& version)
963{
964  version = "";
965
966  const char* env = ::getenv ("CMTROOT");
967  if (env != 0)
968    {
969      cmt_string s = env;
970      basename (s, version);
971      version.replace_all ("\"", "");
972    }
973  else
974    {
975#ifdef WIN32
976      LONG status;
977      HKEY key = 0;
978
979      status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
980                             0, KEY_READ, &key);
981      if (status == ERROR_SUCCESS)
982        {
983          char temp[256];
984          DWORD length = sizeof (temp) - 1;
985          DWORD type;
986         
987          status = RegQueryValueEx (key, "version", 0, &type, 
988                                    (LPBYTE) temp, &length);
989          if (status == ERROR_SUCCESS)
990            {
991              version = temp;
992            }
993        }
994#endif
995    }
996}
997
998//----------------------------------------------------------
999cmt_string CmtSystem::get_cmt_config ()
1000{
1001  const char* env = ::getenv ("CMTCONFIG");
1002  if (env != 0)
1003    {
1004      return (cmt_string (env));
1005    }
1006
1007  env = ::getenv ("CMTBIN");
1008  if (env != 0)
1009    {
1010      return (cmt_string (env));
1011    }
1012
1013#ifdef WIN32
1014  LONG status;
1015  HKEY key = 0;
1016
1017  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
1018                         0, KEY_READ, &key);
1019  if (status == ERROR_SUCCESS)
1020    {
1021      char temp[256];
1022      DWORD length = sizeof (temp) - 1;
1023      DWORD type;
1024
1025      status = RegQueryValueEx (key, "config", 0, &type, 
1026                                (LPBYTE) temp, &length);
1027      if (status == ERROR_SUCCESS)
1028        {
1029          cmt_string config (temp);
1030          return (config);
1031        }
1032    }
1033
1034  return ("VisualC");
1035#endif
1036
1037  return ("");
1038
1039}
1040
1041//----------------------------------------------------------
1042cmt_string CmtSystem::get_cmt_site ()
1043{
1044  const char* env = ::getenv ("CMTSITE");
1045  if (env != 0)
1046    {
1047      return (cmt_string (env));
1048    }
1049
1050#ifdef WIN32
1051  LONG status;
1052  HKEY key = 0;
1053
1054  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
1055                         0, KEY_READ, &key);
1056  if (status == ERROR_SUCCESS)
1057    {
1058      char temp[256];
1059      DWORD length = sizeof (temp) - 1;
1060      DWORD type;
1061
1062      status = RegQueryValueEx (key, "site", 0, &type, (LPBYTE) temp, &length);
1063      if (status == ERROR_SUCCESS)
1064        {
1065          cmt_string site (temp);
1066          return (site);
1067        }
1068    }
1069#endif
1070
1071  return ("");
1072}
1073
1074//----------------------------------------------------------
1075void CmtSystem::get_uname (cmt_string& uname)
1076{
1077#ifdef WIN32
1078  uname = "WIN32";
1079#else
1080
1081  uname = "";
1082
1083  FILE* file;
1084
1085  file = popen ("uname", "r");
1086
1087  if (file != 0)
1088    {
1089      char line[1024];
1090      char* ptr;
1091      char* nl;
1092
1093      line[0] = 0;
1094      ptr = fgets (line, sizeof (line), file);
1095      if (ptr != 0)
1096        {
1097          nl = strrchr (ptr, '\n');
1098          if (nl != 0) *nl = 0;
1099
1100          uname = ptr;
1101        }
1102      pclose (file);
1103    }
1104#endif
1105}
1106
1107//----------------------------------------------------------
1108void CmtSystem::get_hosttype (cmt_string& hosttype)
1109{
1110  hosttype = "";
1111
1112  char* ptr;
1113
1114  ptr = ::getenv ("HOSTTYPE");
1115  if (ptr != 0)
1116    {
1117      hosttype = ptr;
1118    }
1119}
1120
1121//----------------------------------------------------------
1122cmt_string CmtSystem::get_temporary_name ()
1123{
1124  cmt_string name;
1125
1126  name = ::tmpnam (NULL);
1127
1128  return (name);
1129}
1130
1131//----------------------------------------------------------
1132cmt_string CmtSystem::get_home_package ()
1133{
1134  cmt_string name = "CMTHOME";
1135
1136  return (name);
1137}
1138
1139//----------------------------------------------------------
1140bool CmtSystem::is_home_package (const cmt_string& name,
1141                                 const cmt_string& version)
1142{
1143  if (name == "CMTHOME") return (true);
1144
1145  return (false);
1146}
1147
1148//----------------------------------------------------------
1149cmt_string CmtSystem::get_user_context_package ()
1150{
1151  cmt_string name = "CMTUSERCONTEXT";
1152
1153  return (name);
1154}
1155
1156//----------------------------------------------------------
1157bool CmtSystem::is_user_context_package (const cmt_string& name,
1158                                         const cmt_string& version)
1159{
1160  if (name == "CMTUSERCONTEXT") return (true);
1161
1162  return (false);
1163}
1164
1165//----------------------------------------------------------
1166cmt_string CmtSystem::get_project_package ()
1167{
1168  cmt_string name = "PROJECT";
1169
1170  return (name);
1171}
1172
1173//----------------------------------------------------------
1174bool CmtSystem::is_project_package (const cmt_string& name,
1175                                    const cmt_string& version)
1176{
1177  if (name == "PROJECT") return (true);
1178
1179  return (false);
1180}
1181
1182//----------------------------------------------------------
1183bool CmtSystem::testenv (const cmt_string& name)
1184{
1185  const char* env = ::getenv (name);
1186  if (env == 0) return (false);
1187  return (true);
1188}
1189
1190//----------------------------------------------------------
1191cmt_string CmtSystem::getenv (const cmt_string& name)
1192{
1193  cmt_string result;
1194
1195  const char* env = ::getenv (name);
1196  if (env != 0)
1197    {
1198      result = env;
1199    }
1200
1201  if (name == "CMTCONFIG")
1202  {
1203    return (get_cmt_config ());
1204  }
1205
1206  /*
1207  if (name == "CMTROOT")
1208  {
1209          return (get_cmt_root ());
1210  }
1211
1212  if (name == "CMTSITE")
1213  {
1214          return (get_cmt_site ());
1215  }
1216  */
1217
1218  return (result);
1219}
1220
1221//----------------------------------------------------------
1222bool CmtSystem::putenv (const cmt_string& name_value)
1223{
1224  int status = ::putenv ((char*) name_value.c_str ());
1225
1226  if (status == 0) return (true);
1227  else return (false);
1228}
1229
1230//----------------------------------------------------------
1231//
1232// This singleton interacts with the ProjectFactory to consistently create
1233// the project graph.
1234//
1235// In particular a single-depth stack of the top project is maintained.
1236//
1237//----------------------------------------------------------
1238class CMTPathManager
1239{
1240public:
1241  static CMTPathManager& instance ();
1242  static void reset ();
1243  static void add_cmt_path (const cmt_string& path,
1244                            const cmt_string& path_source,
1245                            IProjectFactory& factory);
1246
1247private:
1248  CMTPathManager () : m_project (0)
1249  {
1250  }
1251
1252  void do_reset ()
1253  {
1254    m_project = 0;
1255  }
1256
1257  void do_add_cmt_path (const cmt_string& path,
1258                        const cmt_string& path_source,
1259                        IProjectFactory& factory)
1260  {
1261    cmt_string npath = path;
1262
1263    if (npath == "") return;
1264
1265#ifdef WIN32
1266    if (npath.size () == 2)
1267      {
1268        if (npath[1] == ':')
1269          {
1270            npath += CmtSystem::file_separator ();
1271          }
1272      }
1273#endif
1274
1275    npath.replace_all ("\\", CmtSystem::file_separator ());
1276    npath.replace_all ("/", CmtSystem::file_separator ());
1277
1278    if (!CmtSystem::absolute_path (npath))
1279      {
1280        cmt_string h = CmtSystem::pwd ();
1281        h += CmtSystem::file_separator ();
1282        h += npath;
1283        npath = h;
1284      }
1285   
1286    CmtSystem::compress_path (npath);
1287
1288    //cerr << "adding npath=" << npath << endl;
1289
1290    while (npath[npath.size ()-1] == CmtSystem::file_separator ())
1291      {
1292        npath.erase (npath.size ()-1);
1293      }
1294   
1295    //cerr << "adding npath=[" << npath << "]" << endl;
1296   
1297    if (npath != "")
1298      {
1299        if (!CmtSystem::test_directory (npath))
1300          {
1301            CmtError::set (CmtError::path_not_found, npath);
1302            return;
1303          }
1304       
1305        m_project = factory.create_project ("", npath, path_source, m_project);
1306      }
1307  }
1308
1309  Project* m_project;
1310};
1311
1312CMTPathManager& CMTPathManager::instance ()
1313{
1314  static CMTPathManager me;
1315 
1316  return (me);
1317}
1318
1319void CMTPathManager::reset ()
1320{
1321  static CMTPathManager& me = instance ();
1322  me.do_reset ();
1323}
1324
1325void CMTPathManager::add_cmt_path (const cmt_string& path,
1326                                   const cmt_string& path_source,
1327                                   IProjectFactory& factory)
1328{
1329  static CMTPathManager& me = instance ();
1330  me.do_add_cmt_path (path, path_source, factory);
1331}
1332
1333
1334
1335//----------------------------------------------------------
1336static void add_cmt_paths_from_text (const cmt_string& text,
1337                                     const cmt_string& context,
1338                                     IProjectFactory& factory)
1339{
1340  static CmtSystem::cmt_string_vector path_vector;
1341  int i;
1342
1343  CmtSystem::split (text, CmtSystem::path_separator (), path_vector);
1344
1345  for (i = 0; i < path_vector.size (); i++)
1346    {
1347      const cmt_string& path = path_vector[i];
1348
1349      CMTPathManager::add_cmt_path (path, context, factory);
1350    }
1351}
1352
1353//----------------------------------------------------------
1354static void add_cmt_paths_from_file (const cmt_string& file_name, IProjectFactory& factory)
1355{
1356  if (!CmtSystem::test_file (file_name)) return;
1357
1358  static cmt_string text;
1359
1360  text.read (file_name);
1361
1362  int pos = text.find ("CMTPATH");
1363  if (pos == cmt_string::npos) return;
1364  pos += strlen ("CMTPATH");
1365  pos = text.find (pos, "=");
1366  if (pos == cmt_string::npos) return;
1367  pos++;
1368
1369  text.erase (0, pos);
1370
1371  int nl = text.find (pos, "\n");
1372  if (nl != cmt_string::npos) text.erase (nl);
1373
1374  add_cmt_paths_from_text (text, file_name, factory);
1375}
1376
1377//----------------------------------------------------------
1378//
1379// With this function we analyse all possible ways of
1380// externally entering CMTPATH items
1381//  + from the environment variable
1382//  + from .cmtrc files
1383//  + from registry on Windows
1384//  + from EV settings for CMTUSERCONTEXT and CMTHOME
1385//
1386// Then projects are created from these settings.
1387//
1388// (The other way to enter project graph is through project files)
1389//----------------------------------------------------------
1390void CmtSystem::get_cmt_paths (IProjectFactory& factory, 
1391                               const cmt_string& init_text,
1392                               const cmt_string& cmt_user_context,
1393                               const cmt_string& cmt_home)
1394{
1395  CMTPathManager::reset ();
1396
1397  if (init_text != "")
1398    {
1399      add_cmt_paths_from_text (init_text, "initialization", factory);
1400    }
1401
1402#ifdef WIN32
1403  LONG status;
1404  HKEY key = 0;
1405
1406  status = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\CMT\\path",
1407                         0, KEY_READ, &key);
1408  if (status == ERROR_SUCCESS)
1409    {
1410      DWORD index = 0;
1411      char name[256];
1412      char temp[256];
1413
1414      for (;;)
1415        {
1416          DWORD name_length = sizeof (name) - 1;
1417          DWORD length = sizeof (temp) - 1;
1418          DWORD type;
1419          status = RegEnumValue (key, index,
1420                                 name, &name_length, 0, &type,
1421                                 (LPBYTE) temp, &length);
1422          if ((status == ERROR_SUCCESS) ||
1423              (status == 234))
1424            {
1425              const cmt_string path = temp;
1426              CMTPathManager::add_cmt_path (path, "HKEY_CURRENT_USER", factory);
1427            }
1428
1429          if (status == 259)
1430            {
1431              break;
1432            }
1433
1434          index++;
1435        }
1436    }
1437
1438  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT\\path",
1439                         0, KEY_READ, &key);
1440  if (status == ERROR_SUCCESS)
1441    {
1442      DWORD index = 0;
1443      char name[256];
1444      char temp[256];
1445
1446      for (;;)
1447        {
1448          DWORD type;
1449          DWORD name_length = sizeof (name) - 1;
1450          DWORD length = sizeof (temp) - 1;
1451
1452
1453          status = RegEnumValue (key, index,
1454                                 name, &name_length, 0, &type,
1455                                 (LPBYTE) temp, &length);
1456          if (status != ERROR_NO_MORE_ITEMS)
1457            {
1458              const cmt_string path = temp;
1459              CMTPathManager::add_cmt_path (path, "HKEY_LOCAL_MACHINE", factory);
1460            }
1461          else
1462            {
1463              break;
1464            }
1465          index++;
1466        }
1467    }
1468
1469#endif
1470
1471  //-----------------------------------------
1472  // look for .cmtrc files :
1473  //  first look in ./
1474  //  then in "~/"
1475  //  then in ${CMTROOT}/mgr
1476  //-----------------------------------------
1477  cmt_string rc_name;
1478
1479  add_cmt_paths_from_file (".cmtrc", factory);
1480
1481  if (get_home_directory (rc_name))
1482    {
1483      rc_name += file_separator ();
1484      rc_name += ".cmtrc";
1485      add_cmt_paths_from_file (rc_name, factory);
1486    }
1487
1488  rc_name = get_cmt_root ();
1489  rc_name += file_separator ();
1490  rc_name += "CMT";
1491  rc_name += file_separator ();
1492  cmt_string version;
1493  get_cmt_version (version);
1494  rc_name += version;
1495  rc_name += file_separator ();
1496  rc_name += "mgr";
1497  rc_name += file_separator ();
1498  rc_name += ".cmtrc";
1499
1500  add_cmt_paths_from_file (rc_name, factory);
1501
1502  CMTPathManager::add_cmt_path (cmt_user_context, "CMTUSERCONTEXT", factory);
1503  CMTPathManager::add_cmt_path (cmt_home, "CMTHOME", factory);
1504}
1505
1506//----------------------------------------------------------
1507int CmtSystem::execute (const cmt_string& command)
1508{
1509  //cout << "CmtSystem::execute1> [" << command << "]" << endl;
1510
1511  return (system (command.c_str ()));
1512}
1513
1514//----------------------------------------------------------
1515int CmtSystem::execute (const cmt_string& command, cmt_string& output)
1516{
1517  output = "";
1518
1519  //cout << "CmtSystem::execute2> [" << command << "]" << endl;
1520
1521  FILE* f = popen (command.c_str (), "r"); 
1522 
1523  if (f != 0) 
1524    { 
1525      char line[256]; 
1526      char* ptr;
1527
1528      while ((ptr = fgets (line, sizeof (line), f)) != NULL) 
1529        {
1530          output += ptr;
1531        } 
1532      pclose (f);
1533
1534      return (0);
1535    }
1536
1537  return (1);
1538}
1539
1540//----------------------------------------------------------
1541bool CmtSystem::is_package_directory (const cmt_string& name)
1542{
1543  cmt_string_vector dirs;
1544
1545  cmt_regexp exp ("^[a-zA-Z.][0-9]+([a-zA-Z.][0-9]+([a-zA-Z.][0-9]+)?)?");
1546
1547  scan_dir (name, exp, dirs);
1548
1549  cmt_string req;
1550
1551  req = name;
1552  req += file_separator ();
1553  req += "cmt";
1554  req += file_separator ();
1555  req += "requirements";
1556
1557  if (test_file (req)) return (true);
1558
1559  if (dirs.size () == 0) 
1560    {
1561      return (false);
1562    }
1563
1564  for (int i = 0; i < dirs.size (); i++)
1565      {
1566        const cmt_string& d = dirs[i];
1567
1568        req = d;
1569        req += file_separator ();
1570        req += "mgr";
1571        req += file_separator ();
1572        req += "requirements";
1573
1574        if (test_file (req)) return (true);
1575
1576      req = d;
1577      req += file_separator ();
1578      req += "cmt";
1579      req += file_separator ();
1580      req += "requirements";
1581     
1582      if (test_file (req)) return (true);
1583    }
1584
1585  return (false);
1586}
1587
1588//----------------------------------------------------------
1589bool CmtSystem::is_version_directory (const cmt_string& name)
1590{
1591  int v;
1592  int r;
1593  int p;
1594
1595  return (is_version_directory (name, v, r, p));
1596}
1597
1598//----------------------------------------------------------
1599bool CmtSystem::is_version_directory (const cmt_string& name,
1600                                      int& v,
1601                                      int& r,
1602                                      int& p)
1603{
1604  if ((name == "HEAD") || (name == "head"))
1605    {
1606      v = 0;
1607      r = 0;
1608      p = 0;
1609
1610      return (true);
1611    }
1612
1613  static const cmt_string numbers = "0123456789";
1614
1615  static const int id_version = 0;
1616  static const int id_release = 1;
1617  static const int id_patch   = 2;
1618
1619  cmt_string buffer;
1620
1621  enum 
1622  {
1623    starting,
1624    at_key,
1625    at_number
1626  } state;
1627
1628  int id;
1629  int pos;
1630  int value;
1631
1632  v = 0;
1633  r = 0;
1634  p = 0;
1635
1636  //
1637  // version : v-field
1638  //         | v-field r-field
1639  //         | v-field r-field p-field
1640  //
1641  // v-field : field
1642  // r-field : field
1643  // p-field : field
1644  //
1645  // field   : key '*'
1646  //         | key number
1647  //
1648  // key     : letters
1649  //
1650
1651  state = starting;
1652  id    = id_version;
1653
1654  for (pos = 0; pos < name.size (); pos++)
1655    {
1656      char c = name[pos];
1657
1658      if (c == '*')
1659        {
1660          // A wild card
1661          switch (state)
1662            {
1663            case starting:
1664              // cannot start with a wild card ??
1665              v = -1;
1666              r = -1;
1667              p = -1;
1668              return (false);
1669            case at_key:
1670              // the numeric field is valued with a wild card
1671              switch (id)
1672                {
1673                case id_version:
1674                  v = -1;
1675                case id_release:
1676                  r = -1;
1677                case id_patch:
1678                  p = -1;
1679                  break;
1680                }
1681              return (true);
1682            case at_number:
1683              // question:
1684              // a number followed by a wild-card is considered as:
1685              //   1) a wild card on the number itself (1* comp with 1, 10, 12, 120, etc)
1686              //   2) a wild card on the next fields (1* comp with 1r1, 1-12 etc)
1687              //
1688
1689              //  Here we select option 1)
1690
1691              sscanf (buffer.c_str (), "%d", &value);
1692              switch (id)
1693                {
1694                case id_version:
1695                  //
1696                  // lazy option 1 implies v = -1;
1697                  // strict option 1 would imply v = -value;
1698                  // option 2 implies v = value;
1699                  //
1700
1701                  v = -1;
1702                  r = -1;
1703                  p = -1;
1704                  break;
1705                case id_release:
1706                  r = value;
1707                  p = -1;
1708                  break;
1709                case id_patch:
1710                  p = value;
1711                  break;
1712                }
1713
1714              return (true);
1715            }
1716        }
1717      else if (numbers.find (c) == cmt_string::npos)
1718        {
1719          // A letter
1720          switch (state)
1721            {
1722            case starting:
1723              state = at_key;
1724              break;
1725            case at_key:
1726              // Multiple letter key (is it permitted??)
1727              break;
1728            case at_number:
1729              sscanf (buffer.c_str (), "%d", &value);
1730              switch (id)
1731                {
1732                case id_version:
1733                  v = value;
1734                  break;
1735                case id_release:
1736                  r = value;
1737                  break;
1738                case id_patch:
1739                  p = value;
1740                  break;
1741                }
1742              buffer = "";
1743              id++;
1744              state = at_key;
1745              break;
1746            }
1747        }
1748      else
1749        {
1750          // a number
1751          switch (state)
1752            {
1753            case starting:
1754              // not starting by a letter (syntax error)
1755              return (false);
1756            case at_key:
1757              // the numeric field for the current id is starting now
1758              buffer += c;
1759              state = at_number;
1760              break;
1761            case at_number:
1762              // continuing the current numeric field
1763              buffer += c;
1764              break;
1765            }
1766        }
1767    }
1768
1769  switch (state)
1770    {
1771    case starting:
1772      // Empty version string
1773      return (false);
1774    case at_key:
1775      // Syntax error (when only letters. Ending letters is not an error)
1776      if (id == id_version) return (false);
1777      else return (true);
1778    case at_number:
1779      sscanf (buffer.c_str (), "%d", &value);
1780      switch (id)
1781        {
1782        case id_version:
1783          v = value;
1784          break;
1785        case id_release:
1786          r = value;
1787          break;
1788        case id_patch:
1789          p = value;
1790          break;
1791        }
1792      id++;
1793      state = at_key;
1794      return (true);
1795    }
1796
1797  return (false);
1798}
1799
1800//----------------------------------------------------------
1801//  Split a line into words. Separators are spaces and tabs
1802//  Text enclosed in double quotes is one word.
1803//----------------------------------------------------------
1804void CmtSystem::split (const cmt_string& text,
1805                       const cmt_string& separators,
1806                       cmt_string_vector& strings)
1807{
1808  static char* buffer = 0;
1809  static int allocated = 0;
1810
1811  bool finished = false;
1812
1813  strings.clear ();
1814
1815  if (text.size () == 0) return;
1816
1817  /*
1818    We are going to work in a copy of the text, since
1819    \0 will be inserted right after each found word.
1820
1821    Then the vector of strings is iteratively filled by each found word.
1822  */
1823
1824  if (buffer == 0)
1825    {
1826      allocated = text.size ();
1827      buffer = (char*) malloc (allocated + 1);
1828    }
1829  else
1830    {
1831      if (text.size () > allocated)
1832        {
1833          allocated = text.size ();
1834          buffer = (char*) realloc (buffer, allocated + 1);
1835        }
1836    }
1837
1838  strcpy (buffer, text.c_str ());
1839
1840  /*
1841    Algorithm :
1842
1843    We look for words separated by <separators> which may be
1844    o spaces (' ' or '\t')
1845    o other characters such as ':'
1846
1847    A word is a character string not containing any separator. A substring in
1848    this word my be enclosed between quotes (" or ') which permits separator
1849    inclusion within words.
1850  */
1851
1852  char* current_word = buffer;
1853
1854  while (*current_word != 0)
1855    {
1856      size_t prefix_length;
1857      size_t word_length;
1858
1859      /*
1860        while ((*current_word == ' ') ||
1861        (*current_word == '\t'))
1862        {
1863        current_word++;
1864        }
1865      */
1866
1867      // first skip all starting separators.
1868
1869      prefix_length = strspn (current_word, separators.c_str ());
1870      if (prefix_length > 0)
1871        {
1872          // Move to the first non-separator character
1873
1874          current_word += prefix_length;
1875        }
1876
1877      /*
1878        Parse the next word.
1879
1880        It may contain enclosures in quote characters or not.
1881        Quotes must be identical on both sides of each enclosure.
1882      */
1883
1884      char* running_char = current_word;
1885
1886      word_length = 0;
1887
1888      for (;;)
1889        {
1890          size_t unquoted_length;
1891          size_t separator_offset;
1892
1893          for (int p = 0;;)
1894            {
1895              unquoted_length = strcspn (running_char + p, "\"\'") + p;
1896              if ((unquoted_length > 0) && (running_char[unquoted_length-1] == '\\'))
1897                {
1898                  p = unquoted_length + 1;
1899                }
1900              else
1901                {
1902                  break;
1903                }
1904            }
1905
1906          separator_offset = strcspn (running_char, separators.c_str ());
1907
1908          if (separator_offset <= unquoted_length)
1909            {
1910              // no quote in this word -> we are finished for this one.
1911              running_char += separator_offset;
1912              break;
1913            }
1914
1915          // We have found a quoted enclosure. Move to it.
1916
1917          running_char += unquoted_length;
1918
1919          char quote = running_char[0];
1920
1921          // Remove it.
1922          {
1923            char* p = running_char;
1924            while (p[1] != 0)
1925              {
1926                *p = p[1];
1927                p++;
1928              }
1929            *p = 0;
1930          }
1931
1932          // Look for the next occurence of this quote.
1933          {
1934            char* p = strchr (running_char, quote);
1935            if (p == 0)
1936              {
1937                // Unmatched quote : the rest of the line will be taken as a word...
1938                running_char += strlen (running_char);
1939                finished = true;
1940                break;
1941              }
1942            else
1943              {
1944                running_char = p;
1945              }
1946          }
1947
1948          // Now we remove the ending quote from the word
1949          // (by shifting all remaining characters by one place to the left)
1950
1951          {
1952            char* p = running_char;
1953            while (p[1] != 0)
1954              {
1955                *p = p[1];
1956                p++;
1957              }
1958            *p = 0;
1959          }
1960        }
1961
1962      word_length = running_char - current_word;
1963
1964      if (current_word[word_length] == 0)
1965        {
1966          finished = true;
1967        }
1968      else
1969        {
1970          current_word[word_length] = 0;
1971        }
1972
1973      /*
1974        if ((t[0] == '"') ||
1975        (t[0] == '\'') ||
1976        (t[0] == ':'))
1977        {
1978        char* quote;
1979
1980        t++;
1981        quote = strchr (t, sep);
1982        if (quote != 0) *quote = 0;
1983        else finished = true;
1984        }
1985        else
1986        {
1987        int offset;
1988
1989        offset = strcspn (t, " \t:");
1990        if ((offset < 0) || (t[offset] == 0)) finished = true;
1991        if (!finished)
1992        {
1993        space = t + offset;
1994        *space = 0;
1995        }
1996        }
1997      */
1998
1999      // Store the current word into the vector of strings
2000
2001      {
2002        cmt_string& s = strings.add ();
2003        s = current_word;
2004      }
2005
2006      if (finished) break;
2007
2008      // Move to the next possible word.
2009      current_word += word_length + 1;
2010    }
2011}
2012
2013//----------------------------------------------------------
2014void CmtSystem::compress_path (const cmt_string& dir, cmt_string& new_dir)
2015{
2016  new_dir = dir;
2017
2018  compress_path (new_dir);
2019}
2020
2021//----------------------------------------------------------
2022//
2023//  We try to detect the aaaa/xxxx/../bbbb patterns which should be
2024// equivalent to aaaa/bbbb
2025//  this therefore consists in removing all /xxxx/../ when
2026//     xxxx is different from ".."
2027//     xxxx is different from "."
2028//     xxxx does not contain any macro reference
2029//
2030//----------------------------------------------------------
2031void CmtSystem::compress_path (cmt_string& dir)
2032{
2033#ifdef WIN32
2034  static const char pattern[] = "\\..";
2035  static const char fs[] = "\\\\";
2036#else
2037  static const char pattern[] = "/..";
2038  static const char fs[] = "//";
2039#endif
2040
2041  if (dir.size () == 0) return;
2042
2043  //
2044  // We first synchronize to using file_separator() in any case.
2045  //
2046
2047  if (file_separator () == '/')
2048    {
2049      dir.replace_all ("\\", file_separator ());
2050    }
2051  else
2052    {
2053      dir.replace_all ("/", file_separator ());
2054    }
2055
2056  // Suppress all duplicated file separators
2057  dir.replace_all (fs, file_separator ());
2058
2059  for (;;)
2060    {
2061      int pos1;
2062      int pos2;
2063      int pos3;
2064
2065      pos1 = dir.find (pattern);
2066      if (pos1 == cmt_string::npos) break;
2067
2068        //
2069        // extract "aaaa/xxxx" from "aaaa/xxxx/../bbbb"
2070        //
2071      cmt_string p = dir.substr (0, pos1);
2072
2073      cmt_string dn;
2074      basename (p, dn);
2075      if (dn == "..") break;
2076      if (dn == ".") break;
2077      if (dn == "") break;
2078     
2079        //
2080        // Is "aaaa/xxxx" only made of "xxxx" ?
2081        //
2082      pos2 = p.find_last_of (file_separator ());
2083     
2084      if (pos2 == cmt_string::npos) 
2085        {
2086          // the pattern was xxxx/..
2087          //
2088          // so xxxx is [0:pos1-1]
2089          //
2090          pos3 = p.find ("$");
2091          if (pos3 == cmt_string::npos)
2092            {
2093              dir.erase (0, pos1 + 3);
2094            }
2095          else
2096            {
2097              break;
2098            }
2099        }
2100      else
2101        {
2102          //    01234567890123456
2103          //    aaaa/xxxx/../bbbb
2104          //        2    1   3
2105          //
2106          // erase the "/xxxx/.." pattern
2107          // result will be "aaaa/bbbb"
2108          //
2109          // Here xxxx is [pos2+1:pos1-1]
2110          //
2111
2112          pos3 = p.find (pos2, "$");
2113          if (pos3 == cmt_string::npos)
2114            {
2115              dir.erase (pos2, pos1 + 3 - pos2);
2116            }
2117          else
2118            {
2119              break;
2120            }
2121        }
2122    }
2123
2124    //if (dir[dir.size () - 1] == file_separator ()) dir.erase (dir.size () - 1);
2125}
2126
2127//----------------------------------------------------------
2128cmt_string CmtSystem::now ()
2129{
2130  cmt_string result;
2131
2132  time_t ltime;
2133  time (&ltime);
2134  result = ctime (&ltime);
2135
2136  result.replace_all ("\n", "");
2137
2138  return (result);
2139}
2140
2141//----------------------------------------------------------
2142cmt_string CmtSystem::user ()
2143{
2144#ifdef _WIN32
2145  cmt_string result = getenv ("USERNAME");
2146#else
2147  cmt_string result = getenv ("USER");
2148#endif
2149
2150  return (result);
2151}
2152
2153//----------------------------------------------------------
2154void CmtSystem::get_cvsroot (cmt_string& cvsroot)
2155{
2156  cvsroot = "";
2157
2158  const char* env = ::getenv ("CVSROOT");
2159  if (env != 0)
2160    {
2161      cvsroot = env;
2162      return;
2163    }
2164
2165#ifdef WIN32
2166  LONG status;
2167  HKEY key = 0;
2168
2169  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
2170                         0, KEY_READ, &key);
2171  if (status == ERROR_SUCCESS)
2172    {
2173      char temp[256];
2174      DWORD length = sizeof (temp) - 1;
2175      DWORD type;
2176
2177      status = RegQueryValueEx (key, "CVSROOT", 0, &type, 
2178                                (LPBYTE) temp, &length);
2179      if (status == ERROR_SUCCESS)
2180        {
2181          cvsroot = temp;
2182          return;
2183        }
2184    }
2185#endif
2186}
2187
2188//----------------------------------------------------------
2189bool CmtSystem::get_home_directory (cmt_string& dir)
2190{
2191  bool status = false;
2192
2193#ifdef WIN32
2194  const char* homedrive = ::getenv ("HOMEDRIVE");
2195  const char* homepath = ::getenv ("HOMEPATH");
2196
2197  if ((homedrive != 0) && (homepath != 0))
2198    {
2199      dir = homedrive;
2200      dir += homepath;
2201      status = true;
2202    }
2203
2204#else
2205  const char* home_env = ::getenv ("HOME");
2206  if (home_env != 0)
2207    {
2208      dir = home_env;
2209      status = true;
2210    }
2211#endif
2212
2213  return (status);
2214}
2215
Note: See TracBrowser for help on using the repository browser.