source: CMT/v1r18p20060606/source/cmt_syntax.cxx

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

Add structure_strategy - see CL#278

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