source: CMT/v1r20p20080222/source/cmt_generators.cxx @ 653

Last change on this file since 653 was 429, checked in by rybkin, 17 years ago

See C.L. 335

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