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

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

See C.L. 370

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