source: CMT/v1r19/source/cmt_system.cxx @ 11

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

Changing eol-style property

  • Property svn:eol-style set to native
File size: 46.4 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  const cmt_string env = CmtSystem::getenv ("CMTPATH");
1480
1481  if (env != "")
1482    {
1483      static cmt_string_vector path_vector;
1484      int i;
1485
1486      split (env, path_separator (), path_vector);
1487
1488      for (i = 0; i < path_vector.size (); i++)
1489        {
1490          const cmt_string& path = path_vector[i];
1491
1492          CMTPathManager::add_cmt_path (path, "${CMTPATH}", factory);
1493        }
1494    }
1495
1496  add_cmt_paths_from_file (".cmtrc", factory);
1497
1498  if (get_home_directory (rc_name))
1499    {
1500      rc_name += file_separator ();
1501      rc_name += ".cmtrc";
1502      add_cmt_paths_from_file (rc_name, factory);
1503    }
1504
1505  rc_name = get_cmt_root ();
1506  rc_name += file_separator ();
1507  rc_name += "CMT";
1508  rc_name += file_separator ();
1509  cmt_string version;
1510  get_cmt_version (version);
1511  rc_name += version;
1512  rc_name += file_separator ();
1513  rc_name += "mgr";
1514  rc_name += file_separator ();
1515  rc_name += ".cmtrc";
1516
1517  add_cmt_paths_from_file (rc_name, factory);
1518
1519  // Suppress the definition of a CMTPATH entry for CMT itself
1520  //CMTPathManager::add_cmt_path (get_cmt_root (), "default path", factory);
1521
1522  CMTPathManager::add_cmt_path (cmt_user_context, "CMTUSERCONTEXT", factory);
1523  CMTPathManager::add_cmt_path (cmt_home, "CMTHOME", factory);
1524}
1525
1526//----------------------------------------------------------
1527int CmtSystem::execute (const cmt_string& command)
1528{
1529  //cout << "CmtSystem::execute1> [" << command << "]" << endl;
1530
1531  return (system (command.c_str ()));
1532}
1533
1534//----------------------------------------------------------
1535int CmtSystem::execute (const cmt_string& command, cmt_string& output)
1536{
1537  output = "";
1538
1539  //cout << "CmtSystem::execute2> [" << command << "]" << endl;
1540
1541  FILE* f = popen (command.c_str (), "r"); 
1542 
1543  if (f != 0) 
1544    { 
1545      char line[256]; 
1546      char* ptr;
1547
1548      while ((ptr = fgets (line, sizeof (line), f)) != NULL) 
1549        {
1550          output += ptr;
1551        } 
1552      pclose (f);
1553
1554      return (0);
1555    }
1556
1557  return (1);
1558}
1559
1560//----------------------------------------------------------
1561bool CmtSystem::is_package_directory (const cmt_string& name)
1562{
1563  cmt_string_vector dirs;
1564
1565  cmt_regexp exp ("^[a-zA-Z.][0-9]+([a-zA-Z.][0-9]+([a-zA-Z.][0-9]+)?)?");
1566
1567  scan_dir (name, exp, dirs);
1568
1569  cmt_string req;
1570
1571  req = name;
1572  req += file_separator ();
1573  req += "cmt";
1574  req += file_separator ();
1575  req += "requirements";
1576
1577  if (test_file (req)) return (true);
1578
1579  if (dirs.size () == 0) 
1580    {
1581      return (false);
1582    }
1583
1584  for (int i = 0; i < dirs.size (); i++)
1585      {
1586        const cmt_string& d = dirs[i];
1587
1588        req = d;
1589        req += file_separator ();
1590        req += "mgr";
1591        req += file_separator ();
1592        req += "requirements";
1593
1594        if (test_file (req)) return (true);
1595
1596      req = d;
1597      req += file_separator ();
1598      req += "cmt";
1599      req += file_separator ();
1600      req += "requirements";
1601     
1602      if (test_file (req)) return (true);
1603    }
1604
1605  return (false);
1606}
1607
1608//----------------------------------------------------------
1609bool CmtSystem::is_version_directory (const cmt_string& name)
1610{
1611  int v;
1612  int r;
1613  int p;
1614
1615  return (is_version_directory (name, v, r, p));
1616}
1617
1618//----------------------------------------------------------
1619bool CmtSystem::is_version_directory (const cmt_string& name,
1620                                      int& v,
1621                                      int& r,
1622                                      int& p)
1623{
1624  static const cmt_string numbers = "0123456789";
1625
1626  static const int id_version = 0;
1627  static const int id_release = 1;
1628  static const int id_patch   = 2;
1629
1630  cmt_string buffer;
1631
1632  enum 
1633  {
1634    starting,
1635    at_key,
1636    at_number
1637  } state;
1638
1639  int id;
1640  int pos;
1641  int value;
1642
1643  v = 0;
1644  r = 0;
1645  p = 0;
1646
1647  //
1648  // version : v-field
1649  //         | v-field r-field
1650  //         | v-field r-field p-field
1651  //
1652  // v-field : field
1653  // r-field : field
1654  // p-field : field
1655  //
1656  // field   : key '*'
1657  //         | key number
1658  //
1659  // key     : letters
1660  //
1661
1662  state = starting;
1663  id    = id_version;
1664
1665  for (pos = 0; pos < name.size (); pos++)
1666    {
1667      char c = name[pos];
1668
1669      if (c == '*')
1670        {
1671          // A wild card
1672          switch (state)
1673            {
1674            case starting:
1675              // cannot start with a wild card ??
1676              v = -1;
1677              r = -1;
1678              p = -1;
1679              return (false);
1680            case at_key:
1681              // the numeric field is valued with a wild card
1682              switch (id)
1683                {
1684                case id_version:
1685                  v = -1;
1686                case id_release:
1687                  r = -1;
1688                case id_patch:
1689                  p = -1;
1690                  break;
1691                }
1692              return (true);
1693            case at_number:
1694              // question:
1695              // a number followed by a wild-card is considered as:
1696              //   1) a wild card on the number itself (1* comp with 1, 10, 12, 120, etc)
1697              //   2) a wild card on the next fields (1* comp with 1r1, 1-12 etc)
1698              //
1699
1700              //  Here we select option 1)
1701
1702              sscanf (buffer.c_str (), "%d", &value);
1703              switch (id)
1704                {
1705                case id_version:
1706                  //
1707                  // lazy option 1 implies v = -1;
1708                  // strict option 1 would imply v = -value;
1709                  // option 2 implies v = value;
1710                  //
1711
1712                  v = -1;
1713                  r = -1;
1714                  p = -1;
1715                  break;
1716                case id_release:
1717                  r = value;
1718                  p = -1;
1719                  break;
1720                case id_patch:
1721                  p = value;
1722                  break;
1723                }
1724
1725              return (true);
1726            }
1727        }
1728      else if (numbers.find (c) == cmt_string::npos)
1729        {
1730          // A letter
1731          switch (state)
1732            {
1733            case starting:
1734              state = at_key;
1735              break;
1736            case at_key:
1737              // Multiple letter key (is it permitted??)
1738              break;
1739            case at_number:
1740              sscanf (buffer.c_str (), "%d", &value);
1741              switch (id)
1742                {
1743                case id_version:
1744                  v = value;
1745                  break;
1746                case id_release:
1747                  r = value;
1748                  break;
1749                case id_patch:
1750                  p = value;
1751                  break;
1752                }
1753              buffer = "";
1754              id++;
1755              state = at_key;
1756              break;
1757            }
1758        }
1759      else
1760        {
1761          // a number
1762          switch (state)
1763            {
1764            case starting:
1765              // not starting by a letter (syntax error)
1766              return (false);
1767            case at_key:
1768              // the numeric field for the current id is starting now
1769              buffer += c;
1770              state = at_number;
1771              break;
1772            case at_number:
1773              // continuing the current numeric field
1774              buffer += c;
1775              break;
1776            }
1777        }
1778    }
1779
1780  switch (state)
1781    {
1782    case starting:
1783      // Empty version string
1784      return (false);
1785    case at_key:
1786      // Syntax error (when only letters. Ending letters is not an error)
1787      if (id == id_version) return (false);
1788      else return (true);
1789    case at_number:
1790      sscanf (buffer.c_str (), "%d", &value);
1791      switch (id)
1792        {
1793        case id_version:
1794          v = value;
1795          break;
1796        case id_release:
1797          r = value;
1798          break;
1799        case id_patch:
1800          p = value;
1801          break;
1802        }
1803      id++;
1804      state = at_key;
1805      return (true);
1806    }
1807
1808  return (false);
1809}
1810
1811//----------------------------------------------------------
1812//  Split a line into words. Separators are spaces and tabs
1813//  Text enclosed in double quotes is one word.
1814//----------------------------------------------------------
1815void CmtSystem::split (const cmt_string& text,
1816                       const cmt_string& separators,
1817                       cmt_string_vector& strings)
1818{
1819  static char* buffer = 0;
1820  static int allocated = 0;
1821
1822  bool finished = false;
1823
1824  strings.clear ();
1825
1826  if (text.size () == 0) return;
1827
1828  /*
1829    We are going to work in a copy of the text, since
1830    \0 will be inserted right after each found word.
1831
1832    Then the vector of strings is iteratively filled by each found word.
1833  */
1834
1835  if (buffer == 0)
1836    {
1837      allocated = text.size ();
1838      buffer = (char*) malloc (allocated + 1);
1839    }
1840  else
1841    {
1842      if (text.size () > allocated)
1843        {
1844          allocated = text.size ();
1845          buffer = (char*) realloc (buffer, allocated + 1);
1846        }
1847    }
1848
1849  strcpy (buffer, text.c_str ());
1850
1851  /*
1852    Algorithm :
1853
1854    We look for words separated by <separators> which may be
1855    o spaces (' ' or '\t')
1856    o other characters such as ':'
1857
1858    A word is a character string not containing any separator. A substring in
1859    this word my be enclosed between quotes (" or ') which permits separator
1860    inclusion within words.
1861  */
1862
1863  char* current_word = buffer;
1864
1865  while (*current_word != 0)
1866    {
1867      size_t prefix_length;
1868      size_t word_length;
1869
1870      /*
1871        while ((*current_word == ' ') ||
1872        (*current_word == '\t'))
1873        {
1874        current_word++;
1875        }
1876      */
1877
1878      // first skip all starting separators.
1879
1880      prefix_length = strspn (current_word, separators.c_str ());
1881      if (prefix_length > 0)
1882        {
1883          // Move to the first non-separator character
1884
1885          current_word += prefix_length;
1886        }
1887
1888      /*
1889        Parse the next word.
1890
1891        It may contain enclosures in quote characters or not.
1892        Quotes must be identical on both sides of each enclosure.
1893      */
1894
1895      char* running_char = current_word;
1896
1897      word_length = 0;
1898
1899      for (;;)
1900        {
1901          size_t unquoted_length;
1902          size_t separator_offset;
1903
1904          for (int p = 0;;)
1905            {
1906              unquoted_length = strcspn (running_char + p, "\"\'") + p;
1907              if ((unquoted_length > 0) && (running_char[unquoted_length-1] == '\\'))
1908                {
1909                  p = unquoted_length + 1;
1910                }
1911              else
1912                {
1913                  break;
1914                }
1915            }
1916
1917          separator_offset = strcspn (running_char, separators.c_str ());
1918
1919          if (separator_offset <= unquoted_length)
1920            {
1921              // no quote in this word -> we are finished for this one.
1922              running_char += separator_offset;
1923              break;
1924            }
1925
1926          // We have found a quoted enclosure. Move to it.
1927
1928          running_char += unquoted_length;
1929
1930          char quote = running_char[0];
1931
1932          // Remove it.
1933          {
1934            char* p = running_char;
1935            while (p[1] != 0)
1936              {
1937                *p = p[1];
1938                p++;
1939              }
1940            *p = 0;
1941          }
1942
1943          // Look for the next occurence of this quote.
1944          {
1945            char* p = strchr (running_char, quote);
1946            if (p == 0)
1947              {
1948                // Unmatched quote : the rest of the line will be taken as a word...
1949                running_char += strlen (running_char);
1950                finished = true;
1951                break;
1952              }
1953            else
1954              {
1955                running_char = p;
1956              }
1957          }
1958
1959          // Now we remove the ending quote from the word
1960          // (by shifting all remaining characters by one place to the left)
1961
1962          {
1963            char* p = running_char;
1964            while (p[1] != 0)
1965              {
1966                *p = p[1];
1967                p++;
1968              }
1969            *p = 0;
1970          }
1971        }
1972
1973      word_length = running_char - current_word;
1974
1975      if (current_word[word_length] == 0)
1976        {
1977          finished = true;
1978        }
1979      else
1980        {
1981          current_word[word_length] = 0;
1982        }
1983
1984      /*
1985        if ((t[0] == '"') ||
1986        (t[0] == '\'') ||
1987        (t[0] == ':'))
1988        {
1989        char* quote;
1990
1991        t++;
1992        quote = strchr (t, sep);
1993        if (quote != 0) *quote = 0;
1994        else finished = true;
1995        }
1996        else
1997        {
1998        int offset;
1999
2000        offset = strcspn (t, " \t:");
2001        if ((offset < 0) || (t[offset] == 0)) finished = true;
2002        if (!finished)
2003        {
2004        space = t + offset;
2005        *space = 0;
2006        }
2007        }
2008      */
2009
2010      // Store the current word into the vector of strings
2011
2012      {
2013        cmt_string& s = strings.add ();
2014        s = current_word;
2015      }
2016
2017      if (finished) break;
2018
2019      // Move to the next possible word.
2020      current_word += word_length + 1;
2021    }
2022}
2023
2024//----------------------------------------------------------
2025void CmtSystem::compress_path (const cmt_string& dir, cmt_string& new_dir)
2026{
2027  new_dir = dir;
2028
2029  compress_path (new_dir);
2030}
2031
2032//----------------------------------------------------------
2033//
2034//  We try to detect the aaaa/xxxx/../bbbb patterns which should be
2035// equivalent to aaaa/bbbb
2036//  this therefore consists in removing all /xxxx/../ when
2037//     xxxx is different from ".."
2038//     xxxx is different from "."
2039//     xxxx does not contain any macro reference
2040//
2041//----------------------------------------------------------
2042void CmtSystem::compress_path (cmt_string& dir)
2043{
2044#ifdef WIN32
2045  static const char pattern[] = "\\..";
2046  static const char fs[] = "\\\\";
2047#else
2048  static const char pattern[] = "/..";
2049  static const char fs[] = "//";
2050#endif
2051
2052  if (dir.size () == 0) return;
2053
2054  //
2055  // We first synchronize to using file_separator() in any case.
2056  //
2057
2058  if (file_separator () == '/')
2059    {
2060      dir.replace_all ("\\", file_separator ());
2061    }
2062  else
2063    {
2064      dir.replace_all ("/", file_separator ());
2065    }
2066
2067  // Suppress all duplicated file separators
2068  dir.replace_all (fs, file_separator ());
2069
2070  for (;;)
2071    {
2072      int pos1;
2073      int pos2;
2074      int pos3;
2075
2076      pos1 = dir.find (pattern);
2077      if (pos1 == cmt_string::npos) break;
2078
2079        //
2080        // extract "aaaa/xxxx" from "aaaa/xxxx/../bbbb"
2081        //
2082      cmt_string p = dir.substr (0, pos1);
2083
2084      cmt_string dn;
2085      basename (p, dn);
2086      if (dn == "..") break;
2087      if (dn == ".") break;
2088      if (dn == "") break;
2089     
2090        //
2091        // Is "aaaa/xxxx" only made of "xxxx" ?
2092        //
2093      pos2 = p.find_last_of (file_separator ());
2094     
2095      if (pos2 == cmt_string::npos) 
2096        {
2097          // the pattern was xxxx/..
2098          //
2099          // so xxxx is [0:pos1-1]
2100          //
2101          pos3 = p.find ("$");
2102          if (pos3 == cmt_string::npos)
2103            {
2104              dir.erase (0, pos1 + 3);
2105            }
2106          else
2107            {
2108              break;
2109            }
2110        }
2111      else
2112        {
2113          //    01234567890123456
2114          //    aaaa/xxxx/../bbbb
2115          //        2    1   3
2116          //
2117          // erase the "/xxxx/.." pattern
2118          // result will be "aaaa/bbbb"
2119          //
2120          // Here xxxx is [pos2+1:pos1-1]
2121          //
2122
2123          pos3 = p.find (pos2, "$");
2124          if (pos3 == cmt_string::npos)
2125            {
2126              dir.erase (pos2, pos1 + 3 - pos2);
2127            }
2128          else
2129            {
2130              break;
2131            }
2132        }
2133    }
2134
2135    //if (dir[dir.size () - 1] == file_separator ()) dir.erase (dir.size () - 1);
2136}
2137
2138//----------------------------------------------------------
2139cmt_string CmtSystem::now ()
2140{
2141  cmt_string result;
2142
2143  time_t ltime;
2144  time (&ltime);
2145  result = ctime (&ltime);
2146
2147  result.replace_all ("\n", "");
2148
2149  return (result);
2150}
2151
2152//----------------------------------------------------------
2153cmt_string CmtSystem::user ()
2154{
2155#ifdef _WIN32
2156  cmt_string result = getenv ("USERNAME");
2157#else
2158  cmt_string result = getenv ("USER");
2159#endif
2160
2161  return (result);
2162}
2163
2164//----------------------------------------------------------
2165void CmtSystem::get_cvsroot (cmt_string& cvsroot)
2166{
2167  cvsroot = "";
2168
2169  const char* env = ::getenv ("CVSROOT");
2170  if (env != 0)
2171    {
2172      cvsroot = env;
2173      return;
2174    }
2175
2176#ifdef WIN32
2177  LONG status;
2178  HKEY key = 0;
2179
2180  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
2181                         0, KEY_READ, &key);
2182  if (status == ERROR_SUCCESS)
2183    {
2184      char temp[256];
2185      DWORD length = sizeof (temp) - 1;
2186      DWORD type;
2187
2188      status = RegQueryValueEx (key, "CVSROOT", 0, &type, 
2189                                (LPBYTE) temp, &length);
2190      if (status == ERROR_SUCCESS)
2191        {
2192          cvsroot = temp;
2193          return;
2194        }
2195    }
2196#endif
2197}
2198
2199//----------------------------------------------------------
2200bool CmtSystem::get_home_directory (cmt_string& dir)
2201{
2202  bool status = false;
2203
2204#ifdef WIN32
2205  const char* homedrive = ::getenv ("HOMEDRIVE");
2206  const char* homepath = ::getenv ("HOMEPATH");
2207
2208  if ((homedrive != 0) && (homepath != 0))
2209    {
2210      dir = homedrive;
2211      dir += homepath;
2212      status = true;
2213    }
2214
2215#else
2216  const char* home_env = ::getenv ("HOME");
2217  if (home_env != 0)
2218    {
2219      dir = home_env;
2220      status = true;
2221    }
2222#endif
2223
2224  return (status);
2225}
2226
Note: See TracBrowser for help on using the repository browser.