source: CMT/HEAD/source/cmt_generators.cxx @ 474

Last change on this file since 474 was 474, checked in by rybkin, 16 years ago

See C.L. 375

  • Property svn:eol-style set to native
File size: 80.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 "cmt_generators.h"
8#include "cmt_awk.h"
9#include "cmt_use.h"
10#include "cmt_symbol.h"
11#include "cmt_log.h"
12#include <assert.h>
13
14//--------------------------------------------------
15AnyDocumentGenerator::AnyDocumentGenerator ()
16{
17  m_TITLE.set ("TITLE");
18  m_STRUCTURED_OUTPUT.set ("STRUCTURED_OUTPUT");
19
20  make_header_fragment.set ("make_header");
21  cleanup_header_fragment.set ("cleanup_header");
22  cleanup_fragment.set ("cleanup");
23  dependencies_fragment.set ("dependencies");
24  dependencies_and_triggers_fragment.set ("dependencies_and_triggers");
25}
26
27void AnyDocumentGenerator::reset ()
28{
29  CmtGenerator::reset ();
30  m_TITLE = "";
31
32  make_header_fragment.reset ();
33  cleanup_header_fragment.reset ();
34  cleanup_fragment.reset ();
35  dependencies_fragment.reset ();
36  dependencies_and_triggers_fragment.reset ();
37}
38
39//--------------------------------------------------
40LibraryGenerator::LibraryGenerator ()
41{
42  library_header_fragment.set ("library_header");
43  application_header_fragment.set ("application_header");
44  java_header_fragment.set ("java_header");
45  jar_header_fragment.set ("jar_header");
46  protos_header_fragment.set ("protos_header");
47  library_fragment.set ("library");
48  library_no_share_fragment.set ("library_no_share");
49  library_no_static_fragment.set ("library_no_static");
50  application_fragment.set ("application");
51  jar_fragment.set ("jar");
52  java_fragment.set ("java");
53  java_copy_fragment.set ("java_copy");
54  cleanup_library_fragment.set ("cleanup_library");
55  cleanup_application_fragment.set ("cleanup_application");
56  cleanup_java_fragment.set ("cleanup_java");
57  cleanup_objects_fragment.set ("cleanup_objects");
58  buildproto_fragment.set ("buildproto");
59  check_application_fragment.set ("check_application");
60  check_java_fragment.set ("check_java");
61}
62
63//--------------------------------------------------
64void LibraryGenerator::reset ()
65{
66  AnyDocumentGenerator::reset ();
67  library_header_fragment.reset ();
68  application_header_fragment.reset ();
69  java_header_fragment.reset ();
70  jar_header_fragment.reset ();
71  protos_header_fragment.reset ();
72  library_fragment.reset ();
73  library_no_share_fragment.reset ();
74  library_no_static_fragment.reset ();
75  jar_fragment.reset ();
76  application_fragment.reset ();
77  java_fragment.reset ();
78  java_copy_fragment.reset ();
79  cleanup_library_fragment.reset ();
80  cleanup_application_fragment.reset ();
81  cleanup_java_fragment.reset ();
82  cleanup_objects_fragment.reset ();
83  buildproto_fragment.reset ();
84  check_application_fragment.reset ();
85  check_java_fragment.reset ();
86}
87
88//--------------------------------------------------
89bool LibraryGenerator::analyze_file (const Constituent& constituent,
90                                     const cmt_string& file)
91{
92  static cmt_string suffix;
93  static cmt_string name;
94  static cmt_string obj;
95
96  bool file_not_found = false;
97  bool can_build = true;
98
99  obj = file;
100
101  if (Cmt::get_debug ())
102    {
103      cout << "CmtGenerator::analyze_file> constituent=" << 
104        constituent.name <<
105        " file=" << file << endl;
106    }
107
108  if (!CmtSystem::test_file (file) && !CmtSystem::test_directory (file))
109    {
110      file_not_found = true;
111      CmtMessage::warning ("Source file " + file + " not found");
112      //      cerr << "#CMT> Warning: Source file " << file << " not found" << endl;
113    }
114
115  CmtSystem::get_suffix (file, suffix);
116  CmtSystem::basename (file, suffix, name);
117
118  Language& language = Language::find_with_suffix (suffix);
119
120  if (m_LINKMACRO == "")
121    {
122      m_LINKMACRO = language.linker;
123    }
124
125  if (language == "java")
126    {
127      static Packager packager;
128     
129      obj  = "$(javabin)";
130      obj +=  m_CONSTITUENT;
131      obj +=  CmtSystem::file_separator ();
132
133      cmt_regexp exp ("^package[ \t][ \t]*[a-zA-Z0-9_.][a-zA-Z0-9_.][ \t]*;");
134     
135      packager.run (file, exp);
136      if (packager.package_name () != "")
137        {
138          obj += packager.package_name ();
139          obj += CmtSystem::file_separator ();
140        }
141     
142      obj += name;
143      obj += ".class";
144    }
145  else if (language != Language::null ())
146    {
147      obj  = "$(bin)";     
148
149      if (CmtSystem::getenv("STRUCTURED_OUTPUT")!="" || Cmt::build_nmake ())
150        {
151          obj +=  m_CONSTITUENT;
152          obj +=  CmtSystem::file_separator ();
153        }
154
155      obj += name;
156      obj += language.output_suffix;
157      obj += constituent.suffix;
158      if (Cmt::build_nmake ()) obj += ".obj";
159      else obj += ".o";
160 
161      for (int i = 0; i < language.extra_output_suffixes.size (); i++)
162        {
163          cmt_string& extra_suffix = language.extra_output_suffixes[i];
164
165          obj += " $(bin)";
166          obj += name;
167          obj += extra_suffix;
168          obj += language.output_suffix;
169          obj += constituent.suffix;
170          if (Cmt::build_nmake ()) obj += ".obj";
171          else obj += ".o";
172        }
173    }
174  else
175    {
176      if (m_LINKMACRO == "java")
177        {
178          obj  = "$(javabin)";
179          obj +=  m_CONSTITUENT;
180          obj +=  CmtSystem::file_separator ();
181          obj += file;
182         
183          obj.replace ("../src/", "");
184          obj.replace ("..\\src\\", "");
185        }
186      else if (file_not_found)
187        {
188          can_build = false;
189          obj  = "";
190          CmtMessage::warning ("Source file " + name + " cannot be rebuilt");
191          //      cerr << "#CMT> Warning: Source file " << name << " cannot be rebuilt" << endl;
192        }
193      else
194        {
195          obj  = "";
196        }
197    }
198
199  if (Cmt::get_debug ())
200    {
201      cout << "CmtGenerator::analyze_file> constituent=" << 
202        constituent.name <<
203        " obj=" << obj << endl;
204    }
205
206  if (can_build)
207    {
208      SourceFile& source = m_source_files.add ();
209      source.set (file, language, obj);
210      return (true);
211    }
212  else
213    {
214      return (false);
215    }
216}
217
218//--------------------------------------------------
219void LibraryGenerator::java_file_action (SourceFile& file, const Constituent& constituent)
220{
221  static cmt_string suffix;
222
223  m_FULLNAME = file.name ();
224  m_OUTPUTNAME = file.output ();
225
226  CmtSystem::get_dot_suffix (m_FULLNAME, suffix);
227 
228  CmtSystem::basename (m_FULLNAME, suffix, m_NAME.value);
229  CmtSystem::basename (m_FULLNAME, m_FILENAME.value);
230 
231  if (CmtSystem::test_file (m_FULLNAME))
232    {
233      java_fragment.copy (m_output_file, constituent.variables, 5,
234                          &m_NAME,
235                          &m_FULLNAME,
236                          &m_OUTPUTNAME,
237                          &m_CONSTITUENT, 
238                          &m_CONSTITUENTSUFFIX);
239    }
240  else
241    {
242      CmtMessage::warning ("file " + m_FULLNAME + " not found");
243      //      cerr << "#CMT> Warning: file " << m_FULLNAME << " not found" << endl;
244    }
245}
246
247//--------------------------------------------------
248void LibraryGenerator::proto_file_action (const cmt_string& file, const Constituent& constituent)
249{
250  static cmt_string suffix;
251
252  CmtSystem::dirname (file, m_FILEPATH.value);
253  if (m_FILEPATH.value != "") m_FILEPATH.value += CmtSystem::file_separator ();
254
255  filter_path (m_FILEPATH.value);
256
257  CmtSystem::basename (file, m_FILENAME.value);
258  CmtSystem::get_dot_suffix (m_FILENAME, suffix);
259
260  CmtSystem::basename (m_FILENAME, suffix, m_NAME.value);
261
262  buildproto_fragment.copy (m_output_file, constituent.variables, 3, 
263                            &m_NAME, 
264                            &m_FILEPATH, 
265                            &m_FILENAME);
266}
267
268//--------------------------------------------------
269void LibraryGenerator::prepare_proto_file (const cmt_string& file)
270{
271  static cmt_string name;
272  static cmt_string pp;
273
274  CmtSystem::name (file, name);
275
276  if (CmtSystem::test_file (file))
277    {
278      pp  = incdir;
279      pp += name;
280      pp += ".pp";
281
282      if (!CmtSystem::test_file (pp))
283        {
284          //Generator::build_prototype (file);
285        }
286    }
287
288  protos += " ";
289  protos += inc;
290  protos += name;
291  protos += ".ph";
292
293  protonames += " ";
294  protonames += name;
295  protonames += ".ph";
296
297  m_PROTOSTAMPS += " ";
298  m_PROTOSTAMPS += inc;
299  m_PROTOSTAMPS += name;
300  m_PROTOSTAMPS += ".pp";
301}
302
303//--------------------------------------------------
304void LibraryGenerator::module_file_action (SourceFile& file, const Constituent& constituent)
305{
306  cmt_string name = file.name ();
307  Language& language = file.language ();
308
309  static cmt_string suffix;
310  static cmt_string prefix;
311  static cmt_string preproc;
312
313  m_FULLNAME = name;
314
315  CmtSystem::get_dot_suffix (name, suffix);
316
317  CmtSystem::basename (name, suffix, m_NAME.value);
318
319  CmtSystem::dirname (name, prefix);
320  CmtSystem::basename (name, m_FILENAME.value);
321
322  FragmentHandle* fragment;
323
324  if (language != Language::null ())
325    {
326      preproc = language.preprocessor_command;
327      fragment = (is_library) ? &(language.library) : &(language.application);
328    }
329  else
330    {
331      //
332      // What happens when the language is not known???
333      //
334      //
335      preproc = "-I";
336      fragment = 0;
337    }
338
339  if ((prefix == "../src") || (prefix == "..\\src"))
340    {
341      m_ADDINCLUDE = "";
342    }
343  else if (prefix != "")
344    {
345      m_ADDINCLUDE  = preproc;
346      m_ADDINCLUDE += prefix;
347    }
348
349  m_FILEPATH = prefix;
350  if (m_FILEPATH.value != "") m_FILEPATH.value += CmtSystem::file_separator ();
351  filter_path (m_FILEPATH.value);
352
353  /*
354  m_LINE = m_FULLNAME.value;
355  m_LINE += " ";
356  */
357
358  filter_path (m_FULLNAME.value);
359  //  filter_path (m_LINE.value);
360
361  CmtSystem::get_suffix (name, m_FILESUFFIX.value);
362
363  if (fragment != 0)
364    {
365      fragment->copy (m_output_file, constituent.variables, 10,
366                      &m_CONSTITUENT, 
367                      &m_CONSTITUENTSUFFIX, 
368                      &m_FILENAME, 
369                      &m_NAME, 
370                      &m_LINE,
371                      &m_ADDINCLUDE, 
372                      &m_FULLNAME, 
373                      &m_FILEPATH, 
374                      &m_FILESUFFIX, 
375                      &m_PACKAGE);
376    }
377  else if (file.output () != "")
378    {
379      m_OUTPUTNAME = file.output ();
380      CmtSystem::dirname (m_OUTPUTNAME.value, m_FILEPATH.value);
381
382      java_copy_fragment.copy (m_output_file, constituent.variables, 11,
383                               &m_CONSTITUENT, 
384                               &m_CONSTITUENTSUFFIX, 
385                               &m_FILENAME, 
386                               &m_NAME, 
387                               &m_LINE,
388                               &m_ADDINCLUDE, 
389                               &m_FULLNAME, 
390                               &m_FILEPATH, 
391                               &m_FILESUFFIX, 
392                               &m_PACKAGE, 
393                               &m_OUTPUTNAME);
394    }
395
396  if (m_PACKOS9)
397    {
398      //      os9sources += m_LINE;
399      os9sources += m_FULLNAME.value;
400      os9sources += " ";
401    }
402}
403
404//--------------------------------------------------
405void LibraryGenerator::build (const cmt_string& package,
406                              const Constituent& constituent,
407                              const cmt_string& file_name)
408{
409  static cmt_string lib;
410  static cmt_string allsources;
411  static cmt_string file;
412  static cmt_string full_name;
413  static cmt_string compressed_name;
414  static cmt_string suffix;
415  int i;
416  bool need_prototypes;
417
418  reset ();
419
420  if (!prepare_output (package, constituent, file_name)) return;
421
422  switch (constituent.type)
423    {
424    case Application:
425      is_library = false;
426      is_application = true;
427      m_TITLE = "Application";
428      break;
429    case Library:
430      is_library = true;
431      is_application = false;
432      m_TITLE = "Library";
433      break;
434    }
435
436  m_source_files.clear ();
437
438  need_prototypes = constituent.need_prototypes;
439
440  //  cout << m_TITLE << " " << m_CONSTITUENT << endl;
441  CmtMessage::info (m_TITLE + " " + m_CONSTITUENT);
442
443  lib  = "$(";
444  lib += m_CONSTITUENT;
445  lib += "lib)";
446
447  //
448  // Prepare the include paths
449  //
450
451  const CmtSystem::cmt_string_vector& includes = constituent.includes;
452
453  for (i = 0; i < includes.size (); i++)
454    {
455      const cmt_string& subdir = includes[i];
456
457      m_PACKINCLUDES += " -I";
458      m_PACKINCLUDES += subdir;
459    }
460
461  //
462  // Scan the sources.
463  //
464
465  const CmtSystem::cmt_string_vector& sources = constituent.modules;
466  const cmt_vector<cmt_regexp>& excludes = constituent.exclude_exprs;
467  const cmt_vector<cmt_regexp>& selects = constituent.select_exprs;
468
469  //  m_LINE = "";
470
471  for (i = 0; i < sources.size (); i++)
472    {
473      file = sources[i];
474
475      set_full_name (full_name, file);
476      if (full_name == "") continue;
477
478      CmtSystem::compress_path (full_name, compressed_name);
479      full_name = compressed_name;
480
481      static CmtSystem::cmt_string_vector files;
482
483      int count = get_all_files (full_name, excludes, selects, files);
484
485      filter_path (full_name);
486
487      for (int j = 0; j < files.size (); j++)
488        {
489          const cmt_string& name = files[j];
490
491          if (name != "") 
492            {
493              if (!analyze_file (constituent, name)) 
494                {
495                  count = 0;
496                  break;
497                }
498            }
499        }
500
501      /*
502      if (count > 0)
503        {
504          m_LINE += full_name;
505          m_LINE += " ";
506        }
507      */
508    }
509
510  fill_names_outputs ();
511  //fill_outputs ();
512
513  prepare_use_context ();
514
515  m_DATE = CmtSystem::now ();
516  m_USER = CmtSystem::user ();
517  m_PACKAGE = package;
518
519  if (constituent.has_target_tag)
520    {
521      m_HASTARGETTAG = "has_target_tag";
522    }
523  else
524    {
525      m_HASTARGETTAG = "has_no_target_tag";
526    }
527   
528  m_STRUCTURED_OUTPUT = "STRUCTURED_OUTPUT";
529
530  make_header_fragment.copy (m_output_file, constituent.variables, 8, 
531                             &m_TITLE,
532                             &m_CONSTITUENT,
533                             &m_CONSTITUENTSUFFIX,
534                             &m_USER,
535                             &m_DATE,
536                             &m_PACKAGE,
537                             &m_HASTARGETTAG,
538                             &m_STRUCTURED_OUTPUT
539                             );
540
541  if (need_prototypes)
542    {
543      need_prototypes = false;
544
545      for (i = 0; i < m_source_files.size (); i++)
546        {
547          const SourceFile& file = m_source_files[i];
548          Language& language = file.language ();
549          if (language.prototypes)
550            {
551              need_prototypes = true;
552              break;
553            }
554        }
555    }
556
557  //-------------------------------------------
558  //
559  // Specific targets (application, library or java)
560  // Prepare in case prototype files are needed
561  //
562  //-------------------------------------------
563
564  m_PROTOTARGET = "";
565
566  //if ((Cmt::current_build_strategy & PrototypesMask) == Prototypes)
567  if (need_prototypes)
568    {
569      m_PROTOTARGET = m_CONSTITUENT;
570      m_PROTOTARGET += "PROTOS";
571    }
572
573  if (m_LINKMACRO == "java")
574    {
575      if (is_library)
576        {
577          jar_header_fragment.copy (m_output_file, constituent.variables, 3, 
578                                    &m_CONSTITUENT, 
579                                    &m_CONSTITUENTSUFFIX,
580                                    &m_OBJS);
581        }
582      else
583        {
584          java_header_fragment.copy (m_output_file, constituent.variables, 3, 
585                                     &m_CONSTITUENT,
586                                     &m_CONSTITUENTSUFFIX,
587                                     &m_OBJS);
588        }
589    }
590  else
591    {
592      if (is_library)
593        {
594          library_header_fragment.copy (m_output_file, constituent.variables, 3,
595                                        &m_CONSTITUENT,
596                                        &m_CONSTITUENTSUFFIX,
597                                        &m_PROTOTARGET);
598        }
599      else
600        {
601          application_header_fragment.copy (m_output_file, constituent.variables, 3,
602                                            &m_CONSTITUENT, 
603                                            &m_CONSTITUENTSUFFIX, 
604                                            &m_PROTOTARGET);
605        }
606    }
607
608
609  //----------------------------------------------------
610  //
611  // Preparing prototype files.
612  //
613  //----------------------------------------------------
614
615  //if ((Cmt::current_build_strategy & PrototypesMask) == Prototypes)
616  if (need_prototypes)
617    {
618      for (i = 0; i < m_source_files.size (); i++)
619        {
620          const SourceFile& file = m_source_files[i];
621          Language& language = file.language ();
622          if (language.prototypes)
623            {
624              prepare_proto_file (file.name ());
625            }
626        }
627
628      if (m_PROTOSTAMPS != "")
629        {
630          protos_header_fragment.copy (m_output_file, constituent.variables, 3, 
631                                       &m_CONSTITUENT,
632                                       &m_CONSTITUENTSUFFIX,
633                                       &m_PROTOSTAMPS);
634        }
635
636      if (protonames != "")
637        {
638          for (i = 0; i < m_source_files.size (); i++)
639            {
640              const SourceFile& file = m_source_files[i];
641              Language& language = file.language ();
642              if (language.prototypes)
643                {
644                  proto_file_action (file.name (), constituent);
645                }
646            }
647        }
648    }
649
650  //----------------------------------------------------
651  //
652  // Preparing the library.
653  //
654  //----------------------------------------------------
655
656  if (m_OBJS != "")
657    {
658      if (m_LINKMACRO == "java")
659        {
660          if (is_library)
661            {
662              cmt_string classes = m_OBJS.value;
663
664              classes.replace_all ("$(javabin)", "");
665              classes.replace_all (srcdir.c_str (), "");
666
667              m_CLASSES = classes;
668
669              jar_fragment.copy (m_output_file, constituent.variables, 4, 
670                                 &m_CONSTITUENT,
671                                 &m_CONSTITUENTSUFFIX,
672                                 &m_OBJS,
673                                 &m_CLASSES);
674            }
675        }
676      else
677        {
678          if (is_library)
679            {
680              if (constituent.no_share && constituent.no_static)
681                {
682                  CmtMessage::warning (constituent.name + ": No shared or static library");
683                }
684              else if (constituent.no_share)
685                {
686                  library_no_share_fragment.copy (m_output_file, constituent.variables, 3, 
687                                                  &m_CONSTITUENT,
688                                                  &m_CONSTITUENTSUFFIX,
689                                                  &m_OBJS);
690                }
691              else if (constituent.no_static)
692                {
693                  library_no_static_fragment.copy (m_output_file, constituent.variables, 3, 
694                                                  &m_CONSTITUENT,
695                                                  &m_CONSTITUENTSUFFIX,
696                                                  &m_OBJS);
697                }
698              else
699                {
700                  library_fragment.copy (m_output_file, constituent.variables, 3, 
701                                         &m_CONSTITUENT,
702                                         &m_CONSTITUENTSUFFIX,
703                                         &m_OBJS);
704                }
705            }
706          else
707            {
708              application_fragment.copy (m_output_file, constituent.variables, 4,
709                                         &m_CONSTITUENT,
710                                         &m_CONSTITUENTSUFFIX, 
711                                         &m_OBJS,
712                                         &m_LINKMACRO);
713            }
714        }
715    }
716
717  if (constituent.build_triggers)
718    {
719      dependencies_and_triggers_fragment.copy (m_output_file, 
720                                               constituent.variables, 3,
721                                               &m_CONSTITUENT, 
722                                               &m_CONSTITUENTSUFFIX, 
723                                               &m_LINE);
724    }
725  else
726    {
727      dependencies_fragment.copy (m_output_file, 
728                                  constituent.variables, 3,
729                                  &m_CONSTITUENT, 
730                                  &m_CONSTITUENTSUFFIX, 
731                                  &m_LINE);
732    }
733
734  //----------------------------------------------------
735  //
736  // Building actual individual targets.
737  //
738  //----------------------------------------------------
739
740  for (i = 0; i < m_source_files.size (); i++)
741    {
742      SourceFile& file = m_source_files[i];
743      Language& language = file.language ();
744
745      if (language == "java")
746        {
747          java_file_action (file, constituent);
748        }
749      else
750        {
751          module_file_action (file, constituent);
752        }
753    }
754
755  if (m_PACKOS9)
756    {
757      if (os9sources != "")
758        {
759          //
760          // Generate transfers to the OS9 area.
761          //
762
763          m_ALLOS9SOURCES = "";
764          allsources = "";
765        }
766    }
767
768  /*
769    for file in `cmt_sort_line.csh ${os9sources}` ; do
770    if test `echo ${file} | grep '$(src)'` ; then
771    name=`echo ${file} | sed 's#$(src)##'`
772    ALLOS9SOURCES="${ALLOS9SOURCES} ../OS9/${name}"
773    allsources="${allsources} ${file}"
774    elif test `echo ${file} | grep '$(inc)'` ; then
775    name=`echo ${file} | sed 's#$(inc)##'`
776    ALLOS9SOURCES="${ALLOS9SOURCES} ../OS9/${name}"
777    allsources="${allsources} ${file}"
778    fi
779    done
780
781    if test ! "${ALLOS9SOURCES}" = "" ; then
782
783    sed -e "`subs_vars ALLOS9SOURCES`" \
784    ${os9_header_fragment} \
785    >>${output}
786
787    for FULLNAME in ${allsources} ; do
788
789    NAME=`echo ${FULLNAME} | sed -e 's#$(src)##' -e 's#$(inc)##'`
790
791    sed -e "`subs_vars NAME FULLNAME`" \
792    ${os9_fragment} \
793    >>${output}
794
795    done
796    fi
797    fi
798    fi
799  */
800
801  //
802  //  Generate package cleanup operations.
803  //
804
805  cleanup_header_fragment.copy (m_output_file, constituent.variables, 2, 
806                                &m_CONSTITUENT,
807                                &m_CONSTITUENTSUFFIX);
808
809  //if ((Cmt::current_build_strategy & PrototypesMask) == Prototypes)
810  if (need_prototypes)
811    {
812      if (protos != "")
813        {
814          m_FULLNAME = protos;
815          cleanup_fragment.copy (m_output_file, constituent.variables, 1, &m_FULLNAME);
816          m_FULLNAME = m_PROTOSTAMPS;
817          cleanup_fragment.copy (m_output_file, constituent.variables, 1, &m_FULLNAME);
818        }
819    }
820
821  if (m_LINKMACRO == "java")
822    {
823      cleanup_java_fragment.copy (m_output_file, constituent.variables, 1, &m_OBJS);
824
825      if (!is_library)
826        {
827          if (constituent.need_check)
828            {
829              check_java_fragment.copy (m_output_file, constituent.variables, 2, 
830                                        &m_CONSTITUENT,
831                                        &m_CONSTITUENTSUFFIX);
832            }
833        }
834    }
835  else
836    {
837      if (is_library)
838        {
839          cleanup_library_fragment.copy (m_output_file, constituent.variables, 2, 
840                                         &m_CONSTITUENT,
841                                         &m_CONSTITUENTSUFFIX);
842        }
843      else
844        {
845          cleanup_application_fragment.copy (m_output_file, constituent.variables, 2, 
846                                             &m_CONSTITUENT,
847                                             &m_CONSTITUENTSUFFIX);
848          if (m_OBJS != "")
849            {
850              cleanup_objects_fragment.copy (m_output_file, constituent.variables, 3, 
851                                             &m_OBJS,
852                                             &m_CONSTITUENT,
853                                             &m_CONSTITUENTSUFFIX);
854            }
855
856          if (constituent.need_check)
857            {
858              check_application_fragment.copy (m_output_file, constituent.variables, 2, 
859                                               &m_CONSTITUENT,
860                                               &m_CONSTITUENTSUFFIX);
861            }
862        }
863    }
864
865  terminate ();
866}
867
868//--------------------------------------------------
869DocumentGenerator::DocumentGenerator ()
870{
871  document_header_fragment.set ("document_header");
872}
873
874//--------------------------------------------------
875void DocumentGenerator::reset ()
876{
877  AnyDocumentGenerator::reset ();
878  document_header_fragment.reset ();
879}
880
881//--------------------------------------------------
882void DocumentGenerator::build (const cmt_string& package,
883                               const Constituent& constituent,
884                               const cmt_string& file_name)
885{
886  static cmt_string names;
887  static cmt_string output_dir;
888  static cmt_string name;
889  static cmt_string full_name;
890  static cmt_string compressed_name;
891  static cmt_string suffix;
892  static cmt_string output_suffix;
893  static cmt_string fragment_suffix;
894
895  reset ();
896
897  if (!prepare_output (package, constituent, file_name)) return;
898
899  is_library = false;
900  is_application = false;
901  m_GENERATOR = constituent.generator;
902  m_TITLE = "Document";
903
904  int i;
905
906  //  cout << m_TITLE << " " << m_CONSTITUENT << endl;
907  CmtMessage::info (m_TITLE + " " + m_CONSTITUENT);
908
909  //
910  // Prepare the include paths.
911  //
912
913  const CmtSystem::cmt_string_vector& includes = constituent.includes;
914
915  for (i = 0; i < includes.size (); i++)
916    {
917      const cmt_string& subdir = includes[i];
918
919      m_PACKINCLUDES += " -I";
920      m_PACKINCLUDES += subdir;
921    }
922
923  //
924  // Get the fragment associated with the document style
925  //
926
927  FragmentHandle fragment (m_GENERATOR);
928
929  fragment_suffix = fragment.suffix ();
930
931  output_suffix = ".";
932
933  if (fragment_suffix == "")
934    {
935      output_suffix += fragment.name ();
936    }
937  else
938    {
939      output_suffix += fragment_suffix;
940    }
941
942  //
943  // Scan the sources.
944  //
945
946  const CmtSystem::cmt_string_vector& sources = constituent.modules;
947  const cmt_vector<cmt_regexp>& excludes = constituent.exclude_exprs;
948  const cmt_vector<cmt_regexp>& selects = constituent.select_exprs;
949
950  //  m_LINE = "";
951
952  for (i = 0; i < sources.size (); i++)
953    {
954      cmt_string& file = sources[i];
955
956      set_full_name (full_name, file);
957      if (full_name == "") continue;
958
959      CmtSystem::compress_path (full_name, compressed_name);
960      full_name = compressed_name;
961
962      static CmtSystem::cmt_string_vector files;
963
964      int count = get_all_files (full_name, excludes, selects, files);
965
966      filter_path (full_name);
967
968      /*
969      if (count > 0)
970        {
971          m_LINE += full_name;
972          m_LINE += " ";
973        }
974      */
975
976      for (int j = 0; j < files.size (); j++)
977        {
978          const cmt_string& name = files[j];
979
980          if (name != "") 
981            {
982              analyze_file (name, constituent.name, output_suffix);
983            }
984        }
985    }
986
987  fill_names_outputs ();
988  //  fill_outputs ();
989
990  prepare_use_context ();
991
992  m_DATE = CmtSystem::now ();
993  m_USER = CmtSystem::user ();
994  m_PACKAGE = package;
995
996  if (constituent.has_target_tag)
997    {
998      m_HASTARGETTAG = "has_target_tag";
999    }
1000  else
1001    {
1002      m_HASTARGETTAG = "has_no_target_tag";
1003    }
1004
1005  make_header_fragment.copy (m_output_file, constituent.variables, 7,
1006                             &m_TITLE, 
1007                             &m_CONSTITUENT,
1008                             &m_CONSTITUENTSUFFIX,
1009                             &m_USER,
1010                             &m_DATE,
1011                             &m_PACKAGE,
1012                             &m_HASTARGETTAG);
1013
1014  const cmt_string& header = fragment.header ();
1015
1016  //
1017  // If the document type specifies a header, use it .
1018  // otherwise, use the default document header fragment.
1019  //
1020  if (header != "")
1021    {
1022      FragmentHandle header_fragment (header);
1023      header_fragment.copy (m_output_file, constituent.variables, 3, 
1024                            &m_CONSTITUENT,
1025                            &m_CONSTITUENTSUFFIX,
1026                            &m_OBJS);
1027    }
1028  else
1029    {
1030      document_header_fragment.copy (m_output_file, constituent.variables, 3, 
1031                                     &m_CONSTITUENT,
1032                                     &m_CONSTITUENTSUFFIX,
1033                                     &m_OBJS);
1034    }
1035
1036  if (fragment.need_dependencies ())
1037    {
1038      dependencies_fragment.copy (m_output_file, constituent.variables, 3, 
1039                                  &m_CONSTITUENT,
1040                                  &m_CONSTITUENTSUFFIX,
1041                                  &m_LINE);
1042    }
1043  else
1044    {
1045      for (i = 0; i < sources.size (); i++)
1046        {
1047          cmt_string& file = sources[i];
1048         
1049          set_full_name (full_name, file);
1050          if (full_name == "") continue;
1051         
1052          CmtSystem::compress_path (full_name, compressed_name);
1053          full_name = compressed_name;
1054
1055          static CmtSystem::cmt_string_vector files;
1056         
1057          get_all_files (full_name, excludes, selects, files);
1058         
1059          for (int j = 0; j < files.size (); j++)
1060            {
1061              const cmt_string& name = files[j];
1062             
1063              if (name != "") 
1064                {
1065                  static cmt_string s;
1066                  static cmt_string n;
1067                 
1068                  CmtSystem::get_dot_suffix (name, s);
1069                  CmtSystem::basename (name, s, n);
1070                  CmtSystem::get_suffix (name, s);
1071                 
1072                  fprintf (m_output_file, "%s_%s_dependencies = %s\n",
1073                           n.c_str (),
1074                           s.c_str (),
1075                           name.c_str ());
1076                }
1077            }
1078        }
1079    }
1080 
1081  m_SUFFIX = fragment_suffix;
1082  for (i = 0; i < m_source_files.size (); i++)
1083    {
1084      SourceFile& file = m_source_files[i];
1085      const cmt_string& file_name = file.name ();
1086      m_FULLNAME = file_name;
1087      CmtSystem::get_dot_suffix (file_name, suffix);
1088      CmtSystem::basename (file_name, suffix, m_NAME.value);
1089      CmtSystem::dirname (file_name, m_FILEPATH.value);
1090      if (m_FILEPATH.value != "") m_FILEPATH.value += CmtSystem::file_separator ();
1091      filter_path (m_FILEPATH.value);
1092      CmtSystem::basename (file_name, m_FILENAME.value);
1093      CmtSystem::get_dot_suffix (m_FILENAME.value, m_FILESUFFIX.value);
1094
1095      if (!CmtSystem::test_file (file_name) && !CmtSystem::test_directory (file_name))
1096        {
1097          CmtMessage::warning ("Source file " + file_name + " not found");
1098          //          cerr << "#CMT> Warning: Source file " << file_name << " not found" << endl;
1099        }
1100
1101      filter_path (m_FULLNAME.value);
1102
1103      fragment.copy (m_output_file, constituent.variables, 8,
1104                     &m_FILEPATH,
1105                     &m_SUFFIX,
1106                     &m_CONSTITUENT,
1107                     &m_CONSTITUENTSUFFIX,
1108                     &m_FILENAME,
1109                     &m_NAME,
1110                     &m_FULLNAME,
1111                     &m_FILESUFFIX);
1112    }
1113
1114  const cmt_string& trailer = fragment.trailer ();
1115  if (trailer != "")
1116    {
1117      FragmentHandle trailer_fragment (trailer);
1118      trailer_fragment.copy (m_output_file, constituent.variables, 3, 
1119                             &m_CONSTITUENT,
1120                             &m_CONSTITUENTSUFFIX,
1121                             &m_OBJS);
1122    }
1123
1124  //
1125  //  Generate package cleanup operations.
1126  //
1127
1128  cleanup_header_fragment.copy (m_output_file, constituent.variables, 2, 
1129                                &m_CONSTITUENT,
1130                                &m_CONSTITUENTSUFFIX);
1131
1132  terminate ();
1133}
1134
1135//--------------------------------------------------
1136bool DocumentGenerator::analyze_file (const cmt_string& file,
1137                                      const cmt_string& constituent_name,
1138                                      const cmt_string& output_suffix)
1139{
1140  static cmt_string output_dir;
1141  static cmt_string suffix;
1142  static cmt_string name;
1143  static cmt_string obj;
1144
1145  if (!CmtSystem::test_file (file) && !CmtSystem::test_directory (file))
1146    {
1147      CmtMessage::warning ("Source file " + file + " not found");
1148      //      cerr << "#CMT> Warning: Source file " << file << " not found" << endl;
1149    }
1150
1151  CmtSystem::dirname (file, output_dir);
1152  output_dir += CmtSystem::file_separator ();
1153
1154  filter_path (output_dir);
1155
1156  CmtSystem::get_suffix (file, suffix);
1157  CmtSystem::basename (file, suffix, name);
1158
1159  //obj = output_dir;
1160  obj = "$(";
1161  obj += constituent_name;
1162  obj += "_output)";
1163  obj += name;
1164  obj += output_suffix;
1165
1166  SourceFile& source = m_source_files.add ();
1167  source.set (file, Language::null (), obj);
1168
1169  return (true);
1170}
1171
1172ReadmeGenerator::ReadmeGenerator ()
1173{
1174  readme_header_fragment.set ("readme_header");
1175  readme_fragment.set ("readme");
1176  readme_doc_fragment.set ("readme_doc");
1177  readme_use_fragment.set ("readme_use");
1178  readme_trailer_fragment.set ("readme_trailer");
1179}
1180
1181void ReadmeGenerator::reset ()
1182{
1183  CmtGenerator::reset ();
1184
1185  readme_header_fragment.reset ();
1186  readme_fragment.reset ();
1187  readme_doc_fragment.reset ();
1188  readme_use_fragment.reset ();
1189  readme_trailer_fragment.reset ();
1190}
1191
1192//--------------------------------------------------
1193void ReadmeGenerator::build (const CmtSystem::cmt_string_vector& arguments)
1194{
1195  reset ();
1196
1197  m_PACKAGE = Cmt::get_current_package ();
1198  m_VERSION = Cmt::get_current_version ();
1199  m_DATE = CmtSystem::now ();
1200  m_USER = CmtSystem::user ();
1201
1202  cmt_string url;
1203  cmt_string doc;
1204
1205  for (int i = 0; i < arguments.size (); i++)
1206    {
1207      cmt_string arg = arguments[i];
1208
1209      if (arg.substr (0, 5) == "-url=")
1210        {
1211          arg.substr (5, url);
1212        }
1213      else if (arg.substr (0, 5) == "-doc=")
1214        {
1215          arg.substr (5, doc);
1216        }
1217    }
1218
1219  m_output_file_name = cmtdir + "README.html";
1220
1221  m_output_file = fopen (m_output_file_name.c_str (), "wb");
1222  if (m_output_file != NULL)
1223    {
1224      readme_header_fragment.copy (m_output_file, 2, 
1225                                   &m_PACKAGE, &m_VERSION);
1226
1227      if (doc != "")
1228        {
1229          m_DOCPATH = doc;
1230          readme_doc_fragment.copy (m_output_file, 3,
1231                                    &m_PACKAGE,
1232                                    &m_VERSION,
1233                                    &m_DOCPATH);
1234        }
1235
1236      readme_fragment.copy (m_output_file, 2,
1237                            &m_PACKAGE,
1238                            &m_VERSION);
1239
1240      int number;
1241      const Use::UsePtrVector& uses = Use::get_ordered_uses ();
1242
1243      for (number = 0; number < uses.size (); number++)
1244        {
1245          const Use* use = uses[number];
1246
1247          if (use == 0) continue;
1248          if (use->discarded) continue;
1249
1250          Package* p = use->get_package ();
1251          if (p->is_cmt ()) continue;
1252
1253          cmt_string selected_path;
1254
1255          if (url == "")
1256            {
1257              selected_path = use->real_path;
1258             
1259              if (use->specified_path != "")
1260                {
1261                  int pos = selected_path.find_last_of (use->specified_path);
1262                  if (pos != cmt_string::npos)
1263                    {
1264                      selected_path.erase (pos);
1265                    }
1266                }
1267            }
1268          else
1269            {
1270              selected_path = url;
1271             
1272              if (use->specified_path != "")
1273                {
1274                  selected_path += CmtSystem::file_separator ();
1275                }
1276            }
1277         
1278          m_PACKAGEPATH = selected_path;
1279          m_PACKAGEPREFIX = use->specified_path;
1280          m_PACKAGE = use->get_package_name ();
1281          m_VERSION = use->version;
1282          m_MGRSTYLE = (use->style == mgr_style) ? "mgr" : "cmt";
1283          readme_use_fragment.copy (m_output_file, 5,
1284                                    &m_PACKAGEPATH,
1285                                    &m_PACKAGEPREFIX,
1286                                    &m_PACKAGE,
1287                                    &m_VERSION,
1288                                    &m_MGRSTYLE);
1289        }
1290
1291      m_PACKAGE = Cmt::get_current_package ();
1292      m_VERSION = Cmt::get_current_version ();
1293      readme_trailer_fragment.copy (m_output_file, 4, 
1294                                    &m_PACKAGE, 
1295                                    &m_VERSION, 
1296                                    &m_DATE, 
1297                                    &m_USER);
1298
1299      terminate ();
1300    }
1301}
1302
1303//--------------------------------------------------
1304class Prototyper : public FAwk
1305{
1306public:
1307  Prototyper (bool static_functions = false) :
1308    m_static_functions(static_functions)
1309  {
1310    if (m_static_functions)
1311      {
1312        m_suffix = "_static.phnew";
1313        m_define_suffix = "_static_ph";
1314      }
1315    else
1316      {
1317        m_suffix = ".phnew";
1318        m_define_suffix = "_ph";
1319      }
1320  }
1321
1322  void begin ()
1323  {
1324    m_running = false;
1325
1326    static cmt_string suffix;
1327    static cmt_string name;
1328
1329    CmtSystem::get_dot_suffix (m_file_name, suffix);
1330    CmtSystem::basename (m_file_name, suffix, name);
1331
1332    m_out_file_name  = "";
1333
1334    if (m_dir_name != "")
1335      {
1336        m_out_file_name  = m_dir_name;
1337        m_out_file_name += CmtSystem::file_separator ();
1338      }
1339
1340    m_out_file_name += name;
1341    m_out_file_name += m_suffix;
1342
1343    CmtSystem::basename (m_file_name, suffix, m_file_name);
1344
1345    m_output = fopen (m_out_file_name.c_str (), "wb");
1346
1347    if (m_output != 0)
1348      {
1349        fprintf (m_output, "#ifndef __%s%s__\n", m_file_name.c_str (),
1350                 m_define_suffix.c_str ());
1351        fprintf (m_output, "#define __%s%s__\n", m_file_name.c_str (),
1352                 m_define_suffix.c_str ());
1353
1354        fprintf (m_output, "\n");
1355        fprintf (m_output, "#ifdef __cplusplus\n");
1356        fprintf (m_output, "extern \"C\" {\n");
1357        fprintf (m_output, "#endif\n");
1358        fprintf (m_output, "\n");
1359      }
1360    else
1361      {
1362        stop ();
1363      }
1364  }
1365
1366  void filter (const cmt_string& line)
1367  {
1368    char c = line[0];
1369
1370    if (!m_running)
1371      {
1372        if ((c == ' ') ||
1373            (c == '/') ||
1374            (c == '|') ||
1375            (c == '\t') ||
1376            (c == '#')) return;
1377        if (line.find ('(') == cmt_string::npos)
1378          {
1379            m_prev_line = line;
1380            return;
1381          }
1382
1383        m_running = true;
1384        m_full_line = line;
1385        m_full_line.replace ("(", " (");
1386
1387        static CmtSystem::cmt_string_vector words;
1388
1389        CmtSystem::split (m_full_line, " \t", words);
1390
1391        const cmt_string& second = words[1];
1392        if (second[0] == '(')
1393          {
1394            m_full_line = m_prev_line;
1395            m_full_line += " ";
1396            m_full_line += line;
1397
1398            m_prev_line = "";
1399          }
1400      }
1401    else
1402      {
1403        m_full_line += line;
1404      }
1405    if (line.find (')') == cmt_string::npos) return;
1406    m_running = false;
1407
1408    if (m_full_line.find (';') != cmt_string::npos) return;
1409    if (m_full_line.find ("::") != cmt_string::npos) return;
1410    if (m_full_line.find ('<') != cmt_string::npos) return;
1411    if (m_full_line.find ('>') != cmt_string::npos) return;
1412    if (m_full_line.find ('{') != cmt_string::npos) return;
1413    if (m_full_line.find ('}') != cmt_string::npos) return;
1414    if (m_full_line.find ("typedef") != cmt_string::npos) return;
1415    if (m_full_line.find ("yy") != cmt_string::npos) return;
1416    if (m_full_line.find ("YY") != cmt_string::npos) return;
1417    if (m_static_functions)
1418      {
1419        if (m_full_line.find ("static") == cmt_string::npos) return;
1420      }
1421    else
1422      {
1423        if (m_full_line.find ("static") != cmt_string::npos) return;
1424      }
1425
1426    m_full_line += ";";
1427
1428    if (m_output != 0)
1429      {
1430        fprintf (m_output, "%s\n", m_full_line.c_str ());
1431      }
1432  }
1433
1434  void end ()
1435  {
1436    if (m_output != 0)
1437      {
1438        fprintf (m_output, "\n");
1439        fprintf (m_output, "#ifdef __cplusplus\n");
1440        fprintf (m_output, "}\n");
1441        fprintf (m_output, "#endif\n");
1442        fprintf (m_output, "\n");
1443        fprintf (m_output, "#endif\n");
1444        fprintf (m_output, "\n");
1445
1446        fclose (m_output);
1447      }
1448
1449    CmtGenerator::check (m_out_file_name);
1450  }
1451
1452private:
1453  bool m_running;
1454  cmt_string m_out_file_name;
1455  FILE* m_output;
1456  bool m_static_functions;
1457  cmt_string m_full_line;
1458  cmt_string m_prev_line;
1459  cmt_string m_suffix;
1460  cmt_string m_define_suffix;
1461};
1462//--------------------------------------------------
1463
1464//--------------------------------------------------
1465void PrototypeGenerator::build (const cmt_string& file_name)
1466{
1467  Prototyper prototyper;
1468
1469  reset ();
1470
1471  prototyper.run (file_name);
1472}
1473
1474//--------------------------------------------------
1475void DefaultMakefileGenerator::build ()
1476{
1477  cmt_string makefile;
1478
1479  //reset ();
1480
1481  //--- Build a simple Makefile if none is installed
1482
1483#ifndef WIN32
1484
1485  bool need_makefile = false;
1486
1487  makefile = cmtdir + "Makefile";
1488
1489  if (!CmtSystem::test_file (makefile))
1490    {
1491      need_makefile = true;
1492    }
1493  else
1494    {
1495      static cmt_string s;
1496
1497      s.read (makefile);
1498      if ((s.find ("METHODSROOT") != cmt_string::npos) ||
1499          (s.find ("$(CMTROOT)/src/constituents.make") == cmt_string::npos))
1500        {
1501          static cmt_string backup = makefile;
1502          backup += "_backup";
1503
1504          makefile += ".cmt";
1505
1506          if (!CmtSystem::test_file (makefile))
1507            {
1508              FILE* file = fopen (backup.c_str (), "wb");
1509              if (file != NULL)
1510                {
1511                  CmtMessage::warning ("\n"
1512                                       "# A Makefile already exists "
1513                                       "but it does not provide\n"
1514                                       "# the recommended features "
1515                                       "for a full benefit of CMT\n"
1516                                       "#\n"
1517                                       "# CMT is now building "
1518                                       "a new 'Makefile.cmt' which you can use\n"
1519                                       "# to upgrade your current one.");
1520                  /*
1521                  cerr << "# " << endl;
1522                  cerr << "#CMT> Warning: " << endl;
1523                  cerr << "# A Makefile already exists "
1524                    "but it does not provides " << endl;
1525                  cerr << "# the recommended features "
1526                    "for a full benefit of CMT" << endl;
1527                  cerr << "# " << endl;
1528                  cerr << "# CMT is now building "
1529                    "a new 'Makefile.cmt' which you can use" << endl;
1530                  cerr << "# to upgrade your current one." << endl;
1531                  cerr << "# " << endl;
1532                  */
1533                  s.write (file);
1534                  fclose (file);
1535
1536                  need_makefile = true;
1537                }
1538            }
1539        }
1540    }
1541
1542  if (need_makefile)
1543    {
1544      FILE* file = fopen (makefile.c_str (), "wb");
1545      if (file != NULL)
1546        {
1547          fprintf (file, "include $(CMTROOT)/src/Makefile.header\n");
1548          fprintf (file, "\n");
1549          fprintf (file, "include $(CMTROOT)/src/constituents.make\n");
1550          fprintf (file, "\n");
1551          fclose (file);
1552        }
1553    }
1554
1555#endif
1556
1557#ifdef WIN32
1558
1559  makefile = cmtdir + "NMake";
1560
1561  if (Cmt::get_debug ())
1562    {
1563      cout << "DefaultMakefileGenerator::build> pwd=" << CmtSystem::pwd () << " cmtdir=" << cmtdir << endl;
1564    }
1565
1566  if (!CmtSystem::test_file (makefile))
1567    {
1568      FILE* file = fopen (makefile.c_str (), "wb");
1569      if (file != NULL)
1570        {
1571          fprintf (file, "!include $(CMTROOT)\\src\\NMakefile.header\n");
1572          fprintf (file, "\n");
1573          fprintf (file, "!include $(CMTROOT)\\src\\constituents.nmake\n");
1574          fprintf (file, "\n");
1575          fclose (file);
1576        }
1577    }
1578
1579#endif
1580
1581}
1582
1583MSDEVGenerator::MSDEVGenerator ()
1584{
1585  dsw_header_fragment.set ("dsw_header");
1586  dsw_project_fragment.set ("dsw_project");
1587  dsw_all_project_header_fragment.set ("dsw_all_project_header");
1588  dsw_all_project_dependency_fragment.set ("dsw_all_project_dependency");
1589  dsw_all_project_trailer_fragment.set ("dsw_all_project_trailer");
1590  dsw_trailer_fragment.set ("dsw_trailer");
1591
1592  dsp_all_fragment.set ("dsp_all");
1593  dsp_library_header_fragment.set ("dsp_library_header");
1594  dsp_application_header_fragment.set ("dsp_application_header");
1595  dsp_windows_header_fragment.set ("dsp_windows_header");
1596  dsp_contents_fragment.set ("dsp_contents");
1597  dsp_trailer_fragment.set ("dsp_trailer");
1598}
1599
1600void MSDEVGenerator::reset ()
1601{
1602  CmtGenerator::reset ();
1603
1604  dsw_header_fragment.reset ();
1605  dsw_project_fragment.reset ();
1606  dsw_all_project_header_fragment.reset ();
1607  dsw_all_project_dependency_fragment.reset ();
1608  dsw_all_project_trailer_fragment.reset ();
1609  dsw_trailer_fragment.reset ();
1610
1611  dsp_all_fragment.reset ();
1612  dsp_library_header_fragment.reset ();
1613  dsp_application_header_fragment.reset ();
1614  dsp_windows_header_fragment.reset ();
1615  dsp_contents_fragment.reset ();
1616  dsp_trailer_fragment.reset ();
1617
1618  CmtSystem::cd (Cmt::get_current_dir ());
1619
1620  cmt_string branch = CmtSystem::current_branch ();
1621
1622  if ((branch == "mgr") || (branch == "cmt"))
1623    {
1624#ifdef WIN32
1625      msdevdir = "..";
1626      msdevdir += CmtSystem::file_separator ();
1627      msdevdir += "Visual";
1628     
1629      if (!CmtSystem::test_directory (msdevdir))
1630        {
1631          CmtSystem::mkdir (msdevdir);
1632        }
1633     
1634      msdevdir += CmtSystem::file_separator ();
1635#endif
1636    }
1637  else
1638    {
1639#ifdef WIN32
1640      msdevdir = ".";
1641      msdevdir += CmtSystem::file_separator ();
1642#endif
1643    }
1644
1645}
1646
1647int MSDEVGenerator::build_workspace (const Constituent::ConstituentVector& constituents)
1648{
1649  reset ();
1650
1651  const cmt_string& package = Cmt::get_current_package ();
1652
1653  m_output_file_name = msdevdir + package + ".dswnew";
1654
1655  m_output_file = fopen (m_output_file_name.c_str (), "wb");
1656  if (m_output_file != NULL)
1657    {
1658      m_PACKAGE = package;
1659      dsw_header_fragment.wincopy (m_output_file, 1,
1660                                   &m_PACKAGE);
1661
1662      int i;
1663
1664      dsw_all_project_header_fragment.wincopy (m_output_file, 1, 
1665                                               &m_PACKAGE);
1666
1667      for (i = 0; i < constituents.size (); i++)
1668        {
1669          const Constituent& constituent = constituents[i];
1670
1671          if (constituent.type == Library)
1672            {
1673              m_CONSTITUENT = constituent.name;
1674              m_CONSTITUENTSUFFIX = constituent.suffix;
1675              dsw_all_project_dependency_fragment.wincopy (m_output_file, constituent.variables, 3,
1676                                                           &m_PACKAGE,
1677                                                           &m_CONSTITUENT, 
1678                                                           &m_CONSTITUENTSUFFIX);
1679            }
1680          else
1681            {
1682              m_CONSTITUENT = constituent.name;
1683              m_CONSTITUENTSUFFIX = constituent.suffix;
1684              dsw_all_project_dependency_fragment.wincopy (m_output_file, constituent.variables, 3,
1685                                                           &m_PACKAGE,
1686                                                           &m_CONSTITUENT, 
1687                                                           &m_CONSTITUENTSUFFIX);
1688            }
1689
1690        }
1691
1692      dsw_all_project_trailer_fragment.wincopy (m_output_file,
1693                                                1, &m_PACKAGE);
1694
1695      for (i = 0; i < constituents.size (); i++)
1696        {
1697          const Constituent& constituent = constituents[i];
1698
1699          if (constituent.type == Library)
1700            {
1701              m_CONSTITUENT = constituent.name;
1702              m_CONSTITUENTSUFFIX = constituent.suffix;
1703              dsw_project_fragment.wincopy (m_output_file,
1704                                            constituent.variables, 3,
1705                                            &m_PACKAGE,
1706                                            &m_CONSTITUENT, 
1707                                            &m_CONSTITUENTSUFFIX);
1708            }
1709          else
1710            {
1711              m_CONSTITUENT = constituent.name;
1712              m_CONSTITUENTSUFFIX = constituent.suffix;
1713              dsw_project_fragment.wincopy (m_output_file, constituent.variables, 3, 
1714                                            &m_PACKAGE,
1715                                            &m_CONSTITUENT, 
1716                                            &m_CONSTITUENTSUFFIX);
1717            }
1718        }
1719
1720      dsw_trailer_fragment.wincopy (m_output_file, 1, &m_PACKAGE);
1721
1722      terminate ();
1723    }
1724
1725  m_output_file_name = msdevdir + "all.dspnew";
1726
1727  m_output_file = fopen (m_output_file_name.c_str (), "wb");
1728  if (m_output_file != NULL)
1729    {
1730      dsp_all_fragment.wincopy (m_output_file, 1, &m_PACKAGE);
1731      terminate ();
1732    }
1733
1734  return (0);
1735}
1736
1737//--------------------------------------------------
1738int MSDEVGenerator::build_project (const Constituent& constituent)
1739{
1740  reset ();
1741
1742  const cmt_string& package = Cmt::get_current_package ();
1743  static cmt_string file;
1744  static cmt_string full_name;
1745  static cmt_string suffix;
1746
1747  int i;
1748
1749  m_CONSTITUENT = constituent.name;
1750  m_CONSTITUENTSUFFIX = constituent.suffix;
1751
1752  for (i = 0; i < constituent.includes.size (); i++)
1753    {
1754      const cmt_string& include = constituent.includes[i];
1755      m_PACKINCLUDES += " -I" + include;
1756    }
1757
1758  switch (constituent.type)
1759    {
1760    case Application:
1761      is_application = true;
1762      m_TITLE = "Application";
1763      break;
1764    case Library:
1765      is_library = true;
1766      m_TITLE = "Library";
1767      break;
1768    case Document:
1769      m_GENERATOR = constituent.generator;
1770      m_TITLE = "Document";
1771      break;
1772    }
1773
1774  m_PACKOS9 = constituent.need_OS9;
1775
1776  const CmtSystem::cmt_string_vector& sources = constituent.modules;
1777  const cmt_vector<cmt_regexp>& excludes = constituent.exclude_exprs;
1778  const cmt_vector<cmt_regexp>& selects = constituent.select_exprs;
1779
1780  //--- Build the constituents fragment -----
1781
1782  m_output_file_name = msdevdir + m_CONSTITUENT + ".dspnew";
1783  m_output_file = fopen (m_output_file_name.c_str (), "wb");
1784
1785  if (m_output_file == NULL) return (0);
1786
1787  m_PACKAGE = package;
1788
1789  if (is_library)
1790    {
1791      if (constituent.no_share)
1792        {
1793          m_LIBRARYSUFFIX = "lib";
1794        }
1795      else
1796        {
1797          m_LIBRARYSUFFIX = "arc";
1798        }
1799
1800      dsp_library_header_fragment.wincopy (m_output_file, constituent.variables, 4,
1801                                           &m_PACKAGE,
1802                                           &m_CONSTITUENT, 
1803                                           &m_CONSTITUENTSUFFIX, 
1804                                           &m_LIBRARYSUFFIX);
1805    }
1806  else
1807    {
1808      if (constituent.windows)
1809        {
1810          dsp_windows_header_fragment.wincopy (m_output_file, constituent.variables, 3,
1811                                               &m_PACKAGE,
1812                                               &m_CONSTITUENT, 
1813                                               &m_CONSTITUENTSUFFIX);
1814        }
1815      else
1816        {
1817          dsp_application_header_fragment.wincopy (m_output_file, constituent.variables, 3,
1818                                                   &m_PACKAGE,
1819                                                   &m_CONSTITUENT, 
1820                                                   &m_CONSTITUENTSUFFIX);
1821        }
1822    }
1823
1824  for (i = 0; i < sources.size (); i++)
1825    {
1826      file = sources[i];
1827
1828      set_full_name (full_name, file);
1829      if (full_name == "") continue;
1830
1831      static CmtSystem::cmt_string_vector files;
1832
1833      get_all_files (full_name, excludes, selects, files);
1834
1835      for (int j = 0; j < files.size (); j++)
1836        {
1837          const cmt_string& name = files[j];
1838
1839          if (name != "") 
1840            {
1841              m_FULLNAME = name;
1842
1843              if (m_output_file != NULL)
1844                {
1845                  dsp_contents_fragment.wincopy (m_output_file, constituent.variables, 2, 
1846                                                 &m_PACKAGE, 
1847                                                 &m_FULLNAME);
1848                }
1849            }
1850        }
1851    }
1852
1853  if (m_output_file != NULL)
1854    {
1855      dsp_trailer_fragment.wincopy (m_output_file, constituent.variables, 3,
1856                                    &m_PACKAGE,
1857                                    &m_CONSTITUENT, 
1858                                    &m_CONSTITUENTSUFFIX);
1859
1860      terminate ();
1861    }
1862
1863  return (0);
1864}
1865
1866
1867VSNETGenerator::VSNETGenerator ()
1868{
1869  sln_header_fragment.set ("sln_header");
1870  sln_project_fragment.set ("sln_project");
1871  sln_dependency_header_fragment.set ("sln_dependency_header");
1872  sln_dependency_project_fragment.set ("sln_dependency_project");
1873  sln_dependency_trailer_fragment.set ("sln_dependency_trailer");
1874  sln_project_config_fragment.set ("sln_project_config");
1875  sln_trailer_fragment.set ("sln_trailer");
1876
1877  vcproj_all_fragment.set ("vcproj_all");
1878  vcproj_library_header_fragment.set ("vcproj_library_header");
1879  vcproj_application_header_fragment.set ("vcproj_application_header");
1880  vcproj_windows_header_fragment.set ("vcproj_windows_header");
1881  vcproj_contents_fragment.set ("vcproj_contents");
1882  vcproj_directory_header_fragment.set ("vcproj_directory_header");
1883  vcproj_directory_trailer_fragment.set ("vcproj_directory_trailer");
1884  vcproj_trailer_fragment.set ("vcproj_trailer");
1885}
1886
1887void VSNETGenerator::reset ()
1888{
1889  CmtGenerator::reset ();
1890
1891  CmtSystem::cd (Cmt::get_current_dir ());
1892
1893  cmt_string branch = CmtSystem::current_branch ();
1894
1895  if ((branch == "mgr") || (branch == "cmt"))
1896    {
1897#ifdef WIN32
1898      vsnetdir = "..";
1899      vsnetdir += CmtSystem::file_separator ();
1900      vsnetdir += "Visual";
1901     
1902      if (!CmtSystem::test_directory (vsnetdir))
1903        {
1904          CmtSystem::mkdir (vsnetdir);
1905        }
1906     
1907      vsnetdir += CmtSystem::file_separator ();
1908#endif
1909    }
1910  else
1911    {
1912#ifdef WIN32
1913      vsnetdir = ".";
1914      vsnetdir += CmtSystem::file_separator ();
1915#endif
1916    }
1917}
1918
1919void VSNETGenerator::pseudoGUID (const cmt_string& a, 
1920                                 const cmt_string& b, 
1921                                 const cmt_string& c, 
1922                                 cmt_string& d)
1923{
1924  char buf[64]; // make the guid in here
1925  static char hex[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
1926  int k = 0;
1927  int i;
1928
1929  for (i = 0; (i < c.size()) && (k < sizeof(buf)); ++i, ++k) buf[k] = c[i];
1930  for (i = 0; (i < a.size()) && (k < sizeof(buf)); ++i, ++k) buf[k] = a[i];
1931  for (i = 0; (i < b.size()) && (k < sizeof(buf)); ++i, ++k) buf[k] = b[i];
1932  for (; k < sizeof(buf); ++k) buf[k] = 0;
1933
1934  // now use the buffer to format the output string
1935  // example: {3FE091FC-3738-4F2E-9723-E846B43F77AB}
1936  d = '{';
1937  k = 0;
1938
1939  for (i = 0; i < 4; ++i, ++k) { d += hex[buf[k]&15]; d += hex[buf[k] >> 4]; } d += '-';
1940  for (i = 0; i < 2; ++i, ++k) { d += hex[buf[k]&15]; d += hex[buf[k] >> 4]; } d += '-';
1941  for (i = 0; i < 2; ++i, ++k) { d += hex[buf[k]&15]; d += hex[buf[k] >> 4]; } d += '-';
1942  for (i = 0; i < 2; ++i, ++k) { d += hex[buf[k]&15]; d += hex[buf[k] >> 4]; } d += '-';
1943  for (i = 0; i < 6; ++i, ++k) { d += hex[buf[k]&15]; d += hex[buf[k] >> 4]; } d += '}';
1944}
1945
1946int VSNETGenerator::build_workspace (const Constituent::ConstituentVector& constituents)
1947{
1948  reset ();
1949
1950  const cmt_string& package = Cmt::get_current_package ();
1951 
1952  m_output_file_name = vsnetdir + package + ".slnnew";
1953 
1954  Variable PACKAGE_GUID ("PACKAGE_GUID");
1955  Variable CONSTITUENT_GUID ("CONSTITUENT_GUID");
1956  Variable NUMBER ("NUMBER");
1957 
1958  cmt_string guid;
1959  pseudoGUID (package, Cmt::get_current_version(), "", guid);
1960  PACKAGE_GUID = guid;
1961 
1962  m_output_file = fopen (m_output_file_name.c_str (), "wb");
1963 
1964  if (m_output_file != NULL)
1965    {
1966      m_PACKAGE = package;
1967      sln_header_fragment.wincopy (m_output_file, 2, 
1968                                   &m_PACKAGE,
1969                                   &PACKAGE_GUID);
1970     
1971      int i;
1972     
1973      for (i = 0; i < constituents.size (); i++)
1974        {
1975          const Constituent& constituent = constituents[i];
1976         
1977          pseudoGUID (package, Cmt::get_current_version(), constituent.name, guid);
1978          CONSTITUENT_GUID = guid;
1979         
1980          if (constituent.type == Library)
1981            {
1982              m_CONSTITUENT = constituent.name;
1983              m_CONSTITUENTSUFFIX = constituent.suffix;
1984              sln_project_fragment.wincopy (m_output_file,
1985                                            constituent.variables, 4,
1986                                            &m_PACKAGE,
1987                                            &m_CONSTITUENT,
1988                                            &PACKAGE_GUID,
1989                                            &CONSTITUENT_GUID);
1990            }
1991          else
1992            {
1993              m_CONSTITUENT = constituent.name;
1994              m_CONSTITUENTSUFFIX = constituent.suffix;
1995              sln_project_fragment.wincopy (m_output_file, constituent.variables, 4,
1996                                            &m_PACKAGE,
1997                                            &m_CONSTITUENT,
1998                                            &PACKAGE_GUID,
1999                                            &CONSTITUENT_GUID);
2000            }
2001        }
2002     
2003      sln_dependency_header_fragment.wincopy (m_output_file,
2004                                              1, &m_PACKAGE);
2005     
2006      for (i = 0; i < constituents.size (); i++)
2007        {
2008          const Constituent& constituent = constituents[i];
2009          pseudoGUID (package, Cmt::get_current_version(), constituent.name, guid);
2010          CONSTITUENT_GUID = guid;
2011         
2012          cmt_string num;
2013          num = (char)('0' + i);
2014          NUMBER = num;
2015          if (constituent.type == Library)
2016            {
2017              m_CONSTITUENT = constituent.name;
2018              m_CONSTITUENTSUFFIX = constituent.suffix;
2019             
2020              sln_dependency_project_fragment.wincopy (m_output_file, constituent.variables, 5,
2021                                                       &m_PACKAGE,
2022                                                       &m_CONSTITUENT,
2023                                                       &PACKAGE_GUID,
2024                                                       &CONSTITUENT_GUID,
2025                                                       &NUMBER);
2026            }
2027          else
2028            {
2029              m_CONSTITUENT = constituent.name;
2030              m_CONSTITUENTSUFFIX = constituent.suffix;
2031              sln_dependency_project_fragment.wincopy (m_output_file, constituent.variables, 5,
2032                                                       &m_PACKAGE,
2033                                                       &m_CONSTITUENT,
2034                                                       &PACKAGE_GUID,
2035                                                       &CONSTITUENT_GUID, 
2036                                                       &NUMBER);
2037            }
2038        }
2039     
2040      sln_dependency_trailer_fragment.wincopy (m_output_file,
2041                                               1, &m_PACKAGE);
2042     
2043      for (i = 0; i < constituents.size (); i++)
2044        {
2045          const Constituent& constituent = constituents[i];
2046          pseudoGUID (package, Cmt::get_current_version(), constituent.name, guid);
2047          CONSTITUENT_GUID = guid;
2048         
2049          if (constituent.type == Library)
2050            {
2051              m_CONSTITUENT = constituent.name;
2052              m_CONSTITUENTSUFFIX = constituent.suffix;
2053              sln_project_config_fragment.wincopy (m_output_file,
2054                                                   constituent.variables, 3,
2055                                                   &m_PACKAGE,
2056                                                   &m_CONSTITUENT,
2057                                                   &CONSTITUENT_GUID);
2058            }
2059          else
2060            {
2061              m_CONSTITUENT = constituent.name;
2062              m_CONSTITUENTSUFFIX = constituent.suffix;
2063              sln_project_config_fragment.wincopy (m_output_file, constituent.variables, 3,
2064                                                   &m_PACKAGE,
2065                                                   &m_CONSTITUENT,
2066                                                   &CONSTITUENT_GUID);
2067            }
2068        }
2069     
2070      sln_trailer_fragment.wincopy (m_output_file, 1, &m_PACKAGE);
2071
2072      terminate ();
2073    }
2074 
2075  m_output_file_name = vsnetdir + "all.vcprojnew";
2076 
2077  m_output_file = fopen (m_output_file_name.c_str (), "wb");
2078  if (m_output_file != NULL)
2079    {
2080      vcproj_all_fragment.wincopy (m_output_file, 1, &m_PACKAGE);
2081
2082      terminate ();
2083    }
2084 
2085  return (0);
2086}
2087
2088int VSNETGenerator::build_project (const Constituent& constituent)
2089{
2090  reset ();
2091 
2092  const cmt_string& package = Cmt::get_current_package();
2093  static cmt_string file;
2094  static cmt_string full_name;
2095  static cmt_string suffix;
2096 
2097  static Variable GUID("GUID");
2098  int i;
2099 
2100  // Directory Support
2101  int dir_pos;
2102  int file_pos;
2103  int src_pos;
2104  int iSFFilter = 0;
2105  cmt_string directory;
2106  cmt_string new_dir;
2107  bool need_trailer = false;
2108
2109  m_CONSTITUENT = constituent.name;
2110  // make up a pseudo-GUID from the constituent-pacakge-version combination
2111 
2112  cmt_string guid;
2113  pseudoGUID (package, Cmt::get_current_version(), constituent.name, guid);
2114 
2115  GUID = guid;
2116 
2117  for (i = 0; i < constituent.includes.size (); i++)
2118    {
2119      const cmt_string& include = constituent.includes[i];
2120      m_PACKINCLUDES += " -I" + include;
2121    }
2122 
2123  switch (constituent.type)
2124    {
2125    case Application:
2126      is_application = true;
2127      m_TITLE = "Application";
2128      break;
2129    case Library:
2130      is_library = true;
2131      m_TITLE = "Library";
2132      break;
2133    case Document:
2134      m_GENERATOR = constituent.generator;
2135      m_TITLE = "Document";
2136      break;
2137    }
2138 
2139  m_PACKOS9 = constituent.need_OS9;
2140 
2141  const CmtSystem::cmt_string_vector& sources = constituent.modules;
2142  const cmt_vector<cmt_regexp>& excludes = constituent.exclude_exprs;
2143  const cmt_vector<cmt_regexp>& selects = constituent.select_exprs;
2144 
2145  //--- Build the constituents fragment -----
2146  cmt_string output;
2147 
2148  m_output_file_name = vsnetdir + m_CONSTITUENT + ".vcprojnew";
2149  m_output_file = fopen (m_output_file_name.c_str (), "wb");
2150 
2151  if (m_output_file == NULL) return (0);
2152 
2153  m_PACKAGE = package;
2154 
2155  if (is_library)
2156    {
2157      if (constituent.no_share)
2158        {
2159          m_LIBRARYSUFFIX = "lib";
2160        }
2161      else
2162        {
2163          m_LIBRARYSUFFIX = "arc";
2164        }
2165     
2166      vcproj_library_header_fragment.wincopy (m_output_file, constituent.variables, 4,
2167                                              &m_PACKAGE,
2168                                              &m_CONSTITUENT,
2169                                              &GUID,
2170                                              &m_LIBRARYSUFFIX);
2171    }
2172  else
2173    {
2174      if (constituent.windows)
2175        {
2176          vcproj_windows_header_fragment.wincopy (m_output_file, constituent.variables, 3,
2177                                                  &m_PACKAGE,
2178                                                  &m_CONSTITUENT,
2179                                                  &GUID);
2180        }
2181      else
2182        {
2183          vcproj_application_header_fragment.wincopy (m_output_file, constituent.variables, 3,
2184                                                      &m_PACKAGE,
2185                                                      &m_CONSTITUENT,
2186                                                      &GUID);
2187        }
2188    }
2189 
2190  for (i = 0; i < sources.size (); i++)
2191    {
2192      file = sources[i];
2193     
2194      set_full_name (full_name, file);
2195      if (full_name == "") continue;
2196     
2197      static CmtSystem::cmt_string_vector files;
2198     
2199      get_all_files (full_name, excludes, selects, files);
2200     
2201      for (int j = 0; j < files.size (); j++)
2202        {
2203          const cmt_string& name = files[j];
2204         
2205          if (name != "")
2206            {
2207              m_FULLNAME = name;
2208
2209              // Add Directory Support here
2210              // Step 1: Parse into "..\src\" "directory" "\filename.cxx"
2211
2212              // find ..\ ;
2213              src_pos = name.find('\\');
2214              // Finds ..\src\ ;
2215              dir_pos = name.find(src_pos+1, '\\') + 1;
2216              // Finds ..\src\..\astro\ ;
2217              file_pos = name.find_last_of('\\');
2218             
2219              // Debug only
2220              //printf("%40s, %i, %i, %i;\n", name src_pos, dir_pos, file_pos);
2221              // If dir_pos == file_pos, then we have ../src/filename.cxx
2222              // If dir_pos >  file_pos, then we have ../filename.cxx or something odd.
2223                           
2224              // Step 2: see if it is or is not a ../src/ directory.
2225              if ((dir_pos < file_pos) && (dir_pos > src_pos))
2226                {
2227                  new_dir = name.substr (dir_pos, file_pos-dir_pos);
2228                  new_dir.replace( "..\\", ""); // All names are relative to package/Visual,
2229                                                // so we want to ditch the prevailing ..\ ;
2230                                                // which all of them have.
2231                }
2232              else
2233                {
2234                  new_dir = "Source Files NN";
2235                }
2236
2237              // Step 3: Add directory structure to vcproj file.
2238              if (new_dir != directory) // Detects a change in directory
2239                {
2240                  directory = new_dir;
2241                  // Step 3a: Add a </Filter> when neccessary.
2242                  if (need_trailer == false)
2243                    {
2244                      // Ensure that no trailing </Filter> is placed incorrectly.
2245                      need_trailer = true;
2246                    }
2247                  else
2248                    {
2249                      vcproj_directory_trailer_fragment.wincopy (m_output_file,
2250                                                                 constituent.variables, 1,
2251                                                                 &m_PACKAGE);
2252                    }
2253
2254                  // Step 3b: Add a <Filter> when neccessary.
2255                  if ((dir_pos < file_pos) && (dir_pos > src_pos))
2256                    {
2257                      // Add <Filter Name="directory">
2258                      m_DIRNAME = new_dir;
2259                      vcproj_directory_header_fragment.wincopy (m_output_file, constituent.variables, 2,
2260                                                                &m_PACKAGE,
2261                                                                &m_DIRNAME);
2262                    }
2263                  else
2264                    {
2265                      // Ensure that no </Filter> is placed incorrectly.
2266                      // This is the case of the file being in ../src
2267                      // which requires no directory. Thus no filter start or end tag is needed.
2268
2269                      need_trailer = false;
2270                    }
2271                }
2272
2273              if (m_output_file != NULL)
2274                {
2275                  vcproj_contents_fragment.wincopy (m_output_file, constituent.variables, 2,
2276                                                    &m_PACKAGE,
2277                                                    &m_FULLNAME);
2278                }
2279            }
2280        }
2281    }
2282
2283  if (need_trailer == true)
2284    {
2285      // Add a trailing </Filter> for directory support.
2286      vcproj_directory_trailer_fragment.wincopy (m_output_file, constituent.variables, 1,
2287                                                 &m_PACKAGE);
2288    }
2289
2290  if (m_output_file != NULL)
2291    {
2292      vcproj_trailer_fragment.wincopy (m_output_file, constituent.variables, 3,
2293                                       &m_PACKAGE,
2294                                       &m_CONSTITUENT,
2295                                       &m_CONSTITUENTSUFFIX);
2296
2297      terminate ();
2298    }
2299
2300  return (0);
2301}
2302
2303MakeSetupGenerator::MakeSetupGenerator ()
2304{
2305  make_setup_header_fragment.set ("make_setup_header");
2306  make_setup_fragment.set ("make_setup");
2307}
2308
2309void MakeSetupGenerator::reset ()
2310{
2311  CmtGenerator::reset ();
2312
2313  make_setup_header_fragment.reset ();
2314  make_setup_fragment.reset ();
2315}
2316
2317void MakeSetupGenerator::build (const cmt_string& package)
2318{
2319  reset ();
2320
2321  m_PACKAGE = package;
2322
2323  cmt_string file_name = "setup.";
2324
2325  if (Cmt::build_nmake ())
2326    {
2327      file_name += "nmake";
2328    }
2329  else
2330    {
2331      file_name += "make";
2332    }
2333 
2334  cmt_string new_file_name = file_name;
2335  new_file_name += "new";
2336
2337  m_output_file = fopen (new_file_name, "wb");
2338
2339  if (m_output_file != NULL)
2340    {
2341      int number;
2342
2343      const Use::UsePtrVector& uses = Use::get_ordered_uses ();
2344
2345      const Constituent::ConstituentVector& constituents =
2346        Constituent::constituents ();
2347
2348      cmt_string temp;
2349
2350      make_setup_header_fragment.copy (m_output_file, 1, &m_PACKAGE);
2351
2352      for (number = 0; number < uses.size (); number++)
2353        {
2354          const Use* use = uses[number];
2355
2356          if (use->discarded) continue;
2357
2358          if (use->real_path != "")
2359            {
2360              temp  = use->prefix;
2361              temp += "ROOT = ";
2362              temp += use->get_full_path ();
2363
2364              fprintf (m_output_file, "%s\n", temp.c_str());
2365            }
2366        }
2367
2368      temp  = "use_requirements = ";
2369      temp += "requirements ";
2370
2371      for (number = 0; number < uses.size (); number++)
2372        {
2373          const Use* use = uses[number];
2374
2375          if (use->discarded) continue;
2376
2377          if (use->real_path != "")
2378            {
2379              temp += "$(";
2380              temp += use->prefix;
2381              temp += "ROOT)";
2382              temp += CmtSystem::file_separator ();
2383              switch (use->style)
2384                {
2385                case cmt_style:
2386                  temp += "cmt";
2387                  break;
2388                case mgr_style:
2389                  temp += "mgr";
2390                  break;
2391                }
2392              temp += CmtSystem::file_separator ();
2393              temp += "requirements ";
2394            }
2395        }
2396
2397      fprintf (m_output_file, "%s\n", temp.c_str());
2398
2399      temp  = "constituents = $(constituents)";
2400      Symbol::expand (temp);
2401
2402      fprintf (m_output_file, "%s\n", temp.c_str());
2403
2404      make_setup_fragment.copy (m_output_file, 1, &m_PACKAGE);
2405
2406      fclose (m_output_file);
2407
2408      //--- Complete the operation --------------
2409
2410      commit (new_file_name);
2411    }
2412
2413  /*
2414    for option in $*
2415    do
2416    case ${option} in
2417    args-tag=*)
2418    tag=${option}
2419    tag=`echo "${tag}" | sed -e 's/args.tag=//'`
2420    ;;
2421    -tag=*)
2422    tag=args${option}
2423    tag=`echo "${tag}" | sed -e 's/args.tag=//'`
2424    ;;
2425    esac
2426    done
2427
2428    if test "${tag}" = "" ; then
2429    tag=${CMTCONFIG}
2430    fi
2431
2432    build_shell_setup_files ${tag}
2433
2434    now=`date`
2435
2436  */
2437}
2438
2439ConstituentsMakefileGenerator::ConstituentsMakefileGenerator ()
2440{
2441  constituents_header_fragment.set ("constituents_header");
2442  constituents_trailer_fragment.set ("constituents_trailer");
2443  group_fragment.set ("group");
2444  constituent_fragment.set ("constituent");
2445  constituent_lock_fragment.set ("constituent_lock");
2446  check_application_header_fragment.set ("check_application_header");
2447}
2448
2449void ConstituentsMakefileGenerator::reset ()
2450{
2451  CmtGenerator::reset ();
2452  constituents_header_fragment.reset ();
2453  constituents_trailer_fragment.reset ();
2454  group_fragment.reset ();
2455  constituent_fragment.reset ();
2456  constituent_lock_fragment.reset ();
2457  check_application_header_fragment.reset ();
2458}
2459
2460//--------------------------------------------------
2461void ConstituentsMakefileGenerator::build (const cmt_string& package,
2462                                           const CmtSystem::cmt_string_vector& arguments)
2463{
2464  reset ();
2465
2466  cmt_string file_name;
2467
2468  if (arguments.size () > 0)
2469    {
2470      cmt_string arg = arguments[0];
2471      if (arg.substr (0, 5) == "-out=")
2472        {
2473          arg.erase (0, 5);
2474          file_name = arg;
2475        }
2476    }
2477
2478  if (file_name == "")
2479    {
2480      file_name = "constituents.";
2481
2482      //--- Build the constituents fragment -----
2483
2484      if (Cmt::build_nmake ())
2485        {
2486          file_name += "nmake";
2487        }
2488      else
2489        {
2490          file_name += "make";
2491        }
2492    }
2493
2494  cmt_string save_file_name = file_name;
2495  save_file_name += "cmtsave";
2496
2497  if (CmtSystem::test_file (file_name))
2498    {
2499      rename (file_name, save_file_name);
2500    }
2501
2502  cmt_string new_file_name = file_name;
2503  new_file_name += "new";
2504
2505  m_output_file = fopen (new_file_name, "wb");
2506  if (m_output_file != NULL)
2507    {
2508      int number;
2509      const Constituent::ConstituentVector&
2510        constituents = Constituent::constituents ();
2511
2512      m_PACKAGE = package;
2513
2514      constituents_header_fragment.copy (m_output_file, 1, &m_PACKAGE);
2515
2516      m_GROUP = "all";
2517      group_fragment.copy (m_output_file, 1, &m_GROUP);
2518
2519      const Group::GroupVector& groups = Group::groups ();
2520
2521      for (number = 0; number < groups.size (); number++)
2522        {
2523          const Group& group = groups[number];
2524
2525          m_GROUP = group.name ();
2526
2527          group_fragment.copy (m_output_file, 1, &m_GROUP);
2528        }
2529     
2530      bool lock = false;
2531      Symbol* lock_command_macro = Symbol::find ("lock_command");
2532      if (lock_command_macro != 0)
2533        {
2534          cmt_string lock_command = lock_command_macro->resolve_macro_value ();
2535          if (lock_command != "")
2536            {
2537              Symbol* unlock_command_macro = Symbol::find ("unlock_command");
2538              if (unlock_command_macro != 0)
2539                {
2540                  cmt_string unlock_command = unlock_command_macro->resolve_macro_value ();
2541                  if (unlock_command != "")
2542                    {
2543                      lock = true;
2544                    }
2545                }
2546            }
2547        }
2548      for (number = 0; number < constituents.size (); number++)
2549        {
2550          const Constituent& constituent = constituents[number];
2551
2552          m_CONSTITUENT = constituent.name;
2553          m_CONSTITUENTSUFFIX = constituent.suffix;
2554
2555          m_LINE = "";
2556
2557          if (constituent.has_target_tag)
2558            {
2559              m_HASTARGETTAG = "has_target_tag";
2560            }
2561          else
2562            {
2563              m_HASTARGETTAG = "has_no_target_tag";
2564            }
2565
2566          if (constituent.type == Document && lock == true)
2567            {
2568              constituent_lock_fragment.copy (m_output_file, constituent.variables,
2569                                              5,
2570                                              &m_PACKAGE,
2571                                              &m_CONSTITUENT, 
2572                                              &m_CONSTITUENTSUFFIX,
2573                                              &m_LINE,
2574                                              &m_HASTARGETTAG);
2575            }
2576          else
2577            {
2578              constituent_fragment.copy (m_output_file, constituent.variables,
2579                                         5,
2580                                         &m_PACKAGE,
2581                                         &m_CONSTITUENT, 
2582                                         &m_CONSTITUENTSUFFIX,
2583                                         &m_LINE,
2584                                         &m_HASTARGETTAG);
2585            }
2586
2587          if (constituent.need_check)
2588            {
2589              check_application_header_fragment.copy (m_output_file, 
2590                                                      constituent.variables, 3,
2591                                                      &m_PACKAGE,
2592                                                      &m_CONSTITUENT,
2593                                                      &m_CONSTITUENTSUFFIX);
2594            }
2595        }
2596
2597      constituents_trailer_fragment.copy (m_output_file, 0);
2598
2599      fclose (m_output_file);
2600
2601      commit (new_file_name);
2602    }
2603}
2604
2605
2606
2607
2608/**
2609   With this Awk filter, we analyze an existing dependency file.
2610   We get the source name in each line
2611   The list of sources is maintained in m_sources
2612   A source is stored in the form <name>_<suffix> (instead of <name>.<suffix>)
2613*/
2614class DependencyFilter : public Awk
2615{
2616public:
2617  DependencyFilter ()
2618  {
2619  }
2620
2621  void begin ()
2622  {
2623    m_sources = "";
2624  }
2625
2626  void filter (const cmt_string& line)
2627  {
2628    int pos = line.find ("_dependencies = ");
2629    if (pos == cmt_string::npos) return;
2630
2631    cmt_string s = line;
2632    s.erase (pos);
2633
2634    m_sources += " ";
2635    m_sources += s;
2636    m_sources += " ";
2637
2638    //pos = s.find_last_of ("_");
2639    //if (pos != cmt_string::npos) s[pos] = "."
2640  }
2641
2642  void add_source (const cmt_string& file_name)
2643  {
2644    static cmt_string suffix;
2645    static cmt_string name;
2646
2647    CmtSystem::get_dot_suffix (file_name, suffix);
2648    CmtSystem::basename (file_name, suffix, name);
2649    CmtSystem::get_suffix (file_name, suffix);
2650
2651    cmt_string s = " ";
2652    s += name;
2653    s += "_";
2654    s += suffix;
2655    s += " ";
2656
2657    if (m_sources.find (s) == cmt_string::npos)
2658      {
2659        m_sources += s;
2660      }       
2661  }
2662
2663  bool has_source (const cmt_string& file_name) const
2664  {
2665    static cmt_string suffix;
2666    static cmt_string name;
2667
2668    CmtSystem::get_dot_suffix (file_name, suffix);
2669    CmtSystem::basename (file_name, suffix, name);
2670    CmtSystem::get_suffix (file_name, suffix);
2671
2672    cmt_string s = " ";
2673    s += name;
2674    s += "_";
2675    s += suffix;
2676    s += " ";
2677
2678    if (m_sources.find (s) == cmt_string::npos)
2679      {
2680        return (false);
2681      }
2682    else
2683      {
2684        return (true);
2685      }
2686  }
2687
2688  cmt_string& get_sources ()
2689  {
2690    return (m_sources);
2691  }
2692
2693private:
2694  cmt_string m_sources;
2695};
2696
2697void DependencyGenerator::build (const CmtSystem::cmt_string_vector& arguments)
2698{
2699  reset ();
2700  prepare_use_context ();
2701
2702  prepare_header_file_filters ();
2703
2704  const cmt_string& name = arguments[0];
2705
2706  m_constituent = Constituent::find (name);
2707  if (m_constituent == 0)
2708    {
2709      // Error : wrong constituent name...
2710      return;
2711    }
2712
2713  const Constituent& constituent = *m_constituent;
2714
2715  cmt_string file_name;
2716  cmt_string full_name;
2717  cmt_string compressed_name;
2718  //  cmt_string suffix;
2719  cmt_string dependencies;
2720
2721  //
2722  // Scan the sources.
2723  //
2724
2725  //
2726  //  We have to rebuild the dependencies for :
2727  //
2728  //   o all sources if the parameter -all_sources has been received
2729  //   o otherwise,
2730  //      + all source names provided in the argument list (if any)
2731  //      + all source names missing from the existing dependency file (if any)
2732  //
2733
2734  const CmtSystem::cmt_string_vector& sources = constituent.modules;
2735  const cmt_vector<cmt_regexp>& excludes = constituent.exclude_exprs;
2736  const cmt_vector<cmt_regexp>& selects = constituent.select_exprs;
2737
2738  m_stamps = true;
2739  bool all_sources = false;
2740
2741  int source_number = arguments.size ();
2742  int i;
2743
2744  //cerr << "source_number=" << source_number << endl;
2745
2746  for (i = source_number-1; i >= 0; i--)
2747    {
2748      file_name = arguments[i];
2749
2750      //cerr << "file_name=" << file_name << endl;
2751
2752      // Get rid of files that may come from the makefile fragment
2753      if (file_name.find ("requirements") != cmt_string::npos) source_number--;
2754      else if (file_name.substr (0, 5) == "-out=" ||
2755               file_name.substr (0, 5) == "-out:" ||
2756               file_name.substr (0, 5) == "/out:" ||
2757               file_name.substr (0, 5) == "/out=")
2758        {
2759          source_number--;
2760          file_name.erase (0, 5);
2761          m_output_file_name = file_name;
2762        }
2763      else if (file_name.find (".make") != cmt_string::npos) source_number--;
2764      else if (file_name == "-all_sources" ||
2765               file_name == "/all_sources") 
2766        {
2767          source_number = sources.size ();
2768          all_sources = true;
2769        }
2770      else if (file_name == "-no_stamps" ||
2771               file_name == "/no_stamps") 
2772        {
2773          source_number--;
2774          m_stamps = false;
2775        }
2776    }
2777
2778  //
2779  // Now prepare the output file names
2780  //
2781  cmt_string branch = CmtSystem::current_branch ();
2782
2783  if ((branch == "mgr") || (branch == "cmt"))
2784    {
2785      Use& current_use = Use::current ();
2786
2787      Package* p = current_use.get_package ();
2788
2789      if (p->is_cmt ())
2790        {
2791          //          m_bin = "../";
2792          m_bin = "..";
2793          m_bin += CmtSystem::file_separator ();
2794          m_bin += CmtSystem::getenv ("CMTBIN");
2795          m_bin += CmtSystem::file_separator ();
2796        }
2797      else if (m_output_file_name != "")
2798        {
2799          CmtSystem::dirname (m_output_file_name, m_bin);
2800          if (m_bin == "")
2801            {
2802              m_bin = ".";
2803            }
2804          m_bin += CmtSystem::file_separator ();
2805        }
2806      else
2807        {
2808          m_bin = "${bin}";
2809        }
2810
2811      Symbol::expand (m_bin);
2812
2813      //cerr << "m_output_file_name=" << m_output_file_name << endl;
2814      //cerr << "current_tag=" << Cmt::current_tag << endl;
2815    }
2816  else
2817    {
2818      m_bin = ".";
2819      m_bin += CmtSystem::file_separator ();
2820    }
2821
2822  if (m_output_file_name == "")
2823    {
2824      m_output_file_name = m_bin;
2825      m_output_file_name += name;
2826      m_output_file_name += "_";
2827      m_output_file_name += "dependencies.";
2828      if (Cmt::build_nmake ())
2829        {
2830          m_output_file_name += "nmake";
2831        }
2832      else
2833        {
2834          m_output_file_name += "make";
2835        }
2836    }
2837
2838  if (all_sources)
2839    {
2840      for (i = 0; i < sources.size (); i++)
2841        {
2842          file_name = sources[i];
2843         
2844          set_full_name (full_name, file_name);
2845          if (full_name == "") continue;
2846
2847          CmtSystem::compress_path (full_name, compressed_name);
2848          full_name = compressed_name;
2849         
2850          static CmtSystem::cmt_string_vector files;
2851
2852          get_all_files (full_name, excludes, selects, files);
2853
2854          for (int j = 0; j < files.size (); j++)
2855            {
2856              const cmt_string& name = files[j];
2857             
2858              if (name != "") 
2859                {
2860                  const cmt_string& line = build (name);
2861                 
2862                  add_line_to_text (line, dependencies);
2863                }
2864            }
2865        }
2866    }
2867  else
2868    {
2869      //
2870      // New read the existing dependency file if any and filter it to
2871      // extract the source names
2872      //
2873      static DependencyFilter filter;
2874      dependencies.read (m_output_file_name);
2875      filter.run (dependencies);
2876     
2877      for (i = 1; i < source_number; i++)
2878        {
2879          file_name = arguments[i];
2880
2881          set_full_name (full_name, file_name);
2882          if (full_name == "") continue;
2883
2884          CmtSystem::compress_path (full_name, compressed_name);
2885          full_name = compressed_name;
2886         
2887          const cmt_string& line = build (full_name);
2888                 
2889          add_line_to_text (line, dependencies);
2890
2891          filter.add_source (full_name);
2892
2893        }
2894
2895      // Now : are there still any missing source file in dependencies??
2896
2897      for (i = 0; i < sources.size (); i++)
2898        {
2899          file_name = sources[i];
2900         
2901          set_full_name (full_name, file_name);
2902          if (full_name == "") continue;
2903         
2904          CmtSystem::compress_path (full_name, compressed_name);
2905          full_name = compressed_name;
2906         
2907          static CmtSystem::cmt_string_vector files;
2908         
2909          get_all_files (full_name, excludes, selects, files);
2910
2911          for (int j = 0; j < files.size (); j++)
2912            {
2913              const cmt_string& name = files[j];
2914              if (name != "") 
2915                {
2916                  if (!filter.has_source (name))
2917                    {
2918                      const cmt_string& line = build (name);
2919                 
2920                      add_line_to_text (line, dependencies);
2921                    }
2922                }
2923            }
2924        }
2925    }
2926
2927  FILE* f = fopen (m_output_file_name.c_str (), "wb");
2928
2929  if (f == 0)
2930    {
2931      CmtMessage::error ("Cannot open " + m_output_file_name + " for write");
2932      //      cerr << "Cannot open " << m_output_file_name << " for write" << endl;
2933    }
2934  else
2935    {
2936      dependencies.write (f);
2937      fclose (f);
2938    }
2939
2940//  m_deps_builder.clear ();
2941}
2942
2943//--------------------------------------------------
2944//  o text contains lines with a pattern like :
2945//      key = xxxxx
2946//
2947//  o line follows the same pattern
2948//
2949//   This function appends <line> to <text> only if the key found in
2950//  <line> is not found in <text>
2951//--------------------------------------------------
2952void DependencyGenerator::add_line_to_text (const cmt_string& line, cmt_string& text)
2953{
2954  static const cmt_string empty;
2955
2956  int pos = line.find (" = ");
2957  if (pos != cmt_string::npos)
2958    {
2959      static cmt_string key;
2960      line.substr (0, pos + 3, key);
2961      pos = text.find (key);
2962      if (pos != cmt_string::npos)
2963        {
2964          // The key in line exists in text.
2965          // Now check if the key is exactly the same.
2966
2967          if ((pos == 0) || (text[pos -1] == '\n'))
2968            {
2969              // The key is either in the first line or
2970              // exactly matches '^key = ...'
2971
2972              int nl = text.find (pos, "\n");
2973              if (nl != cmt_string::npos)
2974                {
2975                  static cmt_string old;
2976                  text.substr (pos, nl - pos + 1, old);
2977                  text.replace (old, empty);
2978                }
2979              else
2980                {
2981                  text.erase (pos);
2982                }
2983            }
2984        }
2985    }
2986  if (line != "")
2987    {
2988      text += line;
2989      text += "\n";
2990    }
2991}
2992
2993cmt_string DependencyGenerator::build (const cmt_string& file_name)
2994{
2995  Log;
2996
2997  const Constituent& constituent = *m_constituent;
2998
2999  static cmt_string full_name;
3000  static cmt_string suffix;
3001  static cmt_string name;
3002  static cmt_string line;
3003
3004  full_name = "";
3005  line = "";
3006
3007  if (!CmtSystem::absolute_path (file_name))
3008    {
3009      full_name = srcdir;
3010    }
3011
3012  full_name += file_name;
3013
3014  CmtSystem::get_dot_suffix (full_name, suffix);
3015  CmtSystem::basename (full_name, suffix, name);
3016  CmtSystem::get_suffix (full_name, suffix);
3017
3018  if (name == "requirements") return (line);
3019
3020  const CmtSystem::cmt_string_vector& deps = m_deps_builder.run (full_name);
3021
3022  line  = name;
3023  line += "_";
3024  line += suffix;
3025  line += "_dependencies = ";
3026
3027  filter_path (full_name);
3028
3029#ifdef WIN32
3030  static const char quote = '\"';
3031#else
3032  static const char quote = ' ';
3033#endif
3034
3035  line += quote;
3036  line += full_name;
3037  line += quote;
3038
3039  for (int j = 0; j < deps.size (); j++)
3040    {
3041      cmt_string d = deps[j];
3042
3043      log << "dep line = " << d << log_endl;
3044
3045      filter_path (d);
3046
3047      log << "filtered dep line = " << d << log_endl;
3048
3049      line += " ";
3050      line += quote;
3051      line += d;
3052      line += quote;
3053    }
3054
3055  Symbol::expand (line);
3056
3057  if (m_stamps)
3058    {
3059      cmt_string stamp_output_base = constituent.name;
3060      stamp_output_base += "_deps";
3061
3062      cmt_string stamp_output = m_bin;
3063      stamp_output += stamp_output_base;
3064
3065      if (!CmtSystem::mkdir (stamp_output))
3066        {
3067          CmtMessage::error ("Cannot create the binary output directory for this constituent " + stamp_output);
3068          //      cerr << "Cannot create the binary output directory for this constituent" << endl;
3069        }
3070
3071      stamp_output_base += CmtSystem::file_separator ();
3072      stamp_output_base += name;
3073      stamp_output_base += "_";
3074      stamp_output_base += suffix;
3075      stamp_output_base += ".stamp";
3076
3077      stamp_output = m_bin;
3078      stamp_output += stamp_output_base;
3079     
3080      line += " $(bin)";
3081      line += stamp_output_base;
3082     
3083      cmt_string old_stamp;
3084     
3085      if (CmtSystem::test_file (stamp_output))
3086        {
3087          old_stamp.read (stamp_output);
3088        }
3089
3090      if (line != old_stamp)
3091        {
3092          line.write (stamp_output);
3093        }
3094    }
3095
3096  return (line);
3097}
3098
3099//--------------------------------------------------
3100void DependencyGenerator::prepare_header_file_filters ()
3101{
3102//   Use::UsePtrVector& uses = Use::get_ordered_uses ();
3103  Use::UsePtrVector uses (Use::get_ordered_uses ());
3104  uses.push_back (&Use::current ());
3105  for (int i = uses.size () - 1; i >= 0; i--)
3106    {
3107      Use* use = uses[i];
3108      if (use->discarded) continue;
3109      if (use->m_hidden) continue;
3110      if (!use->located ()) continue;
3111
3112      cmt_string package_name = use->get_package_name ();
3113      if (package_name == "CMT") continue;
3114
3115      Symbol* filter_macro = Symbol::find (package_name + "_header_file_filter");
3116      if (filter_macro == 0) continue;
3117
3118      Symbol* stamp_macro = Symbol::find (package_name + "_header_file_stamp");
3119      cmt_string stamp;
3120      if (stamp_macro != 0)
3121        {
3122          stamp = stamp_macro->resolve_macro_value ();
3123        }
3124      else
3125        {
3126          use->get_full_path (stamp);
3127          stamp += CmtSystem::file_separator ();
3128          if (use->style == mgr_style) stamp += "mgr";
3129          else stamp += "cmt";
3130          stamp += CmtSystem::file_separator ();
3131          stamp += "cmt_header_file.stamp";
3132          //stamp += "cmt_all_headers.stamp";
3133          //<package>/cmt/cmt_all_headers.stamp
3134        }
3135      if (!CmtSystem::test_file (stamp)) continue;
3136
3137      cmt_regexp* filter = new cmt_regexp (filter_macro->resolve_macro_value ());
3138      assert (filter != 0);
3139
3140      m_deps_builder.add_header_filter (use, filter, stamp);
3141    }
3142}
Note: See TracBrowser for help on using the repository browser.