source: CMT/v1r20p20070208/source/cmt_generators.cxx

Last change on this file was 197, checked in by garonne, 18 years ago

add the STRUCTURED_OUTPUT support on linux +mac

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