source: CMT/v1r18p20041201/source/cmt_generators.cxx @ 1

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

Import all tags

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