source: CMT/v1r20p20080222/source/cmt_generator.cxx

Last change on this file was 428, checked in by rybkin, 17 years ago

See C.L. 334

  • Property svn:eol-style set to native
File size: 19.8 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 <errno.h>
8#include <stdio.h>
9
10#ifndef WIN32
11#include <unistd.h>
12#endif
13
14#include "cmt_generator.h"
15#include "cmt_use.h"
16#include "cmt_symbol.h"
17
18#include "cmt_generators.h"
19
20//------------------------------------------------------------------------
21void SourceFile::set (const cmt_string name, Language& language, const cmt_string output)
22{
23  m_name = name;
24  m_language = &language;
25  m_output = output;
26 
27  CmtSystem::reduce_file_separators (m_name);
28}
29
30cmt_string SourceFile::name () const
31{
32  return (m_name);
33}
34
35Language& SourceFile::language () const
36{
37  return (*m_language);
38}
39
40cmt_string SourceFile::output () const
41{
42  return (m_output);
43}
44//------------------------------------------------------------------------
45
46//--------------------------------------------------
47CmtGenerator::CmtGenerator ()
48{
49  m_CONSTITUENT.set ("CONSTITUENT");
50  m_LINKMACRO.set ("LINKMACRO");
51  m_DOCPATH.set ("DOCPATH");
52  m_PACKAGEPATH.set ("PACKAGEPATH");
53  m_PACKAGEPREFIX.set ("PACKAGEPREFIX");
54  m_PACKAGE.set ("PACKAGE");
55  m_VERSION.set ("VERSION");
56  m_MGRSTYLE.set ("MGRSTYLE");
57  m_TITLE.set ("TITLE");
58  m_GROUP.set ("GROUP");
59  m_CONSTITUENT.set ("CONSTITUENT");
60  m_CONSTITUENTSUFFIX.set ("CONSTITUENTSUFFIX");
61  m_LIBRARYSUFFIX.set ("LIBRARYSUFFIX");
62  m_USER.set ("USER");
63  m_DATE.set ("DATE");
64  m_PROTOTARGET.set ("PROTOTARGET");
65  m_OBJS.set ("OBJS");
66  m_CLASSES.set ("CLASSES");
67  m_PROTOSTAMPS.set ("PROTOSTAMPS");
68  m_NAME.set ("NAME");
69  m_FILEPATH.set ("FILEPATH");
70  m_FILESUFFIX.set ("FILESUFFIX");
71  m_SUFFIX.set ("SUFFIX");
72  m_FILENAME.set ("FILENAME");
73  m_LINKMACRO.set ("LINKMACRO");
74  m_LINE.set ("LINE");
75  m_ADDINCLUDE.set ("ADDINCLUDE");
76  m_FULLNAME.set ("FULLNAME");
77  m_DIRNAME.set ("DIRNAME");
78  m_OUTPUTNAME.set ("OUTPUTNAME");
79  m_ALLOS9SOURCES.set ("ALLOS9SOURCES");
80  m_NODEBUGUSELINKOPTS.set ("NODEBUGUSELINKOPTS");
81  m_DEBUGUSELINKOPTS.set ("DEBUGUSELINKOPTS");
82  m_USEINCLUDES.set ("USEINCLUDES");
83  m_HASTARGETTAG.set ("HASTARGETTAG");
84}
85
86//--------------------------------------------------
87void CmtGenerator::reset ()
88{
89  m_CONSTITUENT = "";
90  m_LINKMACRO = "";
91  m_DOCPATH = "";
92  m_PACKAGEPATH = "";
93  m_PACKAGEPREFIX = "";
94  m_PACKAGE = "";
95  m_VERSION = "";
96  m_MGRSTYLE = "";
97  m_TITLE = "";
98  m_GROUP = "";
99  m_CONSTITUENTSUFFIX = "";
100  m_LIBRARYSUFFIX = "";
101  m_USER = "";
102  m_DATE = "";
103  m_PROTOTARGET = "";
104  m_OBJS = "";
105  m_CLASSES = "";
106  m_PROTOSTAMPS = "";
107  m_NAME = "";
108  m_FILEPATH = "";
109  m_FILESUFFIX = "";
110  m_SUFFIX = "";
111  m_FILENAME = "";
112  m_LINE = "";
113  m_ADDINCLUDE = "";
114  m_FULLNAME = "";
115  m_OUTPUTNAME = "";
116  m_ALLOS9SOURCES = "";
117  m_NODEBUGUSELINKOPTS = "";
118  m_DEBUGUSELINKOPTS = "";
119  m_USEINCLUDES = "";
120  m_HASTARGETTAG = "";
121  m_PACKINCLUDES = "";
122  m_PACKOS9      = false;
123  m_GENERATOR    = "";
124
125  is_library     = false;
126  is_application = false;
127  srcdir       = "";
128  docdir       = "";
129  cmtdir       = "";
130  incdir       = "";
131  src          = "$(src)";
132  doc          = "$(doc)";
133  inc          = "$(inc)";
134  mgr          = "$(mgr)";
135  cmt          = "$(cmt)";
136  protos       = "";
137  protonames   = "";
138  os9sources   = "";
139
140  m_source_files.clear ();
141
142  Language::setup_all_fragments ();
143
144  CmtSystem::cd (Cmt::get_current_dir ());
145
146  cmt_string branch = CmtSystem::current_branch ();
147
148  if ((branch == "mgr") || (branch == "cmt"))
149    {
150      if (CmtSystem::test_directory ("../src"))
151        {
152          srcdir = "..";
153          srcdir += CmtSystem::file_separator ();
154          srcdir += "src";
155          srcdir += CmtSystem::file_separator ();
156        }
157      else
158        {
159          srcdir = "";
160        }
161
162      if (CmtSystem::test_directory ("../doc"))
163        {
164          docdir = "..";
165          docdir += CmtSystem::file_separator ();
166          docdir += "doc";
167          docdir += CmtSystem::file_separator ();
168        }
169      else
170        {
171          docdir = "";
172        }
173
174      if (CmtSystem::test_directory ("../cmt"))
175        {
176          cmtdir = "..";
177          cmtdir += CmtSystem::file_separator ();
178          cmtdir += "cmt";
179          cmtdir += CmtSystem::file_separator ();
180        }
181      else if (CmtSystem::test_directory ("../mgr"))
182        {
183          cmtdir = "..";
184          cmtdir += CmtSystem::file_separator ();
185          cmtdir += "mgr";
186          cmtdir += CmtSystem::file_separator ();
187        }
188      else
189        {
190          cmtdir = CmtSystem::pwd ();
191          cmtdir += CmtSystem::file_separator ();
192        }
193
194      if (CmtSystem::test_directory ("../src"))
195        {
196          incdir = "..";
197          incdir += CmtSystem::file_separator ();
198          incdir += "src";
199          incdir += CmtSystem::file_separator ();
200        }
201      else
202        {
203          incdir = "";
204        }
205    }
206  else
207    {
208      srcdir = ".";
209      srcdir += CmtSystem::file_separator ();
210      docdir = ".";
211      docdir += CmtSystem::file_separator ();
212      cmtdir = CmtSystem::pwd ();
213      cmtdir += CmtSystem::file_separator ();
214      incdir = ".";
215      incdir += CmtSystem::file_separator ();
216    }
217}
218
219//--------------------------------------------------
220bool CmtGenerator::prepare_output (const cmt_string& package,
221                                   const Constituent& constituent,
222                                   const cmt_string& file)
223{
224  m_PACKAGE = package;
225  m_CONSTITUENT = constituent.name;
226  m_CONSTITUENTSUFFIX = constituent.suffix;
227
228  m_PACKOS9 = constituent.need_OS9;
229
230  m_output_file_name = cmtdir + m_CONSTITUENT + ".";
231
232  if (Cmt::build_nmake ())
233    {
234      m_output_file_name += "nmake";
235    }
236  else
237    {
238      m_output_file_name += "make";
239    }
240 
241  if (file != "") m_output_file_name = file;
242
243  m_output_file_name += "new";
244
245
246  m_output_file = fopen (m_output_file_name.c_str (), "wb");
247  if (m_output_file != NULL)
248    {
249      return (true);
250    }
251  else
252    {
253      return (false);
254    }
255}
256
257//--------------------------------------------------
258void CmtGenerator::check (const cmt_string& name)
259{
260  static cmt_string old;
261  static cmt_string backup;
262
263  old = name;
264
265  int pos = old.find_last_of ("new");
266  old.erase (pos);
267
268  if (!CmtSystem::compare_files (old, name))
269    {
270      backup = old;
271      backup += "sav";
272
273      unlink (backup.c_str ());
274      rename (old.c_str (), backup.c_str ());
275      rename (name.c_str (), old.c_str ());
276    }
277  else
278    {
279      unlink (name);
280    }
281}
282
283//--------------------------------------------------
284void CmtGenerator::commit (const cmt_string& name)
285{
286  static cmt_string old;
287  static cmt_string backup;
288
289  old = name;
290
291  int pos = old.find_last_of ("new");
292  old.erase (pos);
293
294  if (CmtSystem::test_file (old))
295    {
296      backup = old;
297      backup += "sav";
298
299      unlink (backup.c_str ());
300      rename (old.c_str (), backup.c_str ());
301    }
302
303  rename (name.c_str (), old.c_str ());
304}
305
306//--------------------------------------------------
307void CmtGenerator::terminate ()
308{
309  fclose (m_output_file);
310
311  //--- Complete the operation --------------
312
313  commit (m_output_file_name);
314}
315
316//--------------------------------------------------
317void CmtGenerator::fill_outputs ()
318{
319  bool first = true;
320
321  m_OBJS = "";
322
323  for (int i = 0; i < m_source_files.size (); i++)
324    {
325      const SourceFile& file = m_source_files[i];
326      const cmt_string output = file.output ();
327
328      if (output != "")
329        {
330          if (first)
331            {
332              first = false;
333            }
334          else
335            {
336              m_OBJS += " ";
337            }
338
339          m_OBJS += output;
340        }
341
342      if (Cmt::get_debug ())
343        {
344          cout << "CmtGenerator::fill_outputs> output=" << output << " OBJS=" << m_OBJS << endl;
345        }
346
347    }
348
349  if (Cmt::get_debug ())
350    {
351      cout << "CmtGenerator::fill_outputs> OBJS=" << m_OBJS << endl;
352    }
353
354}
355
356//--------------------------------------------------
357void CmtGenerator::prepare_use_context ()
358{
359  cmt_string path;
360  cmt_string substitution;
361
362  Use* use = &Use::current ();
363
364  m_deps_builder.clear ();
365
366  if (use->include_path != "none")
367    {
368      if (use->include_path == "")
369        {
370          m_deps_builder.add (incdir, "$(src)");
371        }
372      else
373        {
374          substitution = use->include_path;
375         
376          path = substitution;
377          Symbol::expand (path);
378         
379          CmtSystem::reduce_file_separators (path);
380
381          m_deps_builder.add (path, substitution);
382        }
383    }
384
385  m_deps_builder.add_includes (*use);
386
387  Use::UsePtrVector& uses = Use::get_ordered_uses ();
388
389  if (uses.size () > 0)
390    {
391      int number;
392
393      for (number = 0; number < uses.size (); number++)
394        {
395          use = uses[number];
396          if (use->discarded) continue;
397
398          if (use->real_path != "")
399            {
400              if (use->include_path != "none")
401                {
402                  if (use->include_path == "")
403                    {
404                      use->get_full_path (path);
405                      path += CmtSystem::file_separator ();
406                      path += "src";
407
408                      substitution = "$(";
409                      substitution += use->prefix;
410                      substitution += "ROOT)";
411                      substitution += CmtSystem::file_separator ();
412                      substitution += "src";
413                      substitution += CmtSystem::file_separator ();
414                    }
415                  else
416                    {
417                      substitution = use->include_path;
418
419                      path = substitution;
420                      Symbol::expand (path);
421
422                      CmtSystem::reduce_file_separators (path);
423                    }
424
425                  m_deps_builder.add (path, substitution);
426                }
427
428              m_deps_builder.add_includes (*use);
429            }
430        }
431    }
432}
433
434//--------------------------------------------------
435void CmtGenerator::filter_path (cmt_string& text)
436{
437  CmtSystem::compress_path (text);
438
439  text.replace_all ("./../src/../", "../");
440  text.replace_all ("./../src/", "$(src)");
441
442  text.replace_all (".\\..\\src\\..\\", "..\\");
443  text.replace_all (".\\..\\src\\", "$(src)");
444
445  text.replace_all ("../src/../", "../");
446  text.replace_all ("../src/", "$(src)");
447
448  text.replace_all ("..\\src\\..\\", "..\\");
449  text.replace_all ("..\\src\\", "$(src)");
450
451  text.replace_all ("../doc/../", "../");
452  text.replace_all ("../doc/", "$(doc)");
453
454  text.replace_all ("..\\doc\\..\\", "..\\");
455  text.replace_all ("..\\doc\\", "$(doc)");
456
457  text.replace_all ("$(src)$(src)", "$(src)");
458}
459
460/**
461   Scan a complete file spec (with possibly wild cards and directory)
462   given in full_name ad fill in a vector of found file names.
463
464   Result of the scan is filtered against matching suffixes
465
466   Returns the count of non empty file names really found.
467
468*/
469int CmtGenerator::get_all_files (const cmt_string& full_name,
470                                 const cmt_vector<cmt_regexp>& exclude_exprs,
471                                 const cmt_vector<cmt_regexp>& select_exprs,
472                                 CmtSystem::cmt_string_vector& files)
473{
474  static cmt_string suffix;
475  static cmt_string name;
476
477  bool has_excludes = false;
478  bool has_selects = false;
479
480  suffix = "";
481  name = "";
482
483  files.clear ();
484
485  has_excludes = (exclude_exprs.size () > 0);
486  has_selects = (select_exprs.size () > 0);
487
488  CmtSystem::get_dot_suffix (full_name, suffix);
489
490  bool wilcarded_suffix = false;
491
492  if (suffix == ".*") wilcarded_suffix = true;
493
494  int count = 0;
495
496  if (full_name.find ('*') != cmt_string::npos)
497    {
498      CmtSystem::scan_dir (full_name, files);
499
500      if (Cmt::get_debug ())
501        {
502          cout << "CMT::get_all_files> full_name=" << full_name <<
503            " pwd=" << CmtSystem::pwd () << endl;
504          cout << "CMT::get_all_files> files.size=" <<  files.size () << endl;
505        }
506
507      /**
508
509      We have to treat patterns of the form *.xxx (ie with a
510      suffix) thus we filter out everything that could have been
511      collected with a different suffix because the
512      CmtSystem::scan_dir function only handles patterns of the
513      form xxx* (ie with trailing *)
514
515      [If the original suffix was empty (ie files specified using
516      xx*) this means getting files without any dot-suffix. This
517      may be incorrect??]
518
519      */
520
521      for (int j = 0; j < files.size (); j++)
522        {
523          cmt_string& n = files[j];
524
525          bool rejected = false;
526
527          if (n == "")
528            {
529              rejected = true;
530            }
531
532          if (!rejected && has_selects)
533            {
534              rejected = true;
535
536              for (int k = 0; k < select_exprs.size (); k++)
537                {
538                  const cmt_regexp& exp = select_exprs[k];
539                  if (exp.match (n))
540                    {
541                      rejected = false;
542                      break;
543                    }
544                }
545            }
546
547          if (!rejected && has_excludes)
548            {
549              for (int k = 0; k < exclude_exprs.size (); k++)
550                {
551                  const cmt_regexp& exp = exclude_exprs[k];
552                  if (exp.match (n))
553                    {
554                      rejected = true;
555                      break;
556                    }
557                }
558            }
559
560          if (!rejected)
561            {
562              static cmt_string s;
563
564              CmtSystem::get_dot_suffix (n, s);
565              if (!wilcarded_suffix && (s != suffix)) 
566                {
567                  rejected = true;
568                }
569              else
570                {
571                  count++;
572                }
573            }
574
575          if (Cmt::get_debug ())
576            {
577              if (rejected)
578                {
579                  cout << "CMT::get_all_files> reject " <<  n << endl;
580                }
581              else
582                {
583                  cout << "CMT::get_all_files> keep " <<  n << endl;
584                }
585            }
586
587          if (rejected)
588            {
589              n = "";
590            }
591        }
592    }
593  else
594    {
595      if (full_name != "")
596        {
597          bool rejected = false;
598
599          if (has_excludes)
600            {
601              for (int k = 0; k < exclude_exprs.size (); k++)
602                {
603                  const cmt_regexp& exp = exclude_exprs[k];
604                  if (exp.match (full_name))
605                    {
606                      rejected = true;
607                      break;
608                    }
609                }
610            }
611
612          if (!rejected)
613            {
614              cmt_string& n = files.add ();
615
616              n = full_name;
617
618              count++;
619            }
620        }
621    }
622
623  return (count);
624}
625
626//--------------------------------------------------
627void CmtGenerator::set_full_name (cmt_string& full_name, cmt_string& file)
628{
629  full_name = "";
630
631  Symbol::expand (file);
632
633  if (file == "") return;
634 
635  if (!CmtSystem::absolute_path (file))
636    {
637      full_name = srcdir;
638      if (full_name != "") full_name += CmtSystem::file_separator ();
639    }
640 
641  full_name += file;
642
643  CmtSystem::reduce_file_separators (full_name);
644}
645
646//------------------------------------------------------------------------
647static ApplicationGenerator ApplicationContext;
648static LibraryGenerator LibraryContext;
649static DocumentGenerator DocumentContext;
650static ReadmeGenerator ReadmeContext;
651static PrototypeGenerator PrototypeContext;
652static DefaultMakefileGenerator DefaultMakefileContext;
653static MSDEVGenerator MSDEVContext;
654static VSNETGenerator VSNETContext;
655static MakeSetupGenerator MakeSetupContext;
656static ConstituentsMakefileGenerator ConstituentsMakefileContext;
657static DependencyGenerator DependencyContext;
658
659//--------------------------------------------------
660int Generator::build_msdev_workspace (const Constituent::ConstituentVector& constituents)
661{
662  return (MSDEVContext.build_workspace (constituents));
663}
664
665//--------------------------------------------------
666int Generator::build_msdev (const Constituent& constituent)
667{
668  return (MSDEVContext.build_project (constituent));
669}
670
671//--------------------------------------------------
672int Generator::build_vsnet_workspace (const Constituent::ConstituentVector& constituents)
673{
674  return (VSNETContext.build_workspace (constituents));
675}
676
677//--------------------------------------------------   
678int Generator::build_vsnet (const Constituent& constituent)
679{
680  return (VSNETContext.build_project (constituent));
681}
682
683//--------------------------------------------------
684void Generator::build_make_setup (const cmt_string& package)
685{
686  MakeSetupContext.build (package);
687}
688
689//--------------------------------------------------
690void Generator::build_constituents_makefile (const cmt_string& package,
691                                             const CmtSystem::cmt_string_vector& arguments)
692{
693  ConstituentsMakefileContext.build (package, arguments);
694}
695
696//--------------------------------------------------
697int Generator::build_constituent_makefile (const Constituent& constituent,
698                                           const cmt_string& file)
699{
700  const cmt_string& package = Cmt::get_current_package ();
701
702  switch (constituent.type)
703    {
704    case Application:
705      ApplicationContext.build (package, constituent, file);
706      break;
707    case Library:
708      LibraryContext.build (package, constituent, file);
709      break;
710    case Document:
711      DocumentContext.build (package, constituent, file);
712      break;
713    }
714
715  return (0);
716}
717
718//--------------------------------------------------
719void Generator::build_constituent_makefile (const CmtSystem::cmt_string_vector& arguments)
720{
721  cmt_string name;
722  cmt_string file;
723
724  if (arguments.size () == 1)
725    {
726      file = "";
727      name = arguments[0];
728    }
729  else if (arguments.size () == 2) // arguments[0].substr (0, 5) == "-out="
730    {
731      cmt_string arg = arguments[0];
732      arg.erase (0, 5);
733      file = arg;
734      name = arguments[1];
735    }
736  else
737    {
738      cerr << "#CMT> build constituent_makefile : wrong arguments" << endl;
739      return;
740    }
741
742  const Constituent* constituent = Constituent::find (name);
743  if (constituent != 0) build_constituent_makefile (*constituent, file);
744}
745
746//--------------------------------------------------
747void Generator::build_default_makefile ()
748{
749  DefaultMakefileContext.build ();
750}
751
752//--------------------------------------------------
753void Generator::build_dependencies (const CmtSystem::cmt_string_vector& arguments)
754{
755  DependencyContext.build (arguments);
756}
757
758//--------------------------------------------------
759void Generator::build_prototype (const cmt_string& file_name)
760{
761  PrototypeContext.build (file_name);
762}
763
764//--------------------------------------------------
765void Generator::build_readme (const CmtSystem::cmt_string_vector& arguments)
766{
767  ReadmeContext.build (arguments);
768}
769
770class WinDefAwk : public PAwk
771{
772public :
773  WinDefAwk (const cmt_string& library_name)
774  {
775    m_name = library_name;
776  }
777
778  void begin ()
779  {
780    cout << "LIBRARY " << m_name << endl;
781    cout << "EXPORTS" << endl;
782  }
783
784  void filter (const cmt_string& line)
785  {
786    if (line.find ("External") == cmt_string::npos) return;
787    if (line.find ("??_") != cmt_string::npos)
788      {
789        if (line.find ("operator/=") == cmt_string::npos) return;
790        // Keep operator /= .
791      }
792
793    CmtSystem::cmt_string_vector words;
794    CmtSystem::split (line, " \t", words);
795    if (words.size () >= 7)
796      {
797        int pos = 7;
798
799        cmt_string& fifth_word = words[4];
800        if (fifth_word == "()") pos = 7;
801        else if (fifth_word == "External") pos = 6;
802        else return;
803
804        cmt_string& symbol = words[pos];
805        if (symbol[0] == '_') symbol.erase (0, 1);
806        symbol.replace_all ("\r", "");
807        symbol.replace_all ("\n", "");
808
809        if ((pos == 6) && 
810            ((line.find(": static") != cmt_string::npos) ||
811             (line.find("(class") != cmt_string::npos)) )
812          {
813            // static data members are not DATA :
814            // extern objects are not DATA :
815            cout << " " << symbol << " " << endl;
816          } 
817        else if (pos == 6)
818          {
819            // DATA :
820            cout << " " << symbol << "\tDATA" << endl;
821          } 
822        else
823          {
824            // code :
825            cout << " " << symbol << " " << endl;
826          } 
827      }
828  }
829
830  void end ()
831  {
832  }
833
834private:
835  cmt_string m_name;
836};
837
838//--------------------------------------------------
839void Generator::build_windefs (const cmt_string& library_name)
840{
841  cmt_string bin;
842  cmt_string name;
843  cmt_string suffix;
844
845  CmtSystem::dirname (library_name, bin);
846  CmtSystem::get_dot_suffix (library_name, suffix);
847  CmtSystem::basename (library_name, suffix, name);
848 
849  if (!CmtSystem::cd (bin)) return;
850 
851  cmt_string text;
852  cmt_string command;
853 
854  command = "dumpbin /symbols ";
855  command += library_name;
856       
857  WinDefAwk filter (name);
858 
859  filter.run (command, "SECT");
860}
861
862//--------------------------------------------------
863void Packager::begin ()
864{
865  m_package_name = "";
866}
867
868void Packager::filter (const cmt_string& line)
869{
870  CmtSystem::cmt_string_vector words;
871
872  CmtSystem::split (line, " ", words);
873  if (words.size () > 1)
874    {
875      cmt_string& w = words[0];
876
877      if (w == "package")
878        {
879          m_package_name = words[1];
880
881          int pos = m_package_name.find (";");
882          if (pos != cmt_string::npos) m_package_name.erase (pos);
883          m_package_name.replace_all (".", CmtSystem::file_separator ());
884        }
885    }
886}
887
888cmt_string& Packager::package_name ()
889{
890  return (m_package_name);
891}
892
Note: See TracBrowser for help on using the repository browser.