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

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

Import all tags

File size: 33.5 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_syntax.h"
8#include "cmt.h"
9#include "cmt_symbol.h"
10#include "cmt_constituent.h"
11#include "cmt_pattern.h"
12#include "cmt_error.h"
13#include "cmt_branch.h"
14#include "cmt_error.h"
15#include "cmt_script.h"
16#include "cmt_language.h"
17#include "cmt_project.h"
18#include "cmt_cmtpath_pattern.h"
19
20void Kwd::action (const CmtSystem::cmt_string_vector& words,
21                  Project* project,
22                  const cmt_string& file_name,
23                  int line_number)
24{
25}
26
27class KwdAction : public Kwd
28{
29public:
30  void action (const CmtSystem::cmt_string_vector& words,
31               Use* use,
32               const cmt_string& file_name,
33               int line_number)
34  {
35    Symbol::action (words, CommandAction, use);
36  }
37};
38
39class KwdAlias : public Kwd
40{
41public:
42  void action (const CmtSystem::cmt_string_vector& words,
43               Use* use,
44               const cmt_string& file_name,
45               int line_number)
46  {
47    Symbol::action (words, CommandAlias, use);
48  }
49};
50
51class KwdApplication : public Kwd
52{
53public:
54  void action (const CmtSystem::cmt_string_vector& words,
55               Use* use,
56               const cmt_string& file_name,
57               int line_number)
58  {
59    if (use == &(Use::current ()))
60      {
61        Constituent::action (Application, words);
62      }
63  }
64};
65
66class KwdApplyPattern : public Kwd
67{
68public:
69  void action (const CmtSystem::cmt_string_vector& words,
70               Use* use,
71               const cmt_string& file_name,
72               int line_number)
73  {
74    ApplyPattern::action (words, use);
75  }
76};
77
78class KwdApplyTag : public Kwd
79{
80public:
81  void action (const CmtSystem::cmt_string_vector& words,
82               Use* use,
83               const cmt_string& file_name,
84               int line_number)
85  {
86    Tag::action_apply (words, use);
87  }
88};
89
90class KwdAuthor : public Kwd
91{
92public:
93  void action (const CmtSystem::cmt_string_vector& words,
94               Use* use,
95               const cmt_string& file_name,
96               int line_number)
97  {
98    use->author_action (words);
99  }
100};
101
102class KwdBranches : public Kwd
103{
104public:
105  void action (const CmtSystem::cmt_string_vector& words,
106               Use* use,
107               const cmt_string& file_name,
108               int line_number)
109  {
110    if (use == &(Use::current ())) 
111      {
112        Branch::action (words);
113      }
114  }
115};
116
117class KwdBuildStrategy : public Kwd
118{
119public:
120  bool decode (const cmt_string& w,
121               int& mask,
122               int& strategy)
123  {
124    bool result = true;
125
126    if (w == "prototypes")
127      {
128        mask = PrototypesMask;
129        strategy = Prototypes;
130      }
131    else if (w == "no_prototypes")
132      {
133        mask = PrototypesMask;
134        strategy = NoPrototypes;
135      }
136    else if ((w == "with_installarea") || (w == "with_install_area"))
137      {
138        mask = InstallAreaMask;
139        strategy = WithInstallArea;
140      }
141    else if ((w == "without_installarea") || (w == "without_install_area"))
142      {
143        mask = InstallAreaMask;
144        strategy = WithoutInstallArea;
145      }
146    else
147      {
148        result = false;
149      }
150
151    return (result);
152  }
153
154  void action (const CmtSystem::cmt_string_vector& words,
155               Use* use,
156               const cmt_string& file_name,
157               int line_number)
158  {
159    cmt_string cmtpath;
160    cmt_string offset;
161
162    use->get_cmtpath_and_offset (cmtpath, offset);
163
164    Project* p = Project::find_by_cmtpath (cmtpath);
165
166    for (int i = 1; i < words.size (); i++)
167      {
168        const cmt_string& w = words[i];
169
170        int mask = 0;
171        int strategy = 0;
172
173        bool in_error = false;
174
175        if (!decode (w, mask, strategy))
176          {
177            in_error = true;
178
179            CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword");
180          }
181
182        if (mask != 0)
183          {
184            if (p == 0) Cmt::set_current_build_strategy (strategy);
185            else p->set_build_strategy (mask, strategy);
186          }
187
188        if ((Cmt::get_action () == action_show_strategies) && !Cmt::get_quiet ())
189          {
190            if (!in_error)
191              {
192                cerr << "# Package " << use->get_package_name ()
193                     << " adds " << w << " to build strategy" << endl;
194              }
195            else
196              {
197                cerr << "# Error: Package " << use->get_package_name ()
198                     << " uses unknown " << w << " keyword to build strategy" << endl;
199              }
200          }
201      }
202  }
203
204  void action (const CmtSystem::cmt_string_vector& words,
205               Project* project,
206               const cmt_string& file_name,
207               int line_number)
208  {
209    for (int i = 1; i < words.size (); i++)
210      {
211        const cmt_string& w = words[i];
212
213        int mask = 0;
214        int strategy = 0;
215
216        bool in_error = false;
217
218        if (!decode (w, mask, strategy))
219          {
220            in_error = true;
221
222            CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword");
223          }
224
225        if (mask != 0)
226          {
227            if (project == 0) Cmt::set_current_build_strategy (strategy);
228            else project->set_build_strategy (mask, strategy);
229          }
230
231        if ((Cmt::get_action () == action_show_strategies) && !Cmt::get_quiet ())
232          {
233            if (!in_error)
234              {
235                cerr << "# Project " << project->get_name ()
236                     << " adds " << w << " to build strategy" << endl;
237              }
238            else
239              {
240                cerr << "# Error: Project " << project->get_name ()
241                     << " uses unknown " << w << " keyword to build strategy" << endl;
242              }
243          }
244      }
245  }
246};
247
248class KwdCleanupScript : public Kwd
249{
250public:
251  void action (const CmtSystem::cmt_string_vector& words,
252               Use* use,
253               const cmt_string& file_name,
254               int line_number)
255  {
256    Script::action (words, CleanupScript, use);
257    Symbol::action (words, CommandCleanupScript, use);
258  }
259};
260
261class KwdCmtPathPattern : public Kwd
262{
263public:
264  void action (const CmtSystem::cmt_string_vector& words,
265               Use* use,
266               const cmt_string& /*file_name*/,
267               int /*line_number*/)
268  {
269    CmtPathPattern::action (words, use);
270  }
271};
272
273class KwdDocument : public Kwd
274{
275public:
276  void action (const CmtSystem::cmt_string_vector& words,
277               Use* use,
278               const cmt_string& file_name,
279               int line_number)
280  {
281    if (use == &(Use::current ()))
282      {
283        Constituent::action (Document, words);
284      }
285  }
286};
287
288class KwdEndPrivate : public Kwd
289{
290public:
291  void action (const CmtSystem::cmt_string_vector& words,
292               Use* use,
293               const cmt_string& file_name,
294               int line_number)
295  {
296    if (use != &(Use::current ()))
297      {
298        use->pop_scope_section ();
299      }
300  }
301};
302
303class KwdEndPublic : public Kwd
304{
305public:
306  void action (const CmtSystem::cmt_string_vector& words,
307               Use* use,
308               const cmt_string& file_name,
309               int line_number)
310  {
311    if (use != &(Use::current ()))
312      {
313        use->pop_scope_section ();
314      }
315  }
316};
317
318class KwdIgnorePattern : public Kwd
319{
320public:
321  void action (const CmtSystem::cmt_string_vector& words,
322               Use* use,
323               const cmt_string& file_name,
324               int line_number)
325  {
326    IgnorePattern::action (words, use);
327  }
328};
329
330class KwdIncludeDirs : public Kwd
331{
332public:
333  void action (const CmtSystem::cmt_string_vector& words,
334               Use* use,
335               const cmt_string& file_name,
336               int line_number)
337  {
338    Include::action (words, use);
339  }
340};
341
342class KwdIncludePath : public Kwd
343{
344public:
345  void action (const CmtSystem::cmt_string_vector& words,
346               Use* use,
347               const cmt_string& file_name,
348               int line_number)
349  {
350    if (words.size () > 1)
351      {
352        use->set_include_path (words[1]);
353      }
354  }
355};
356
357class KwdLanguage : public Kwd
358{
359public:
360  void action (const CmtSystem::cmt_string_vector& words,
361               Use* use,
362               const cmt_string& file_name,
363               int line_number)
364  {
365    Language::action (words);
366  }
367};
368
369class KwdLibrary : public Kwd
370{
371public:
372  void action (const CmtSystem::cmt_string_vector& words,
373               Use* use,
374               const cmt_string& file_name,
375               int line_number)
376  {
377    if (use == &(Use::current ()))
378      {
379        Constituent::action (Library, words);
380      }
381  }
382};
383
384class KwdMacro : public Kwd
385{
386public:
387  void action (const CmtSystem::cmt_string_vector& words,
388               Use* use,
389               const cmt_string& file_name,
390               int line_number)
391  {
392    Symbol::action (words, CommandMacro, use);
393  }
394};
395
396class KwdMacroPrepend : public Kwd
397{
398public:
399  void action (const CmtSystem::cmt_string_vector& words,
400               Use* use,
401               const cmt_string& file_name,
402               int line_number)
403  {
404    Symbol::action (words, CommandMacroPrepend, use);
405  }
406};
407
408class KwdMacroAppend : public Kwd
409{
410public:
411  void action (const CmtSystem::cmt_string_vector& words,
412               Use* use,
413               const cmt_string& file_name,
414               int line_number)
415  {
416    Symbol::action (words, CommandMacroAppend, use);
417  }
418};
419
420class KwdMacroRemove : public Kwd
421{
422public:
423  void action (const CmtSystem::cmt_string_vector& words,
424               Use* use,
425               const cmt_string& file_name,
426               int line_number)
427  {
428    Symbol::action (words, CommandMacroRemove, use);
429  }
430};
431
432class KwdMacroRemoveRegexp : public Kwd
433{
434public:
435  void action (const CmtSystem::cmt_string_vector& words,
436               Use* use,
437               const cmt_string& file_name,
438               int line_number)
439  {
440    Symbol::action (words, CommandMacroRemoveRegexp, use);
441  }
442};
443
444class KwdMacroRemoveAll : public Kwd
445{
446public:
447  void action (const CmtSystem::cmt_string_vector& words,
448               Use* use,
449               const cmt_string& file_name,
450               int line_number)
451  {
452    Symbol::action (words, CommandMacroRemoveAll, use);
453  }
454};
455
456class KwdMacroRemoveAllRegexp : public Kwd
457{
458public:
459  void action (const CmtSystem::cmt_string_vector& words,
460               Use* use,
461               const cmt_string& file_name,
462               int line_number)
463  {
464    Symbol::action (words, CommandMacroRemoveAllRegexp, use);
465  }
466};
467
468class KwdMakeFragment : public Kwd
469{
470public:
471  void action (const CmtSystem::cmt_string_vector& words,
472               Use* use,
473               const cmt_string& file_name,
474               int line_number)
475  {
476    Fragment::action (words, use);
477  }
478};
479
480class KwdManager : public Kwd
481{
482public:
483  void action (const CmtSystem::cmt_string_vector& words,
484               Use* use,
485               const cmt_string& file_name,
486               int line_number)
487  {
488    use->manager_action (words);
489  }
490};
491
492class KwdPackage : public Kwd
493{
494public:
495  void action (const CmtSystem::cmt_string_vector& words,
496               Use* use,
497               const cmt_string& file_name,
498               int line_number)
499  {
500    /*
501    if (words.size () > 1)
502      {
503        if (use == &(Use::current()))
504          {
505            m_current_package = words[1];
506            build_prefix (m_current_package, m_current_prefix);
507           
508            if ((use->get_package_name () != "") &&
509                (use->get_package_name () != m_current_package))
510              {
511                if (!m_quiet)
512                  {
513                    //  cerr << "#CMT> package name mismatch in requirements of " <<
514                    //  use->get_package_name () << " " <<
515                    //  use->version << " line #" << line_number;
516                    //  cerr << " : " << m_current_package << " versus " <<
517                    //  use->get_package_name () << endl;
518                  }
519              }
520           
521            use->set (m_current_package,
522                      m_current_version,
523                      m_current_path,
524                      "",
525                      "");
526           
527            use->change_path (m_current_path);
528            use->style = m_current_style;
529          }
530      }
531    */
532  }
533};
534
535class KwdPath : public Kwd
536{
537public:
538  void action (const CmtSystem::cmt_string_vector& words,
539               Use* use,
540               const cmt_string& file_name,
541               int line_number)
542  {
543    Symbol::action (words, CommandPath, use);
544  }
545};
546
547class KwdPathAppend : public Kwd
548{
549public:
550  void action (const CmtSystem::cmt_string_vector& words,
551               Use* use,
552               const cmt_string& file_name,
553               int line_number)
554  {
555    Symbol::action (words, CommandPathAppend, use);
556  }
557};
558
559class KwdPathPrepend : public Kwd
560{
561public:
562  void action (const CmtSystem::cmt_string_vector& words,
563               Use* use,
564               const cmt_string& file_name,
565               int line_number)
566  {
567    Symbol::action (words, CommandPathPrepend, use);
568  }
569};
570
571class KwdPathRemove : public Kwd
572{
573public:
574  void action (const CmtSystem::cmt_string_vector& words,
575               Use* use,
576               const cmt_string& file_name,
577               int line_number)
578  {
579    Symbol::action (words, CommandPathRemove, use);
580  }
581};
582
583class KwdPathRemoveRegexp : public Kwd
584{
585public:
586  void action (const CmtSystem::cmt_string_vector& words,
587               Use* use,
588               const cmt_string& file_name,
589               int line_number)
590  {
591    Symbol::action (words, CommandPathRemoveRegexp, use);
592  }
593};
594
595class KwdPattern : public Kwd
596{
597public:
598  void action (const CmtSystem::cmt_string_vector& words,
599               Use* use,
600               const cmt_string& file_name,
601               int line_number)
602  {
603    Pattern::action (words, use);
604  }
605};
606
607class KwdPrivate : public Kwd
608{
609public:
610  void action (const CmtSystem::cmt_string_vector& words,
611               Use* use,
612               const cmt_string& file_name,
613               int line_number)
614  {
615    if (use != &(Use::current ()))
616      {
617        use->push_scope_section (ScopePrivate);
618      }
619  }
620};
621
622class KwdProject : public Kwd
623{
624public:
625  void action (const CmtSystem::cmt_string_vector& words,
626               Use* use,
627               const cmt_string& file_name,
628               int line_number)
629  {
630  }
631
632  void action (const CmtSystem::cmt_string_vector& words,
633               Project* project,
634               const cmt_string& file_name,
635               int line_number)
636  {
637  }
638};
639
640class KwdPublic : public Kwd
641{
642public:
643  void action (const CmtSystem::cmt_string_vector& words,
644               Use* use,
645               const cmt_string& file_name,
646               int line_number)
647  {
648    if (use != &(Use::current ()))
649      {
650        use->push_scope_section (ScopePublic);
651      }
652  }
653};
654
655class KwdSet : public Kwd
656{
657public:
658  void action (const CmtSystem::cmt_string_vector& words,
659               Use* use,
660               const cmt_string& file_name,
661               int line_number)
662  {
663    Symbol::action (words, CommandSet, use);
664  }
665};
666
667class KwdSetAppend : public Kwd
668{
669public:
670  void action (const CmtSystem::cmt_string_vector& words,
671               Use* use,
672               const cmt_string& file_name,
673               int line_number)
674  {
675    Symbol::action (words, CommandSetAppend, use);
676  }
677};
678
679class KwdSetPrepend : public Kwd
680{
681public:
682  void action (const CmtSystem::cmt_string_vector& words,
683               Use* use,
684               const cmt_string& file_name,
685               int line_number)
686  {
687    Symbol::action (words, CommandSetPrepend, use);
688  }
689};
690
691class KwdSetRemove : public Kwd
692{
693public:
694  void action (const CmtSystem::cmt_string_vector& words,
695               Use* use,
696               const cmt_string& file_name,
697               int line_number)
698  {
699    Symbol::action (words, CommandSetRemove, use);
700  }
701};
702
703class KwdSetRemoveRegexp : public Kwd
704{
705public:
706  void action (const CmtSystem::cmt_string_vector& words,
707               Use* use,
708               const cmt_string& file_name,
709               int line_number)
710  {
711    Symbol::action (words, CommandSetRemoveRegexp, use);
712  }
713};
714
715class KwdSetupScript : public Kwd
716{
717public:
718  void action (const CmtSystem::cmt_string_vector& words,
719               Use* use,
720               const cmt_string& file_name,
721               int line_number)
722  {
723    Script::action (words, SetupScript, use);
724    Symbol::action (words, CommandSetupScript, use);
725  }
726};
727
728class KwdSetupStrategy : public Kwd
729{
730public:
731  bool decode (const cmt_string& w, int& mask, int& strategy)
732  {
733    bool result = true;
734
735    if (w == "config")
736      {
737        mask = SetupConfigMask;
738        strategy = SetupConfig;
739      }
740    else if (w == "no_config")
741      {
742        mask = SetupConfigMask;
743        strategy = SetupNoConfig;
744      }
745    else if (w == "root")
746      {
747        mask = SetupRootMask;
748        strategy = SetupRoot;
749      }
750    else if (w == "no_root")
751      {
752        mask = SetupRootMask;
753        strategy = SetupNoRoot;
754      }
755    else if (w == "cleanup")
756      {
757        mask = SetupCleanupMask;
758        strategy = SetupCleanup;
759      }
760    else if (w == "no_cleanup")
761      {
762        mask = SetupCleanupMask;
763        strategy = SetupNoCleanup;
764      }
765    else
766      {
767        result = false;
768      }
769
770    return (result);
771  }
772
773  void action (const CmtSystem::cmt_string_vector& words,
774               Use* use,
775               const cmt_string& file_name,
776               int line_number)
777  {
778    cmt_string cmtpath;
779    cmt_string offset;
780
781    use->get_cmtpath_and_offset (cmtpath, offset);
782
783    Project* p = Project::find_by_cmtpath (cmtpath);
784
785    for (int i = 1; i < words.size (); i++)
786      {
787        const cmt_string& w = words[i];
788
789        int mask = 0;
790        int strategy = 0;
791
792        bool in_error = false;
793
794        if (!decode (w, mask, strategy))
795          {
796            in_error = true;
797
798            CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword");
799          }
800       
801        if (mask != 0)
802          {
803            if (p == 0) Cmt::set_current_setup_strategy (strategy);
804            else p->set_setup_strategy (mask, strategy);
805          }
806
807        if ((Cmt::get_action () == action_show_strategies) && !Cmt::get_quiet ())
808          {
809            if (!in_error)
810              {
811                cerr << "# Package " << use->get_package_name ()
812                     << " adds " << w << " to setup strategy" << endl;
813              }
814            else
815              {
816                cerr << "# Error: Package " << use->get_package_name ()
817                     << " uses unknown " << w << " keyword to setup strategy" << endl;
818              }
819          }
820      }
821  }
822
823  void action (const CmtSystem::cmt_string_vector& words,
824               Project* project,
825               const cmt_string& file_name,
826               int line_number)
827  {
828    for (int i = 1; i < words.size (); i++)
829      {
830        const cmt_string& w = words[i];
831
832        int mask = 0;
833        int strategy = 0;
834
835        bool in_error = false;
836
837        if (!decode (w, mask, strategy))
838          {
839            in_error = true;
840
841            CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword");
842          }
843       
844        if (mask != 0)
845          {
846            if (project == 0) Cmt::set_current_setup_strategy (strategy);
847            else project->set_setup_strategy (mask, strategy);
848          }
849
850        if ((Cmt::get_action () == action_show_strategies) && !Cmt::get_quiet ())
851          {
852            if (!in_error)
853              {
854                cerr << "# Project " << project->get_name ()
855                     << " adds " << w << " to setup strategy" << endl;
856              }
857            else
858              {
859                cerr << "# Error: Project " << project->get_name ()
860                     << " uses unknown " << w << " keyword to setup strategy" << endl;
861              }
862          }
863      }
864  }
865};
866
867class KwdTag : public Kwd
868{
869public:
870  void action (const CmtSystem::cmt_string_vector& words,
871               Use* use,
872               const cmt_string& file_name,
873               int line_number)
874  {
875    Tag::action (words, use);
876  }
877};
878
879class KwdTagExclude : public Kwd
880{
881public:
882  void action (const CmtSystem::cmt_string_vector& words,
883               Use* use,
884               const cmt_string& file_name,
885               int line_number)
886  {
887    Tag::action_exclude (words, use);
888  }
889};
890
891class KwdUse : public Kwd
892{
893public:
894  void action (const CmtSystem::cmt_string_vector& words,
895               Use* use,
896               const cmt_string& file_name,
897               int line_number)
898  {
899    Use::action (words, use);
900  }
901};
902
903class KwdVersionStrategy : public Kwd
904{
905public:
906  void action (const CmtSystem::cmt_string_vector& words,
907               Use* use,
908               const cmt_string& file_name,
909               int line_number)
910  {
911    cerr << "# Package " << use->get_package_name () <<
912      " sets obsolescent version strategy" << endl;
913  }
914};
915
916class KwdVersion : public Kwd
917{
918public:
919  void action (const CmtSystem::cmt_string_vector& words,
920               Use* use,
921               const cmt_string& file_name,
922               int line_number)
923  {
924  }
925};
926
927class KwdDefault : public Kwd
928{
929public:
930  void action (const CmtSystem::cmt_string_vector& words,
931               Use* use,
932               const cmt_string& file_name,
933               int line_number)
934  {
935    /*
936      Unknown keyword : just ignore the line
937    */
938    if (!Cmt::get_quiet ())
939      {
940        cerr << "#CMT> bad syntax in requirements of " << use->get_package_name ()
941             << " " << use->version << " line #" << line_number;
942        cerr << " [" << words[0] << "...]" << endl;
943      }
944   
945    CmtError::set (CmtError::syntax_error, "ParseRequirements> ");
946  }
947};
948
949SyntaxParser& SyntaxParser::instance ()
950{
951  static SyntaxParser p;
952
953  return (p);
954}
955
956/**
957 *  Parse the input file, rejecting comments and
958 * rebuilding complete lines (from sections separated by
959 *  \ characters.
960 *
961 *  Each reformatted line is parsed by filter_line
962 */
963void SyntaxParser::parse_requirements (const cmt_string& file_name, Use* use)
964{
965  SyntaxParser& me = instance ();
966
967  if (use != 0)
968    {
969      cmt_string buffer;
970
971      use->fill_standard_macros (buffer);
972
973      AccessMode saved_current_access = Cmt::get_current_access ();
974      Cmt::set_current_access (UserMode);
975      me.do_parse_text (buffer, "", package_context, use, 0);
976      Cmt::set_current_access (saved_current_access);
977    }
978
979  me.do_parse_requirements (file_name, use);
980
981  if (use != 0)
982    {
983      use->close_scope_sections ();
984    }
985}
986
987/**
988 */
989void SyntaxParser::parse_project_file_text (const cmt_string& text,
990                                            const cmt_string& file_name,
991                                            Project* project)
992{
993  SyntaxParser& me = instance ();
994  me.do_parse_text (text, file_name, project_context, 0, project);
995}
996
997/**
998 *  Parse a text, rejecting comments and
999 * rebuilding complete lines (from sections separated by
1000 *  \ characters.
1001 *
1002 *  Each reformatted line is parsed by filter_line
1003 */
1004void SyntaxParser::parse_requirements_text (const cmt_string& text,
1005                                            const cmt_string& file_name,
1006                                            Use* use)
1007{
1008  SyntaxParser& me = instance ();
1009
1010    /**
1011     *
1012     *    We have to preserve m_current_access since it reflects whether
1013     *   the current cmt action is run in the context of the current package.
1014     *   (the opposite is when the cmt command specifies the current package
1015     *    in its arguments -use=... therefore the pwd is NOT the directory
1016     *    of the current package)
1017     *
1018     *   m_current_access is Developer when pwd =  current
1019     *                       User      when pwd != current
1020     *
1021     *    Therefore, as soon as we reach a used package, this must be switched to User
1022     *
1023     *   On the other hand, Cmt::scope reflects the status of the public/private
1024     *  statements. By default, we are in public context when entering a new requirements
1025     *  file.
1026     *
1027     */
1028
1029  AccessMode saved_current_access;
1030
1031  saved_current_access = Cmt::get_current_access ();
1032
1033  if (use == 0) use = &(Use::current ());
1034
1035  if (use != &(Use::current ()))
1036    {
1037      Cmt::set_current_access (UserMode);
1038    }
1039  else
1040    {
1041      Cmt::set_current_access (DeveloperMode);
1042    }
1043
1044  me.do_parse_text (text, file_name, package_context, use, 0);
1045
1046  Cmt::set_current_access (saved_current_access);
1047}
1048
1049/**
1050 *  Apply the basic parser to one single line :
1051 *
1052 *   o Append to global text if previous back_slash
1053 *   o Split into words
1054 *   o Apply the generic Select operator
1055 */
1056void SyntaxParser::parse_requirements_line (const cmt_string& line,
1057                                            Use* use,
1058                                            const cmt_string& file_name,
1059                                            int line_number)
1060{
1061  SyntaxParser& me = instance ();
1062  me.do_parse_line (line, file_name, line_number, package_context, use, 0);
1063}
1064
1065SyntaxParser::SyntaxParser ()
1066{
1067  m_keywords.add ("action", new KwdAction ());
1068  m_keywords.add ("alias", new KwdAlias ());
1069  m_keywords.add ("application", new KwdApplication ());
1070  m_keywords.add ("apply_pattern", new KwdApplyPattern ());
1071  m_keywords.add ("apply_tag", new KwdApplyTag ());
1072  m_keywords.add ("author", new KwdAuthor ());
1073  m_keywords.add ("branches", new KwdBranches ());
1074  m_keywords.add ("build_strategy", new KwdBuildStrategy ());
1075  m_keywords.add ("cleanup_script", new KwdCleanupScript ());
1076  m_keywords.add ("cmtpath_pattern", new KwdCmtPathPattern ());
1077  m_keywords.add ("document", new KwdDocument ());
1078  m_keywords.add ("end_private", new KwdEndPrivate ());
1079  m_keywords.add ("end_public", new KwdEndPublic ());
1080  m_keywords.add ("ignore_pattern", new KwdIgnorePattern ());
1081  m_keywords.add ("include_dirs", new KwdIncludeDirs ());
1082  m_keywords.add ("include_path", new KwdIncludePath ());
1083  m_keywords.add ("language", new KwdLanguage ());
1084  m_keywords.add ("library", new KwdLibrary ());
1085  m_keywords.add ("macro", new KwdMacro ());
1086  m_keywords.add ("macro+", new KwdMacroAppend ());
1087  m_keywords.add ("macro_prepend", new KwdMacroPrepend ());
1088  m_keywords.add ("macro_append", new KwdMacroAppend ());
1089  m_keywords.add ("macro_remove", new KwdMacroRemove ());
1090  m_keywords.add ("macro_remove_regexp", new KwdMacroRemoveRegexp ());
1091  m_keywords.add ("macro_remove_all", new KwdMacroRemoveAll ());
1092  m_keywords.add ("macro_remove_all_regexp", new KwdMacroRemoveAllRegexp ());
1093  m_keywords.add ("make_fragment", new KwdMakeFragment ());
1094  m_keywords.add ("manager", new KwdManager ());
1095  m_keywords.add ("package", new KwdPackage ());
1096  m_keywords.add ("path", new KwdPath ());
1097  m_keywords.add ("path_append", new KwdPathAppend ());
1098  m_keywords.add ("path_prepend", new KwdPathPrepend ());
1099  m_keywords.add ("path_remove", new KwdPathRemove ());
1100  m_keywords.add ("path_remove_regexp", new KwdPathRemoveRegexp ());
1101  m_keywords.add ("pattern", new KwdPattern ());
1102  m_keywords.add ("public", new KwdPublic ());
1103  m_keywords.add ("private", new KwdPrivate ());
1104  m_keywords.add ("project", new KwdProject ());
1105  m_keywords.add ("set", new KwdSet ());
1106  m_keywords.add ("set_append", new KwdSetAppend ());
1107  m_keywords.add ("set_prepend", new KwdSetPrepend ());
1108  m_keywords.add ("set_remove", new KwdSetRemove ());
1109  m_keywords.add ("set_remove_regexp", new KwdSetRemoveRegexp ());
1110  m_keywords.add ("setup_script", new KwdSetupScript ());
1111  m_keywords.add ("setup_strategy", new KwdSetupStrategy ());
1112  m_keywords.add ("tag", new KwdTag ());
1113  m_keywords.add ("tag_exclude", new KwdTagExclude ());
1114  m_keywords.add ("use", new KwdUse ());
1115  m_keywords.add ("version_strategy", new KwdVersionStrategy ());
1116  m_keywords.add ("version", new KwdVersion ());
1117
1118  m_project_keywords.add ("build_strategy", new KwdBuildStrategy ());
1119  m_project_keywords.add ("project", new KwdProject ());
1120  m_project_keywords.add ("setup_strategy", new KwdSetupStrategy ());
1121}
1122
1123void SyntaxParser::do_parse_requirements (const cmt_string& file_name, Use* use)
1124{
1125  cmt_string actual_file_name = file_name;
1126  cmt_string text;
1127
1128  CmtError::clear ();
1129
1130  if (!CmtSystem::test_file (actual_file_name))
1131    {
1132      actual_file_name = "..";
1133      actual_file_name += CmtSystem::file_separator ();
1134      actual_file_name += "cmt";
1135      actual_file_name += CmtSystem::file_separator ();
1136      actual_file_name += file_name;
1137
1138      if (!CmtSystem::test_file (actual_file_name))
1139        {
1140          actual_file_name = "..";
1141          actual_file_name += CmtSystem::file_separator ();
1142          actual_file_name += "mgr";
1143          actual_file_name += CmtSystem::file_separator ();
1144          actual_file_name += file_name;
1145
1146          if (!CmtSystem::test_file (actual_file_name))
1147            {
1148              return;
1149            }
1150        }
1151    }
1152
1153  text.read (actual_file_name);
1154
1155  SyntaxParser::parse_requirements_text (text, actual_file_name, use);
1156}
1157
1158/**
1159 *  Parse a text, rejecting comments and
1160 * rebuilding complete lines (from sections separated by
1161 *  \ characters.
1162 *
1163 *  Each reformatted line is parsed by filter_line
1164 */
1165void SyntaxParser::do_parse_text (const cmt_string& text,
1166                                  const cmt_string& file_name,
1167                                  ContextType context,
1168                                  Use* use,
1169                                  Project* project)
1170{
1171  cmt_string line;
1172  int pos;
1173  int max_pos;
1174  int line_number = 1;
1175
1176  if (context == package_context)
1177    {
1178      if (use == 0) use = &(Use::current ());
1179    }
1180
1181  m_filtered_text.erase (0);
1182
1183  pos = 0;
1184  max_pos = text.size ();
1185
1186  for (pos = 0; pos < max_pos;)
1187    {
1188      int cr = text.find (pos, "\r\n");
1189      int nl = text.find (pos, '\n');
1190      int first = nl;
1191      int length = 1;
1192
1193      if (cr != cmt_string::npos)
1194        {
1195          if (nl == cmt_string::npos)
1196            {
1197              first = cr;
1198              length = 2;
1199            }
1200          else
1201            {
1202              first = (nl < cr) ? nl : cr;
1203              length = (nl < cr) ? 1 : 2;
1204            }
1205        }
1206
1207      if (first == cmt_string::npos)
1208        {
1209          text.substr (pos, line);
1210          pos = max_pos;
1211        }
1212      else if (first > pos)
1213        {
1214          text.substr (pos, first - pos, line);
1215          pos = first + length;
1216        }
1217      else
1218        {
1219          line.erase (0);
1220          pos += length;
1221        }
1222
1223      do_parse_line (line, file_name, line_number, context, use, project);
1224
1225      if ((Cmt::get_action () == action_check_configuration) && CmtError::has_pending_error ())
1226        {
1227          //break;
1228        }
1229
1230      line_number++;
1231    }
1232}
1233
1234void SyntaxParser::do_parse_line (const cmt_string& line,
1235                                  const cmt_string& file_name,
1236                                  int line_number,
1237                                  ContextType context,
1238                                  Use* use,
1239                                  Project* project)
1240{
1241  int length;
1242  int nl;
1243  int back_slash;
1244  cmt_string temp_line = line;
1245
1246  if (temp_line.size () == 0) return;
1247  if (temp_line[0] == '#') return;
1248
1249  nl = temp_line.find_last_of ('\n');
1250  if (nl != cmt_string::npos) temp_line.erase (nl);
1251
1252  length = temp_line.size ();
1253  if (length == 0) return;
1254
1255  //
1256  // We scan the line for handling backslashes.
1257  //
1258  // o Really terminating backslashes (ie those only followed by spaces/tabs
1259  // mean continued line
1260  //
1261  //
1262
1263  bool finished = true;
1264
1265  length = temp_line.size ();
1266
1267  back_slash = temp_line.find_last_of ('\\');
1268
1269  if (back_slash != cmt_string::npos)
1270    {
1271      //
1272      // This is the last backslash
1273      // check if there are only space chars after it
1274      //
1275     
1276      bool at_end = true;
1277
1278      for (int i = (back_slash + 1); i < length; i++)
1279        {
1280          char c = temp_line[i];
1281          if ((c != ' ') && (c != '\t'))
1282            {
1283              at_end = false;
1284              break;
1285            }
1286        }
1287
1288      if (at_end)
1289        {
1290          temp_line.erase (back_slash);
1291          finished = false;
1292        }
1293      else
1294        {
1295          // This was not a trailing backslash.
1296          finished = true;
1297        }
1298    }
1299
1300  m_filtered_text += temp_line;
1301
1302  if (!finished)
1303    {
1304      // We still need to accumulate forthcoming lines
1305      // before parsing the resulting text.
1306      return;
1307    }
1308
1309  /*
1310    Here a full line (possibly accumulating several lines
1311    ended by backslashes) is parsed :
1312   
1313    o Special characters are filtered now :
1314   
1315    <cmt:tab/>  \t
1316    <cmt:cr/>   \r
1317    <cmt:lf/>   \n
1318   
1319    o Split into words (a word is a string not containing
1320    spaces or enclosed in quotes)
1321
1322    o Parse the word array (function Select)
1323
1324  */
1325
1326  m_filtered_text.replace_all ("<cmt:tab/>", "\t");
1327  m_filtered_text.replace_all ("<cmt:cr/>",  "\r");
1328  m_filtered_text.replace_all ("<cmt:lf/>",  "\n");
1329
1330  if (Cmt::get_debug ())
1331    {
1332      cout << "parse_requirements_line [" << m_filtered_text << "]" << endl;
1333    }
1334 
1335  static CmtSystem::cmt_string_vector words;
1336 
1337  CmtSystem::split (m_filtered_text, " \t", words);
1338 
1339  if (words.size () != 0)
1340    {
1341      switch (context)
1342        {
1343        case project_context:
1344          do_parse_words (words, file_name, line_number, project);
1345          break;
1346        case package_context:
1347          do_parse_words (words, file_name, line_number, use);
1348          break;
1349        }
1350    }
1351 
1352  m_filtered_text.erase (0);
1353}
1354
1355void SyntaxParser::do_parse_words (const CmtSystem::cmt_string_vector& words,
1356                                   const cmt_string& file_name,
1357                                   int line_number,
1358                                   Use* use)
1359{
1360  CmtError::clear ();
1361
1362  if (words.size () == 0) return;
1363
1364  const cmt_string& command = words[0];
1365
1366  if (command.size () == 0) return;
1367
1368  //
1369  // First analyze the syntax
1370  //
1371
1372  Kwd* keyword = m_keywords.find (command);
1373  if (keyword == 0)
1374    {
1375      /*
1376
1377        When the first word of the line is not a keyword, it may be an
1378        implicit pattern application.
1379
1380       */
1381
1382      Pattern* p = Pattern::find (command);
1383      if (p == 0)
1384        {
1385          CmtError::set (CmtError::syntax_error, "ParseRequirements> ");
1386        }
1387      else
1388        {
1389          keyword = m_keywords.find ("apply_pattern");
1390        }
1391    }
1392
1393  if (CmtError::has_pending_error ())
1394    {
1395      if (!Cmt::get_quiet ())
1396        {
1397          cerr << "#CMT> bad syntax in requirements of " << use->get_package_name ()
1398               << " " << use->version
1399               << " " << use->specified_path
1400               << " line #" << line_number;
1401          cerr << " [" << command << " ...]" << endl;
1402        }
1403
1404      return;
1405    }
1406
1407  //
1408  // Then interpret the action
1409  //
1410
1411  keyword->action (words, use, file_name, line_number);
1412}
1413
1414void SyntaxParser::do_parse_words (const CmtSystem::cmt_string_vector& words,
1415                                   const cmt_string& file_name,
1416                                   int line_number,
1417                                   Project* project)
1418{
1419  CmtError::clear ();
1420
1421  if (words.size () == 0) return;
1422
1423  const cmt_string& command = words[0];
1424
1425  if (command.size () == 0) return;
1426
1427  //
1428  // First analyze the syntax
1429  //
1430
1431  Kwd* keyword = m_project_keywords.find (command);
1432  if (keyword == 0)
1433    {
1434      CmtError::set (CmtError::syntax_error, "ParseRequirements> ");
1435    }
1436
1437  if (CmtError::has_pending_error ())
1438    {
1439      if (!Cmt::get_quiet ())
1440        {
1441          cerr << "#CMT> bad syntax in project file of " << project->get_name ()
1442               << " line #" << line_number;
1443          cerr << " [" << command << " ...]" << endl;
1444        }
1445
1446      return;
1447    }
1448
1449  //
1450  // Then interpret the action
1451  //
1452
1453  keyword->action (words, project, file_name, line_number);
1454}
1455
1456
1457
1458
Note: See TracBrowser for help on using the repository browser.